我尝试解析类似 xml 的标签(但不是正确的 xml 文档..):
目标是在没有开头或结尾空格的情况下返回“法兰宽度”,而是使用内部空格。
open FParsec
let testParser =
pstring "<desc>" .>>. spaces
>>. manyCharsTill anyChar (spaces .>>. pstring "</desc>")
run testParser "<desc> Flange width </desc>"
如果我理解解析器组合器的预期结果:
保持吞下字符的 anyChar 解析器单元“直到”解析器,它寻找空格,然后是结束标记成功。
实际发生的情况是,“直到”解析器在“宽度”之前的空间上失败(应该如此),但会使 manyTill 解析器短路,而不是让 anyChar 吞下该空间并继续前进。
输出:
val it : ParserResult<string,unit> =
Failure:
Error in Ln: 1 Col: 15
<desc> Flange width </desc>
^
Expecting: '</desc>'
我没有得到什么?或者这里的惯用解决方案是什么?
最佳答案
问题是spaces
解析成功并将流移动到 w
的开头. pstring "</desc>"
然后失败。
最终结果是endp
解析器失败了,但它改变了状态(我们已经移过了空格)。您希望解析器失败并且不更改状态(在空格之前)。 manyTill
的文档(由 manyCharsTill
引用)解释一下:
The parser
manyTill p endp
repeatedly applies the parserp
for as long asendp
fails (without changing the parser state).
您可以使用
.>>.?
operator 来做到这一点。 :The parser
p1 .>>.? p2
behaves likep1 .>>. p2
, except that it will backtrack to the beginning ifp2
fails with a non‐fatal error and without changing the parser state, even ifp1
has changed the parser state.
所以这个:
let testParser =
pstring "<desc>" .>>. spaces
>>. manyCharsTill anyChar (spaces .>>.? pstring "</desc>")
见 this fiddle用于工作演示。
关于f# - 如果 "till"解析器以空格开头,为什么 manyCharsTill 组合器不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57291144/