Parsing 语法:开始:(a-b)?a c;输入:a d。位置2处的哪个错误正确?1.“预期”;“b”&引用;c";。“或预期”;";

Parsing 语法:开始:(a-b)?a c;输入:a d。位置2处的哪个错误正确?1.“预期”;“b”&引用;c";。“或预期”;";,parsing,error-reporting,peg,parsing-error,Parsing,Error Reporting,Peg,Parsing Error,语法: rule: (a b)? a c ; 输入: a d 问题:对于给定的输入,哪条错误消息在位置2处正确 1. expected "b", "c". 2. expected "c". 附言 我编写解析器,我有选择(进退两难)来考虑“b”在位置上的预期值,或者不考虑 #1错误(预期为“b”、“c”)表示输入“AB”是预期的,但由于它是可选的,因此可能不是预期的,而是可能的 我不知道可能和预期的一样吗 哪一条错误消息更好且正确#1或#2 谢谢你的回答 附言 在第一种情况下,我将测试的标记

语法:

rule: (a b)? a c ;
输入:

a d
问题:对于给定的输入,哪条错误消息在位置2处正确

1. expected "b", "c".
2. expected "c".
附言

我编写解析器,我有选择(进退两难)来考虑“b”在位置上的预期值,或者不考虑

#1错误(预期为“b”、“c”)表示输入“AB”是预期的,但由于它是可选的,因此可能不是预期的,而是可能的

我不知道可能和预期的一样吗

哪一条错误消息更好且正确#1或#2

谢谢你的回答

附言

在第一种情况下,我将
测试的标记定义为位置限制

if(_inputPos > testing) {
  _failure(_inputPos, _code[cp + {{OFFSET_RESULT}}]);
}
在可选表达式中移动的限制:

OPTIONAL_EXPRESSION:
testing = _inputPos;
“b”表达式将
\u inputPos
移动到
测试
位置上方,并在
\u inputPos
处添加故障

在第二种情况下,我可以将
测试的标记定义为布尔标志

if(!testing) {
  _failure(_inputPos, _code[cp + {{OFFSET_RESULT}}]);
}
本例中的“b”表达式未添加失败,因为它已测试(可选表达式为内部)

你认为什么是更好和正确的

  • 测试定义为特定位置,如果表达式位于该位置上方(_inputPos>Testing),则会添加失败(甚至在可选表达式内)

  • 测试定义为标志,如果该标志设置为不考虑故障。执行可选表达式后,它将恢复(而不是重置!)测试的上一个值(true或false)

  • 如果规则没有失败,也不考虑失败。它们仅在解析失败时报告

    附言

    截至2014年1月6日的变化

    提出这个问题是因为它涉及两个不同的问题

    第一个问题:

    解析表达式语法(PEG)仅描述输入的三个原子项:

    • 终端符号
    • 非终结符
    • 空字符串
    该语法不提供诸如词法预处理之类的操作,因此它不提供诸如标记之类的元素

    第二个问题:

    什么是语法?如果两个语法接受相同的输入但产生不同的结果,它们是否可以被视为相等

    假设我们有两种语法:

    语法1

    规则表达式

    这个解释就是我对“为什么会这样”这个问题的回答

    另一个问题

    PEG解析器不识别空白,因为它没有标记和标记分隔符

    现在看看这个语法(简而言之):

    程序这是您的语法:


    这里清楚的是,在第一个
    a
    之后有两个可能的输入:
    b
    c
    。您的错误消息不应将一个优先于另一个


    为无效输入生成错误消息的基本思想是找到您失败的最远的地方(如果您的语法在哪里?
    d|(a b)?a c
    d
    不会是错误的一部分),并确定哪些可能的输入可以让您前进并说
    “预期的”…“但得到的”…”
    。还有其他方法可以尝试恢复解析器并强制其继续。如果只有一个可能的预期令牌,那么让我们暂时将其插入令牌流并继续,就像它从那时起就存在一样。这将导致更好的错误检测,因为您可以在解析器第一次停止的位置之外发现错误。

    最好只看到一次,而不是听到一百次。很好的图表,很好的证明。“你的错误信息不应该优先考虑其中一个。”。这仅在状态自动机图表中可见。在PEG中,我没有对表达式使用状态自动机,对我来说,这个明显的图形路径是不可用的。我通过一些解析器来分析语法(规则和表达式),这些解析器主要作为表达式访问者来实现。很好。实现它的一种方法是使用一个输入位置最大的变量(以-1开头)和一个包含错误时预期标记(以空开头)的列表。每当你有一个规则由于某种原因失败时(当你回溯时),对照第一个变量检查你的当前位置。如果较大,则更新变量并删除列表。然后,如果它相等,则将期望的标记追加到列表中。是的,这是一个明显的问题,并且它已经按照您描述的方式实现了。问题处于进退两难的境地:“可选表达式的内部表达式是否为预期输入?”您的图表证明语法描述方式(用于定义所有集合的表达式)没有差异。需要考虑所有可能的路径(令牌或字符,这取决于解析器的类型,而不是描述令牌)。当然,远位置的故障比近位置的故障更为重要,它初始化为-1(输入开始之前)。
    List<int list; // type? ident
    
    Here "List<int" is a "type". But missing ">" is not at the first position in optional "type?".