Próbuję parsować standardowe typy proste (w znaczeniu rachunku lambda) przy użyciu FParsec, ale mam trudności z przechodzeniem od stylu Lex/Yacc do tego używanego w FParsec, szczególnie z szacunkiem do definicji rekursywnych.Parsowanie prostych typów w FParsec
Przykłady typów Staram się analizować to:
- o
- O -> O
- (O -> O -> O) -> O
A oto moja próba:
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"`
Kiedy ładuję to do interakcji ve ostatnia linia powoduje przepełnienie stosu (ironicznie dość trudne do wyszukania w tych dniach). Mogę sobie wyobrazić, dlaczego, biorąc pod uwagę, że istnieją referencje rekursywne, ale przypuszczam, że przewinięcie z jednym znacznikiem uniemożliwiłoby dokonanie pierwszego (w nawiasie) wyboru w stype
. Zakładam więc, że musi to być wybór arr
, który wybiera stype
i tak dalej. Ale jak zapobiec tej pętli?
Interesują mnie komentarze na temat idiomatycznego wykorzystania biblioteki, a także poprawki do mojego rozwiązania.
To może być chcesz chcesz: http://stackoverflow.com/questions/6186230/recursive-grammars-in-fparsec –
Dzięki, mam czytać to pytanie/odpowiedź, ale nie bardzo rozumiem, jak przenieść odpowiedź na mój problem. Ale będę miał inne spojrzenie. – rneatherway