我尝试解析类似xml的标签(但不是正确的xml文档。): 目标是只返回“法兰宽度”,而没有开头或结尾的空格,而是内部空格。
open FParsec
let testParser =
pstring "<desc>" .>>. spaces
>>. manyCharsTill anyChar (spaces .>>. pstring "</desc>")
run testParser "<desc> Flange width </desc>"
如果我了解解析器组合器,则将获得预期结果:
anyChar解析器可以继续吞下char单元,而“ till”解析器会先查找空格,后跟end标记。
实际上发生的是,“耕种”解析器在“宽度”之前的空间上失败了(应该如此),但使manyTill解析器短路了,而不是让anyChar吞噬了该空间并继续。
输出:
val it : ParserResult<string,unit> =
Failure:
Error in Ln: 1 Col: 15
<desc> Flange width </desc>
^
Expecting: '</desc>'
我没有得到什么?还是这里的惯用解决方案?
答案 0 :(得分:4)
问题是spaces
成功解析并将流移到w
的开头。 pstring "</desc>"
然后失败。
最终结果是endp
解析器失败,但是它更改了状态(我们已经移过空格了)。您希望解析器失败,并且不更改状态(在空格之前)。 manyTill
(由manyCharsTill
引用)的文档对此进行了解释:
只要
manyTill p endp
失败(不更改解析器状态),解析器p
就会反复应用解析器endp
。
您可以使用.>>.?
operator:
解析器
p1 .>>.? p2
的行为与p1 .>>. p2
相似,不同之处在于,如果p2
因非致命错误而失败并且不更改解析器状态,即使{{{ 1}}更改了解析器状态。
因此,这是
p1
有关有效的演示,请参见this fiddle。