我正在尝试为Haskell模块构建一个main函数,该模块将从用户处获取正则表达式并在SimplifyRegExp函数中使用它,但这需要RegExp类型的输入:
data RegExp sy = Empty
| Epsilon
| Literal sy
| Or (RegExp sy) (RegExp sy)
| Then (RegExp sy) (RegExp sy)
| Star (RegExp sy)
deriving (Read, Eq)
我如何能够将字符串转换为RegExp类型?
如果我将程序加载到GHCi上,那么我可以直接调用该方法,如下所示:
*Language.HaLex.RegExp> simplifyRegExp(Star (Star a))
'a'*
但是我想这样做,所以我可以在命令提示符中只传递一个参数的程序,它会打印出类似下面的结果(当然没有工作):
main = do
n <- getArgs $ head
print (simplifyRegExp(n))
答案 0 :(得分:2)
您可以为您的类型定义Read
实例并使用
data RegEx sy = ...
deriving Read
然后使用readMay
import Text.Read
...
main = do
regexp <- (readMay . head) `fmap` getArgs
case regexp of
Just r -> ...
Nothing -> putStrLn "Parse error!"
但这在两个方面有点脆弱。首先是read
是部分功能!如果正则表达式生成错误,您的程序将会爆炸。其次,使用您的默认read
实例强制您的正则表达式的内部表示形式到您的用户!如果这是一个严肃的项目,你最好做一些实际的解析。
幸运的是,Haskell有一些非常棒的解析库。一些最着名的包括parsec和attoparsec。
parsec解析器的示例可能是
import Text.Parsec
import Text.Parsec.String
import Control.Applicative
parseStar :: Parsec (RegExp Char)
parseStar = Star <$> (parseRe <* char '*')
parseLiteral :: Parsec (RegExp Char)
parseLiteral = Literal <$> noneOf "*()"
parseOr :: Parsec (RegExp Char)
parseOr = Or <$> parseRe <*> (char '|' *> parseRe)
parseThen :: Parsec (RegExp Char)
parseThen = Then <$> parseRe <*> parseRe
....