编译器如何处理运行时错误消息中的行号

时间:2012-04-15 15:07:04

标签: compiler-construction runtime lexical-analysis

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

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

另外:

  • 运行时环境
  • 机器翻译

2 个答案:

答案 0 :(得分:1)

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

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

  

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

由于我的语言很简单,我可以做出一些假设,例如:指令只能在一行中。我的Lexer使用正则表达式检查不应该存在的字符,例如“不是数字,字母的字符”(“,”,“”等。“我将文件读入字符串列表,其中每个字符串是下一行,所以如果我扫描一行并找到错误,我返回指数+ 1,即行数。

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

当我扩展解析器时,我将一个令牌与代码中的行相关联,以便在出现错误时将其返回。

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

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

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

*请注意,这是3次通过的非常简单的模型。 Modern compilers have a lot more

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

答案 1 :(得分:0)

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

如上所述,在词法分析器规范中将行和字符编号与标识符或字符串/ char / integer / boolean literal相关联是很常见的。通常,词法分析器提供yyline()方法来执行此操作。不要让词法分析器返回原始令牌(例如字符串)值,而是让它返回包含字符串值,字符和行号的对象。例如,快速查看this lexer规范。

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

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