【发布时间】:2011-07-20 15:00:09
【问题描述】:
我正在尝试使用 FParsec 解析标准的简单类型(在 lambda 演算的意义上),但是我很难从 Lex/Yacc 样式转换为 FParsec 中使用的样式,特别是在递归定义方面。
我尝试解析的类型示例如下:
- o
- o -> 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"`
当我将它加载到交互中时,最后一行会导致堆栈溢出(具有讽刺意味的是,这些天很难搜索)。鉴于存在递归引用,我可以想象为什么,但我会认为一个标记前瞻会阻止遵循stype 中的第一个(括号中的)选择。因此我假设它必须选择arr,它选择stype,依此类推。但是如何防止这种循环呢?
我对 cmets 关于库的惯用用法以及对我尝试的解决方案的更正感兴趣。
【问题讨论】:
-
谢谢,我已经阅读了那个问题/回复,但我不太明白如何继续回答我的问题。不过我会再看看。