F# 为什么';t如果;直到;解析器从空格开始?
我尝试解析类似xml的标记(但不是正确的xml文档..): 我们的目标是只返回“凸缘宽度”,不带开头或尾随空格,而是带内部空格F# 为什么';t如果;直到;解析器从空格开始?,f#,parser-combinators,fparsec,F#,Parser Combinators,Fparsec,我尝试解析类似xml的标记(但不是正确的xml文档..): 我们的目标是只返回“凸缘宽度”,不带开头或尾随空格,而是带内部空格 open FParsec let testParser = pstring "<desc>" .>>. spaces >>. manyCharsTill anyChar (spaces .>>. pstring "</desc>") run testParser "<desc>
open FParsec
let testParser =
pstring "<desc>" .>>. spaces
>>. manyCharsTill anyChar (spaces .>>. pstring "</desc>")
run testParser "<desc> Flange width </desc>"
打开FParsec
让testParser=
pstring“>>。空间
>>. manyCharsTill anyChar(空格>.pstring“”)
运行testParser“法兰宽度”
如果我理解解析器组合符,那么预期结果是:
anyChar解析器继续吞咽字符的单元是“直到”解析器,它查找结尾标记后面的空格
实际发生的情况是,“直到”解析器在“宽度”之前的空格上失败(应该如此),但会使manyTill解析器短路,而不是让anyChar吞下该空格并继续
输出:
val it : ParserResult<string,unit> =
Failure:
Error in Ln: 1 Col: 15
<desc> Flange width </desc>
^
Expecting: '</desc>'
valit:ParserResult=
失败:
Ln:1列中的错误:15
凸缘宽度
^
应为:“”
我没有得到什么?或者,这里的惯用解决方案是什么?问题是
空格
成功解析并将流移动到w
的开头<代码>pstring“”然后失败
最终的结果是endp
解析器失败,但它已经改变了状态(我们已经移动过了空格)。您希望解析器失败并且不更改状态(在空格之前)。相关文件(参见)对此进行了解释:
只要endp
失败(不改变解析器状态),解析器manyTill p endp
就会重复应用解析器p
您可以使用以下命令来执行此操作:
解析器p1.>>。?p2的行为与p1类似。p2
,但如果p2
因非致命错误而失败且未更改解析器状态,即使p1
更改了解析器状态,它也会返回到开始
因此,取而代之的是:
let testParser=
pstring“>>。空间
>>. manyCharsTill anyChar(空格>>?pstring“”)
请参阅一个有效的演示。作为旁注,我还发现仅仅做
|>>有趣的(s:string)->s.Trim()
有时比跳过空白更容易,甚至更快。