分析器错误 - 自动生成错误处理的模式

Mic*_*dda 8 compiler-construction grammar parsing

有没有任何已知的方法来为机器生成的解析器实现良好的错误处理?这种问题是否存在"模式"或已知算法?

对于"好",我的意思是类似于手工制作的递归下降解析器和现代编译器可获得的结果:Parser不会在第一次出错时停止,可以发出"有意义"的错误而不仅仅是"行xyz中无法识别的令牌"一个错误一次.

理想情况下,这种方法也应该是自动化的,而不是手工制作的.

我不是在寻找一个库,我需要一种方法,可以在不同的平台上使用,理想情况下尽可能与语言无关.

eh9*_*eh9 7

对于这个问题,我有不同的看法,那就是您不应将语法错误视为内部编译器错误。任何实际的编译器实际上都在实现三种语言:

  1. 作为指定目标语言的语言L。正确的程序是该语言的成员。
  2. L加上编译器可识别的所有错误组成的语言M。M \ L的成员收到提示错误。
  3. 编译器正常终止的语言Z。该集合应该是所有可能的输入字符串的集合,但是如果编译器在某些输入上崩溃,则不是。Z \ M的成员收到有关编译器如何失败的一般消息,形式通常为“解析器在x线char y处失败”。

如果在解析器中指定语言M而不是语言L,则可以使用自动解析器生成器工具。这种方法的问题在于语言设计者始终指定大号,而不是中号。我想不出哪怕是M的标准。

这不仅仅是抽象的废话。C ++最近发生了变化,很好地说明了这种区别。曾经是

template< class T > class X;
template< class T > class Y;
X<Y<int>> foo; // syntax in M
Run Code Online (Sandbox Code Playgroud)

第三行出现错误,因为字符“ >>”是右移运算符的标记。那行必须写

X<Y<int> > foo; // syntax in L
Run Code Online (Sandbox Code Playgroud)

标准已更改,不需要额外的空间。原因是所有主要的编译器都已经编写了识别这种情况的代码,以生成有意义的错误消息。换句话说,他们发现M语言已经在所有地方实现。一旦委员会确定,他们就将M语法转移到L的新版本中。

我们将有更好的语言设计的整体设计是否考虑到中号的语言,同时为他们在工作大号语言。只是出于他们自己的理智,他们会尽力减少M规范的大小,这对每个人都是一件好事。las,世界还不存在。

其结果是,你需要设计自己的语言中号。那是个难题。在这一点上,是否使用自动化工具还是有点困难。它有帮助,但并没有摆脱最耗时的部分。


rur*_*ban 5

使用传统的 YACC/bison 生成器,您可以获得yyerror / YYERROR框架,由于 LALR 解析器的无序回溯性质,使用它生成非常有用的错误消息并不容易。您甚至可以在那里添加错误恢复规则,因为您可能需要它们来抑制失败规则中的错误错误消息,而您只想削减解析规则。

使用基于 PEG 的解析器,您可以获得更好的~{}后缀错误操作块语法。见例如。在挂手册

  rule = e1 e2 e3 ~{ error("e[12] ok; e3 has failed"); }
         | ...

  rule = (e1 e2 e3) ~{ error("one of e[123] has failed"); }
         | ...
Run Code Online (Sandbox Code Playgroud)

您会在错误的实际位置获得极好的错误消息。但是你必须编写 PEG 规则,这不是那么容易编写,尤其是。处理运算符优先级时。使用 LALR 解析器会更容易。

使用更简单的递归下降解析器生成器,您可以获得与 PEG 相同的错误报告优势,但解析速度要慢得多。

请参阅http://lambda-the-ultimate.org/node/4781 上的相同讨论