如果 "till" 解析器以空格开头,为什么 manyCharsTill 组合子不起作用?
Why doesn't manyCharsTill combinator work if the "till" parser starts with spaces?
我尝试解析类似 xml 的标签(但不是正确的 xml 文档..):
目标是只返回 "Flange width",没有开头或结尾的白色 space,但有内部的。
open FParsec
let testParser =
pstring "<desc>" .>>. spaces
>>. manyCharsTill anyChar (spaces .>>. pstring "</desc>")
run testParser "<desc> Flange width </desc>"
如果我理解解析器组合器的预期结果:
anyChar 解析器保持吞咽字符单元 "till" 解析器查找 spaces 后跟结束标记成功。
实际发生的是,"till" 解析器在 "width" 之前的 space 上失败(它应该如此)但是短路 manyTill 解析器而不是让 anyChar 吞下 space 并继续前进。
输出:
val it : ParserResult<string,unit> =
Failure:
Error in Ln: 1 Col: 15
<desc> Flange width </desc>
^
Expecting: '</desc>'
我没有得到什么?或者这里的惯用解决方案是什么?
问题是 spaces
成功解析并将流移动到 w
的开头。 pstring "</desc>"
然后失败。
最终结果是 endp
解析器失败了,但是它 改变了状态 (我们已经过了 space) .您希望解析器失败并且 不 更改状态(在 space 之前)。 manyTill
(which are referred to by manyCharsTill
) 的文档解释了这一点:
The parser manyTill p endp
repeatedly applies the parser p
for as long as endp
fails (without changing the parser state).
您可以使用 .>>.?
operator:
The parser p1 .>>.? p2
behaves like p1 .>>. p2
, except that it will backtrack to the beginning if p2
fails with a non‐fatal error and without changing the parser state, even if p1
has changed the parser state.
因此改为:
let testParser =
pstring "<desc>" .>>. spaces
>>. manyCharsTill anyChar (spaces .>>.? pstring "</desc>")
有关工作演示,请参阅 this fiddle。
我尝试解析类似 xml 的标签(但不是正确的 xml 文档..): 目标是只返回 "Flange width",没有开头或结尾的白色 space,但有内部的。
open FParsec
let testParser =
pstring "<desc>" .>>. spaces
>>. manyCharsTill anyChar (spaces .>>. pstring "</desc>")
run testParser "<desc> Flange width </desc>"
如果我理解解析器组合器的预期结果:
anyChar 解析器保持吞咽字符单元 "till" 解析器查找 spaces 后跟结束标记成功。
实际发生的是,"till" 解析器在 "width" 之前的 space 上失败(它应该如此)但是短路 manyTill 解析器而不是让 anyChar 吞下 space 并继续前进。
输出:
val it : ParserResult<string,unit> =
Failure:
Error in Ln: 1 Col: 15
<desc> Flange width </desc>
^
Expecting: '</desc>'
我没有得到什么?或者这里的惯用解决方案是什么?
问题是 spaces
成功解析并将流移动到 w
的开头。 pstring "</desc>"
然后失败。
最终结果是 endp
解析器失败了,但是它 改变了状态 (我们已经过了 space) .您希望解析器失败并且 不 更改状态(在 space 之前)。 manyTill
(which are referred to by 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。