4

我正在为这种形式的字符串编写 FParsec 解析器:

do[ n times]([ action] | \n([action]\n)*endDo)

换句话说,这是一个带有可选时间量词的“do”语句,或者是一个单独的“action”语句或一个“action”列表(每个都在一个新行上),最后有一个“end do”(我为简单起见省略了缩进/尾随空格处理)。

这些是有效输入的示例:

do action

do 3 times action

do
endDo

do 3 times
endDo

do
action
action
endDo

do 3 times
action
action
endDo

这看起来不是很复杂,但是:

为什么这不起作用?

let statement = pstring "action"
let beginDo = pstring "do"
                >>. opt (spaces1 >>. pint32 .>> spaces1 .>> pstring "times")
let inlineDo = tuple2 beginDo (spaces >>. statement |>> fun w -> [w])
let expandedDo = (tuple2 (beginDo .>> newline)
                    (many (statement .>> newline)))
                 .>> pstring "endDo"
let doExpression = (expandedDo <|> inlineDo)

这个表达式的正确解析器是什么?

4

1 回答 1

6

您需要使用该attempt功能。我刚刚修改了你的beginDodoExpression功能。

这是代码:

let statement  o=o|>  pstring "action"

let beginDo o= 
    attempt (pstring "do"
        >>. opt (spaces1 >>. pint32 .>> spaces1 .>> pstring "times")) <|> 
        (pstring "do" >>% None)                                       <|o

let inlineDo   o= tuple2 beginDo (spaces >>. statement |>> fun w -> [w]) <|o
let expandedDo o= (tuple2 (beginDo .>> newline) (many (statement .>> newline)))
                 .>> pstring "endDo" <|o

let doExpression o= ((attempt expandedDo) <|> inlineDo) .>> eof <|o

eof在最后加了一个。这样会更容易测试。

我还添加了虚拟o参数以避免值限制。

于 2011-12-16T14:52:54.353 回答