【问题标题】:Haskell lexer problemsHaskell 词法分析器问题
【发布时间】:2009-10-20 00:43:19
【问题描述】:

我正在用haskell 编写一个词法分析器。代码如下:

lexer :: String -> [Token]
lexer s
    | s =~ whitespace :: Bool =
        let token = s =~ whitespace :: String in
            lex (drop (length token) s)
    | s =~ number :: Bool =
        let token = s =~ number :: String in
            Val (read token) : lex (drop (length token) s)
    | s =~ operator :: Bool =
        let token = s =~ operator :: String in
            Oper token : lex (drop (length token) s)
    | otherwise = error "unrecognized character"
    where
        whitespace = "^[ \t\n]"
        number = "^[0-9]*(\.[0-9]+)?"
        operator = "^[+-*/()]"

data Token = Val Int | Oper String

我遇到了两个问题。一、数字正则表达式"^[0-9]*(\.[0-9]+)?"抛出这个错误:

字符'['处的字符串/字符文字中的词法错误

当我注释掉包含它的行和使用它的函数部分时,我得到这个错误:

无法匹配预期类型“令牌”
           针对推断类型 `(String, String)'
      预期类型:[令牌]
      推断类型:[(String, String)]
    在表达式中: lex (drop (length token) s)
    在表达式中:
        让 token = s =~ 空格 :: String
        in lex (drop (length token) s)

我不知道为什么会出现这些错误。有人可以帮我吗?

【问题讨论】:

    标签: haskell types lexer


    【解决方案1】:

    反斜杠在字符串文字中用作转义字符,例如在"\n" 中用于包含换行符的字符串。如果你想要一个文字反斜杠,你需要将它转义为"\\"。 这就是正则表达式"^[0-9]*(\.[0-9]+)?" 中的问题,Haskell 解析器试图将"\." 解释为正常的字符串转义并阻塞它(可能是因为没有这样的转义)。如果您将正则表达式写为"^[0-9]*(\\.[0-9]+)?",错误就会消失。

    类型问题的原因是您从lex (drop (length token) s) 中的标准Prelude 中调用lex,它的类型为String -> [(String, String)]。可能您想对自己的函数 lexer 进行递归调用...

    【讨论】:

      【解决方案2】:

      另外,请注意"^[0-9]*(\\.[0-9]+)?" 匹配空字符串或数字,如 0.12(而不是 0.12),您可能不希望这样。这是一个严重的问题,因为它会导致您的函数无限调用自身。要解决此问题,请将 * 更改为 +。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-17
        • 1970-01-01
        相关资源
        最近更新 更多