4

几乎所有编译器都会返回一个行号以及错误消息。我想知道从编译器设计的角度来看,编译器如何处理不同阶段的行号消息?谢谢。

  • 扫描器
  • 解析器
  • AST 数据结构
  • 代码生成

另外的:

  • 运行环境
  • 机器翻译
4

2 回答 2

1

我为我的班级分配实现了一个相当简单的编译器。它是 Pascal 的一个子集,但有一些其他限制。

编译器是将一种语言翻译成另一种语言的工具。它通过执行错误检查然后生成输出代码(如果可能)来做到这一点。通常,编译器的流水线大致相当于:

输入代码 -> 词法分析器(扫描器) -> 语法分析器 -> 语义分析器 -> 代码生成器 -> 输出代码 *

因为我的语言很简单,所以我可以做出一堆假设,例如一条指令只会在一行中。我的 Lexer 使用正则表达式来检查不应该存在的字符,例如“不是数字、字母、“(”、“”、“。”等的字符。”我将文件读入字符串列表,其中每个字符串是下一行,所以如果我扫描一行并发现错误,我会返回索引 + 1,即行号。

使用语法分析器(解析器)检查例如“如果变量名以字母开头”,算法是相似的。

当我扩展解析器时,我将一个标记与代码中的行相关联,以便在发生错误时返回它。

我不知道现代编译器如何解决这个问题,但我可以猜测这也是 AST 和行号的某种关联,记住一个 AST 可能在几行中(嗯,这取决于语言)。

使用代码生成编译器知道代码是正确的(据他们所知)并且返回错误不会与代码有关,而是编译器或进程存在问题(错误,内存不足,无法写入位置等)。

运行时环境和机器解释也可能有编译器,例如 JIT,但错误消息返回通常表示编译器或运行时中的错误,而不是代码。

*请注意,这是非常简单的 3 遍模型。现代编译器有更多的.

编辑:我发现 AST 有一个指示行号的字段和一个错误文件(对于每个节点)。

于 2012-04-15T16:11:25.267 回答
0

大多数词法分析器和解析器生成器将生成具有错误报告方法的代码,这些方法在发生匹配错误时被调用。您可以覆盖该方法并做您想做的事。

如前所述,在词法分析器规范中,将行号和字符号与标识符或字符串/字符/整数/布尔文字相关联是很常见的。通常,词法分析器会提供一种yyline()方法来执行此操作。与其让词法分析器返回原始标记(例如字符串)值,不如让它返回一个包含字符串值、字符和行号的对象。例如,快速浏览一下这个词法分析器规范。

private Symbol symbol(int type) {
    return new Symbol(type, yyline, yycolumn);
}

解析器将在解析期间接收符号,并应获取位置信息以及令牌值,并将其插入 AST 节点。该信息最终应该会进入符号表。在类型分析过程中,每个叶子节点都会绑定位置信息。这应该是您提供相当好的错误诊断所需的全部内容。

于 2012-04-15T20:49:43.593 回答