如何处理可选的尾随逗号?

时间:2016-11-03 02:43:32

标签: f# fparsec

给出以下

let maxCount = System.Int32.MaxValue
let pmlcomment = pstring "/*" >>. skipCharsTillString "*/" true (maxCount)
let ws = pspaces >>. many (pspaces >>. pmlcomment .>> pspaces) |>> (function | [] -> () | _ -> ())
let str_ws s = pstring s .>> ws
let exprBraceSeqOpt p =
    let trailingComma = (str_ws "," |>> fun _ -> None )
    between (str_ws "{") (str_ws "}") ((opt (attempt (sepBy p (str_ws ",")))) <|> (attempt trailingComma))
let sampleP = exprBraceSeqOpt (str_ws "x")

它正确匹配除最后一个之外的所有以下内容:

["{}";"{x}";"{x,x}";"{x,x,}"]

我猜测某些东西正在改变这种状态。

如何在fparsec中处理可选的尾随逗号?

1 个答案:

答案 0 :(得分:4)

sepBy&#34;吃掉&#34;额外的分隔符,如果它存在。这就是它的运作方式。您不能通过在各个地方应用attempt来破解它:如果您将attempt应用于分隔符,则无法提供帮助,因为最后一个分隔符实际上已成功,因此attempt将具有没有效果。将attempt应用于整个sepBy也无济于事,因为整个sepBy将被回滚,而不仅仅是最后一个分隔符。并将attempt应用于&#34; x&#34;解析器本身在实现所需的尾随逗号行为时,也会产生使解析器连续接受多个逗号的不利影响。

因为通过巧妙使用组合器无法达到预期的效果,实际上有一个特殊的功能可以完成你之后的事情 - sepEndBy

这可以按预期工作:

let exprBraceSeqOpt p =
    between (str_ws "{") (str_ws "}") (sepEndBy p (str_ws ","))

另外,除此之外,我应该指出function | [] -> () | _ -> ()是一种非常精细的方式ignore。 : - )

相关问题