FParsecを使用して標準的な単純型(ラムダ計算の意味で)を解析しようとしていますが、FParsecで使用されているLex/Yacc形式から、再帰的な定義に。私が解析しようとしているタイプのFParsecの単純型の解析
例は次の通りである:
- - > O
- (O - > O - > O) - > O
そして、ここに私の試みがあります:
type SType =
| Atom
| Arrow of SType * SType
let ws = spaces
let stype, styperef = createParserForwardedToRef()
let atom = pchar 'o' .>> ws |>> (fun _ -> Atom)
let arrow = pipe2 (stype .>> (pstring "->" .>> ws))
stype
(fun t1 t2 -> Arrow (t1,t2))
let arr = parse {
let! t1 = stype
do! ws
let! _ = pstring "->"
let! t2 = stype
do! ws
return Arrow (t1,t2)
}
styperef := choice [ pchar '(' >>. stype .>> pchar ')';
arr;
atom ]
let _ = run stype "o -> o"`
これをインタラクティブにロードすると最後の行はスタックオーバーフローを引き起こします(皮肉なことに、これらの日を検索するのは非常に困難です)。なぜ再帰的な参照があるのか想像することができますが、先読みの1トークンがstype
の最初の(括弧で囲まれた)選択に続くのを防ぐことができたと思います。したがって、arr
を選択する必要があります。これはstype
などを選択します。しかし、このループを防ぐ方法は?
私は、ライブラリの慣用的な使用についてのコメントだけでなく、試行した解決策への修正にも興味があります。
:http://stackoverflow.com/questions/6186230/recursive-grammars-in-fparsec –
おかげで、私が読んでいるあなたのケースでは、たとえば
sepBy1
コンビネータを使用することができますその質問/回答、しかし私はかなり私の問題に答えを引き継ぐ方法を見ることはできません。私はもう一度見ていきます。 – rneatherway