3

なぜこれが失敗するのですか?

data Value = Num Integer
           | Str String

let numberOrString = (liftM Num (try int) <|> liftM Str (many1 (noneOf " "))
parse (numberOrString >> space)  "" "123-4 "

>> spaceが必要です。それ以外の場合、パーサーは後に停止します123

期待される結果:

parse numberOrString "" "1234"
-> Num 1234

parse numberOrString "" "12-34"
-> Str "12-34"

結果:

parse numberOrString "" "1234-34 "
-> Left (line 1, column 5):
   unexpected "-"
   expecting digit or space
4

1 に答える 1

4

パーサーコンビネーターの定義は与えていませんが、int基本的には 1 つ以上の数字が必要であり、オプションで前に「-」が付いていると仮定しましょう (ただし、前だけです!)。numberOrStringそれでは、パーサーについて説明しましょう。

整数リテラルを解析するか、それが失敗すると、スペース以外の文字列を解析します。サンプル文字列では、パーサーの最初のブランチは成功します。これは、数字の文字列が表示されるためです。「-」文字は数字ではないため、文字の直前で停止します。numberOrString >> space数字の後に次の文字がスペースであると予想されるため、失敗しますが、「-」はそうではありません。

基本的に、パーサーを2 つの整数リテラル (1 つは正の値、もう 1 つは負の値) (または文法によっては「-」で区切られた 2 つの正のリテラル) の文字列に適用しました。numberOfStringこれは、パーサーを単独で適用しても "1234" しか消費されない理由でもあります。これは、パーサーが解析できる最大の整数リテラルだからです。

編集:私があなたが望んでいるtry intのは、ほとんどが数字の文字列に数字以外の文字がある場合に失敗することです。繰り返しますが、これは実際には の定義に依存しますがint、おそらく、アルファベット文字が続かない少なくとも 1 桁の文字列で成功するパーサーとして定義されています。の通常の定義はint、2 つの整数リテラルと中置演算子の間のスペースがオプションになるため、間にスペース文字がなくても、数字の文字列の後に "-" などの英数字以外の文字が続く場合に成功します。また、「123 )」と書かなくても、「123)」を正しく解析できます。

于 2012-09-28T15:46:23.410 に答える