Haskell 中的 Lexer - 如何模式匹配特定案例?

Lexer in Haskell - How to Pattern Match specific case?

我目前正在研究用 Haskell 编写的词法分析器,快完成了,但是 运行 遇到了一个特殊情况标记的问题。目前,我的词法分析器接受一个输入字符串并将语句分解为数字标记、变量名和特定标记,例如 "if"、"else" 和 "then"。

除了“000...”之外,它对我的​​所有标记都非常有效。

我被教导使用 span 函数,所以我让我的词法分析器使用 isDigit 和 isAlphaNum 布尔函数来解析输入。但是,因为“000...”以零开头,它会自动 returns 作为数字。此外,句点也是语法中的标记,因此在我的词法分析器中输入“000 ...”的结果当前为“0”“。” “。” “.”。

我不精通Haskell的语言,但是否可以使用isPrint来匹配一个字符串,并用case来处理字符串和整数的实例?我现在不知所措,似乎我尝试过的一切都破坏了我的程序。我当前的模式匹配部分如下所示:

lexer (c:cs)
| isSpace c = lexer cs
| isDigit c = lexDigit (c:cs)
| isAlphaNum c = lexString (c:cs)
| True = InvalidToken c : lexer cs

lexString 
| s1 == "if" = IfToken : lexer s2 
| s1 == "else" = ElseToken : lexer s2 
| s1 == "then" = ThenToken : lexer s2 
| s1 == "000..." = Zero : lexer s2
| True = StringToken s1 : lexer s2 
where (s1,s2) = (span isAlphaNum cs)

欢迎任何帮助!

首先请注意,在 Haskell 中处理此类任务的惯用方法是使用 解析器组合器库 ,例如 parsec. (It may make sense to go the traditional parser/lexer route for some applications, but this isn't really something you should code by hand – use a lexer generator, i.e. alex。)

现在,如果您决定手动执行此操作,并且没有更具表现力的解析器组合器...您将需要在 lexDigit 中处理这种特殊情况,而不是 lexString:

lexDigit :: String -> [Token] -- Always use type signatures!
lexDigit cs
  | ("000...",s2) <- splitAt 6 cs  = Zero : lexer s2
lexDigit cs = ... -- your original definition of `lexDigit`

lexString :: String -> [Token]
lexString cs = case s1 of
  "if"   -> IfToken : lexer s2 
  "else" -> ElseToken : lexer s2 
  "then" -> ThenToken : lexer s2
  -- no clause for "000...", since it can't happen here anyway
  _      -> StringToken s1 : lexer s2 
 where (s1,s2) = (span isAlphaNum cs)

lexer :: String -> [Token]
lexer cs@(c:cs')
  | isSpace c    = lexer cs'
  | isDigit c    = lexDigit cs
  | isAlphaNum c = lexString cs
  | otherwise    = InvalidToken c : lexer cs'