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

私が抱えている問題は2つあります。1つは、正規表現番号"^[0-9]*(\.[0-9]+)?"がこのエラーをスローすることです。

文字'['での文字列/文字リテラルの字句エラー

そして、それを含む行とそれを使用する関数の一部をコメントアウトすると、次のエラーが発生します。

期待されるタイプの「トークン」と一致しませんでした
           推論された型`(String、String)'に対して
      予想されるタイプ:[トークン]
      推測されるタイプ:[(String、String)]
    式内:lex(drop(長さトークン)s)
    式では:
        トークン=s=〜空白::文字列
        lexで(ドロップ(長さトークン)s)

なぜこれらのエラーのいずれかが発生するのかわかりません。誰かが私を助けることができますか?

4

2 に答える 2

7

バックスラッシュは"\n"、改行を含む文字列の場合のように、文字列リテラルのエスケープ文字として使用されます。文字通りの円記号が必要な場合は、としてエスケープする必要があります"\\"。これが正規表現の問題です"^[0-9]*(\.[0-9]+)?"。Haskellパーサーは通常の文字列エスケープとして解釈しようとし"\."、それをチョークします(おそらくそのようなエスケープがないためです)。"^[0-9]*(\\.[0-9]+)?"エラーが消えるときに正規表現を書き込む場合。

タイプの問題の理由は、タイプがの標準のプレリュードから呼び出すためlexです。おそらく、代わりに自分の関数を再帰的に呼び出したいと思ったでしょう...lex (drop (length token) s)String -> [(String, String)]lexer

于 2009-10-20T01:27:16.270 に答える
2

また、これは空の文字列または.12(0.12ではなく)のような数字と一致することに注意して"^[0-9]*(\\.[0-9]+)?"ください。これはおそらく望ましくありません。関数がそれ自体を無限に呼び出す原因になるため、これは深刻な問題です。これを修正するには、*を+に変更します。

于 2011-04-29T20:14:14.883 に答える