给出以下
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中处理可选的尾随逗号?
答案 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
。 : - )