0

我正在用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
        在 lex (drop (length token) s)

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

4

2 回答 2

7

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

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

于 2009-10-20T01:27:16.270 回答
2

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

于 2011-04-29T20:14:14.883 回答