Rebol Parse中匹配时出现错误消息失败

Eri*_*ick 7 error-handling parsing rebol peg

基于PEG的解析器生成器通常在无效输入上提供有限的错误报告.从我读到的,重新解析的解析方言的灵感来自用正则表达式扩展的PEG语法.

例如,在JavaScript中键入以下内容:

d8> function () {}
Run Code Online (Sandbox Code Playgroud)

给出以下错误,因为在声明全局函数时未提供标识符:

(d8):1: SyntaxError: Unexpected token (
function () {}
         ^
Run Code Online (Sandbox Code Playgroud)

解析器能够在解析预期令牌丢失的位置精确定位.预期令牌的字符位置用于将箭头定位在错误消息中.

rebol中的解析方言是否提供了内置工具来报告无效输入上的行和列错误?

否则,是否存在提供此类错误报告的自定义推出解析规则的示例?

mol*_*iad 7

我已经完成了非常先进的Rebol解析器,它可以管理实时和任务关键型TCP服务器,并且需要进行适当的错误报告.所以这很重要!

Rebol PARSE最独特的一个方面可能是您可以在规则中包含直接评估.因此,您可以设置变量来跟踪解析位置或错误消息等. (这很简单,因为Rebol的本质是将代码和数据混合在一起是一个核心思想.)

所以这就是我做的方式.在尝试每个匹配规则之前,我将解析位置保存到"here"(通过写入here:),然后使用代码执行将错误保存到变量中(通过放入(error: {some error string})括号使得解析方言运行它).如果匹配规则成功,我们不需要使用错误或位置......我们只是继续下一个规则.但是如果它失败了,我们将在失败后设置我们设置的最后一个状态.

因此,解析方言中的模式很简单:

; use PARSE dialect handling of "set-word!" instances to save parse
; position into variable named "here"

here:

; escape out of the parse dialect using parentheses, and into the DO 
; dialect to run arbitrary code.  Here we run code that saves an error
; message string into a variable named "error"

(error: "<some error message relating to rule that follows>")

; back into the PARSE dialect again, express whatever your rule is,
; and if it fails then we will have the above to use in error reporting

what: (ever your) [rule | {is}]
Run Code Online (Sandbox Code Playgroud)

这基本上就是你需要做的.以下是电话号码的示例:

digit: charset "012345689"

phone-number-rule: [
    here:
    (error: "invalid area code")
    ["514" | "800" | "888" | "916" "877"]

    here:
    (error: "expecting dash")
    "-"

    here:
    (error: "expecting 3 digits")
    3 digit

    here:
    (error: "expecting dash")
    "-"

    here:
    (error: "expecting 4 digits")
    4 digit

    (error: none)
]
Run Code Online (Sandbox Code Playgroud)

然后你可以看到它在行动.请注意,如果我们到达解析规则的末尾,我们将错误设置为none.如果还有更多要处理的输入,PARSE将返回false,所以如果我们注意到没有设置错误但是PARSE仍然返回false ...我们失败了因为有太多的额外输入:

input: "800-22r2-3333"

if not parse input phone-number-rule [
   if none? error [
        error: "too much data for phone number"
    ]
]

either error [
    column: length? copy/part input here newline
    print rejoin ["error at position:" space column]
    print error
    print input
    print rejoin [head insert/dup "" space column "^^"}
    print newline
][
    print {all good}
]
Run Code Online (Sandbox Code Playgroud)

以上将打印以下内容:

error at position: 4

expecting 3 digits
800-22r2-3333
    ^
Run Code Online (Sandbox Code Playgroud)

显然,你可以做更多有力的东西,因为你在parens中放入的任何内容都将像普通的Rebol源代码一样进行评估.它非常灵活.我甚至有解析器在加载巨大的数据集时更新进度条...... :-)