F# 型の構文を解析しようとしています。[F]Parsec 文法を書き始めて問題が発生したので、文法を次のように単純化しました。
type ::= identifier | type -> type
identifier ::= [A-Za-z0-9.`]+
FParsec で問題が発生した後、私は Parsec に切り替えました。なぜなら、私はそれを説明するための本の完全な章を持っているからです。この文法の私のコードは
typeP = choice [identP, arrowP]
identP = do
id <- many1 (digit <|> letter <|> char '.' <|> char '`')
-- more complicated code here later
return id
arrowP = do
domain <- typeP
string "->"
range <- typeP
return $ "("++domain++" -> "++range++")"
run = parse (do t <- typeP
eof
return t) "F# type syntax"
問題は、Parsec がデフォルトでバックトラックしないことです。
> run "int"
Right "int"
-- works!
> run "int->int"
Left "F# type syntax"
unexpected "-"
expecting digit, letter, ".", "`" or end of input
-- doesn't work!
私が最初に試みたのは、typeP の順序を変更することでした。
typeP = choice [arrowP, identP]
しかし、文法が左再帰であるため、これは単なるスタック オーバーフローidentP
ですarrowP
。次に、さまざまな場所で試しtry
ました。たとえば、
typeP = choice [try identP, arrowP]
しかし、(1)スタックオーバーフローまたは(2)識別子に続く「->」の非認識の基本的な動作を変更することは何もないようです。
私の間違いは、Parsec 文法の記述に成功した人なら誰にでも明らかです。誰かがそれを指摘できますか?