使用FPARSEC,当解析器失败时是否可以操纵误差位置?
作为示例,我将采用 Phillip Trelford 的简单的 C# 解析器。为了解析标识符,他这样写(稍作修改):
let reserved = ["for";"do"; "while";"if";"switch";"case";"default";"break" (*;...*)]
let pidentifierraw =
let isIdentifierFirstChar c = isLetter c || c = '_'
let isIdentifierChar c = isLetter c || isDigit c || c = '_'
many1Satisfy2L isIdentifierFirstChar isIdentifierChar "identifier"
let pidentifier =
pidentifierraw
>>= fun s ->
if reserved |> List.exists ((=) s) then fail "keyword instead of identifier"
else preturn s
pidentifier 的问题是,当它失败时,位置指示器位于流的末尾。我的一个例子:
Error in Ln: 156 Col: 41 (UTF16-Col: 34)
Block "main" 116x60 font=default fg=textForeground
^
Note: The column count assumes a tab stop distance of 8 chars.
keyword instead of identifier
显然,不是 C# 代码片段,但为了示例起见,我使用 pidentifier
来解析 font=
之后的文本。是否可以告诉 FParsec 在解析输入的开头显示错误?使用 >>?
、.>>.?
或任何回溯变体似乎没有效果。
As an example, I will take this simple C# parser by Phillip Trelford. In order to parse an identifier he writes this (slightly changed):
let reserved = ["for";"do"; "while";"if";"switch";"case";"default";"break" (*;...*)]
let pidentifierraw =
let isIdentifierFirstChar c = isLetter c || c = '_'
let isIdentifierChar c = isLetter c || isDigit c || c = '_'
many1Satisfy2L isIdentifierFirstChar isIdentifierChar "identifier"
let pidentifier =
pidentifierraw
>>= fun s ->
if reserved |> List.exists ((=) s) then fail "keyword instead of identifier"
else preturn s
The problem with pidentifier is that when it fails, the position indicator is at the end of the stream. An example of mine:
Error in Ln: 156 Col: 41 (UTF16-Col: 34)
Block "main" 116x60 font=default fg=textForeground
^
Note: The column count assumes a tab stop distance of 8 chars.
keyword instead of identifier
Obviously, not a C# snippet, but for the example's sake, I've used the pidentifier
to parse the text after font=
. Is it possible to tell FParsec to show the error at the beginning of the parsed input? Using >>?
, .>>.?
or any of the backtracking variants seems to have no effect.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为你想要的是
attempt p
< /a>,如果解析器p
失败,它将回溯到原始解析器状态。因此,您可以将pidentifier
定义为:输出类似于:
Update
如果您不想在错误消息中看到回溯信息,您可以使用
attempt< 的简化版本/code>,像这样:
输出现在只是:
I think what you want is
attempt p
, which will backtrack to the original parser state if parserp
fails. So you could just definepidentifier
as:Output is then something like:
Update
If you don't want to see the backtracking info in the error message, you can use a simplified version of
attempt
, like this:Output is now just:
不幸的是,我错过了&gt;&gt; =? 操作员显然(至少在语义上)等于
尝试
Brian Berns正确建议。这两种方法的问题是随后的消息
在以下方式回溯:[…]
,如果前面的解析器也在回溯:Unfortunately I missed the
>>=?
operator which apparently is (at least semantically) equivalent toattempt
that Brian Berns correctly suggested.The problem with both of these approaches is the subsequent messages
The parser backtracked after:[…]
that can cascade if the preceding parsers are backtracking as well: