语法:开始:(a b)?一个c;输入:a。在位置2哪个错误正确? 1.预期“b”,“c”。或预期“c”

时间:2014-01-03 11:07:18

标签: parsing error-reporting peg parsing-error

语法:

rule: (a b)? a c ;

输入:

a d

问题:给定输入的位置2哪条错误消息正确?

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

P.S。

我写解析器,我有选择(困境)考虑到" b"期待或不参加。

#1错误(预期" b"," c")想要输入" a b"预期,但因为它是可选的,它可能没有预期但可能。

我不知道可能与预期相同吗?

哪个错误信息更好,更正确#1或#2?

感谢您的回答。

P.S。

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

if(_inputPos > testing) {
  _failure(_inputPos, _code[cp + {{OFFSET_RESULT}}]);
}

在可选表达式中移动限制:

OPTIONAL_EXPRESSION:
testing = _inputPos;

" b"表达式移动_inputPos高于testing pos并在_inputPos添加失败。

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

if(!testing) {
  _failure(_inputPos, _code[cp + {{OFFSET_RESULT}}]);
}

" b"在这种情况下,表达式不会因为测试而导致失败(内部表示可选表达式)。

您认为哪些更好更正确?

  1. 测试被定义​​为特定位置,如果表达式高于此位置(_inputPos>测试),则会增加失败(即使它在可选表达式中)。

  2. 测试定义为标志,如果此标志设置失败未考虑。执行可选表达式后,它会恢复(不重置!)以前的测试值(true或false)。

  3. 如果规则没有失败,也不会考虑故障。他们只报告解析是否失败。

    P.S。

    2014年1月6日的变更

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

    第一个问题:

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

    • 终端符号
    • 非终结符号
    • 空字符串

    这种语法不提供词法预处理等操作,因此它不提供令牌这样的元素。

    第二个问题:

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

    假设我们有两个语法:

    语法1

    规则< - 类型?标识符

    语法2

    规则< - 类型标识符/标识符

    他们都接受相同的输入,但产生(在PEG中)不同的结果。

    语法1结果:

    • {type:type,identifier:identifier}
    • {type:null,identifier:identifier}

    语法2结果:

    • {type:type,identifier:identifier}
    • {identifier:identifier}

    Quetions:

    • 两种语法都相等吗?
    • 进行语法优化是无痛的吗?

    我对这两个问题的回答都是否定的。不平等,不痛苦。

    但你可能会问。 "但为什么会这样?"。

    我可以回答你。 "因为这不是问题。这是一个功能"。

    在PEG解析器表达式中,ALWAYS由这些部分组成。

    ORDERED_CHOICE => SEQUENCE =>表达

    这个解释是我对问题的答案"但为什么会这样呢?"。

    另一个问题。

    PEG解析器无法识别WHITESPACES,因为它没有令牌和令牌分隔符。

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

    程序< - WHITESPACE expr EOF

    expr< - ruleX

    ruleX< - ' X' WHITESPACE

    WHITESPACE< ' '?

    EOF< - !

    所有PEG语法都以这种方式描述。

    第一个WHITESPACE在开始时和其他WHITESPACE(经常)在规则结束时。

    在这种情况下,在PEG中,必须假设WHITESPACE符合预期。

    但WHITESPACE并不仅仅意味着空间。它可能更复杂[\ t \ n \ r]甚至评论。

    但错误消息的主要规则如下。

    如果无法显示所有预期的元素(或者不能显示所有预期元素中的至少一个),在这种情况下更正确,不显示任何内容。

    更精确地要求显示"意外"错误消息。

    你在PEG中如何展示预期的WHITESPACE?

    • 分析器错误:预期WHITESPACE
    • 分析器错误:预期' ',' \ t',' \ n' ,' r'

    如何开始评论?在一些语法中,它们也可能是WHITESPACE的一部分。

    在这种情况下,可选的WHITESPACE将拒绝所有其他潜在的预期元素,因为无法正确显示错误消息中的WHITESPACE,因为WHITESPACE太复杂而无法显示。

    这是好还是坏?

    我认为这并不错,需要一些技巧来隐藏PEG解析器的这种性质。

    在我的PEG解析器中,我不认为必须按预期处理可选(可选& zero_or_more)表达式的第一个位置的内部表达式。 但所有其他内部(除了在第一个位置)必须按预期处理。

    示例1:

    List<int list; // type? ident
    
    Here "List<int" is a "type". But missing ">" is not at the first position in optional "type?".
    

    此失败会考虑并报告为&#34;预期&#39;&gt;&#39;&#34;&#34; 这是因为我们不会跳过&#34;键入&#34;但进入&#34;键入&#34;经过真正的选择&#34; List&#34;我们将头寸从第一个移到下一个真实的&#34;预期&#34; (已经在测试位置之外)元素。

    &#34;列表&#34;在&#34;测试&#34;位置。

    如果内部表达(在可选表达式内)&#34;符合限制&#34;不继续在下一个位置,然后它不被假定为预期的输入。

    从这个假设中提出了一个主要问题。

    您必须考虑到我们正在讨论PEG解析器及其错误消息。

1 个答案:

答案 0 :(得分:3)

这是你的语法:

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

为无效输入生成错误消息的基本思路是找到失败的最远位置(如果您的语法d | (a b)? a cd不会成为错误的一部分)并且确定哪些可能的输入可以让你前进并说出"expected '...' but got '...'"。还有其他方法可以尝试恢复解析器并强制它继续。如果只有一个可能的预期令牌,让我们暂时将其插入令牌流中,并继续,就像它从那里一样。这将导致更好的错误检测,因为您可以找到超出解析器首次停止点的错误。