【问题标题】:Lexer in Haskell - How to Pattern Match specific case?Haskell 中的 Lexer - 如何对特定情况进行模式匹配?
【发布时间】:2015-10-10 18:01:51
【问题描述】:

我目前正在开发一个用 Haskell 编写的词法分析器,几乎完成了,但遇到了一个特殊情况标记的问题。目前,我的词法分析器采用输入字符串并将语句分解为数字、变量名和特定标记(例如“if”、“else”和“then”)的标记。

它适用于我所有的令牌,除了一个“000 ...”。

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

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

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)

感谢任何帮助!

【问题讨论】:

    标签: html haskell design-patterns token matching


    【解决方案1】:

    首先请注意,在 Haskell 中处理此类任务的惯用方法是使用 解析器组合库,例如 parsec(对于某些应用程序,采用传统的解析器/词法分析器路线可能是有意义的,但这并不是你应该手动编码的东西——使用词法分析器生成器,即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'
    

    【讨论】:

    • 谢谢,你是一个活生生的救星!是的,我不允许为此使用任何库,我对 Haskell 的了解可以通过他们网站上的 5 分钟教程和一些关于模式匹配的阅读来总结。干杯!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多