在翻译中,lexer之后会出现什么(通常)?

时间:2011-05-15 05:05:06

标签: design-patterns language-design interpreter

对于编程语言解释器,我想知道解释器经历的事件序列。例如,我认为这就是它:

  • 口译员得到一些输入
  • lexer / tokenizer获取输入并划分标记
  • x 获取令牌列表
  • ???
  • 代码执行

什么步骤属于???现场,以及 x 所代替的地方(也就是说,那些在词法分子产生的标记上收集和操作的东西)?

3 个答案:

答案 0 :(得分:2)

解析发生,将令牌流转换为结构化,经过验证的语法信息。如果你想评估一个算术表达式:

( x + 4 ) * 3

你不是通过从左到右扫描令牌来做到这一点。你需要弄清楚操作的顺序。您需要将if关键字和{ }花括号之间的标记转换为描述if语句的高级结构,这样您就可以在不使用一堆标记的情况下对其进行评估。你需要检查语法,如果没有正确解析它,这基本上是不可能的;请阅读无上下文语法

上面的表达式将成为抽象语法树,如下所示:

    *
  +   3
 x y

评估这一点非常简单 - 只需遍历树,然后在环境中查找xy

同样,给出了一系列这样的陈述:

if ( p && q ) { foo ; {{ 1}} bar ; } else { baz ;

抽象语法树可能具有以下一般结构:

}

希望你能想象如何遍历这棵树来解释代码。

我强烈推荐的口译员教材是Essentials of Programming Languages

答案 1 :(得分:2)

我首先推荐经典免费图书:Structure and Interpretation of Computer Programsvideo lectures

Lisp是基线解释器,其他所有东西在某种程度上都是主题的变体。

一般来说,步骤是:

  • 词法分析采用char流并生成令牌
  • 解析获取标记(平面列表)并构建称为抽象语法树(AST)的数据结构。这一步非常简单(Lisp)或非常复杂(C ++,Ruby)。
  • 评估AST。细节有点不同,但这几乎是深入树下的深度。叶子是data(数字,字符串,常数,变量)节点是原始函数(数学,数据操作,控制结构)或更高级别的复合函数。每个节点应该减少到可以直接馈送到它上面的节点的东西。

最后一步“代码被执行。”对于编译或即时(JIT)语言,最后一步是将AST转换回机器指令。注意可能存在的其他两个步骤也很重要。一种是翻译成更简单的语言,如c--,LLVM,.NET或Java bitecode。另一个是解析器和评估器之间可能发生的desugaring和/或优化。例如,哈斯克尔因为大量的堕落而臭名昭着。

最后,我将鼓励您尝试编写Scheme(Lisp方言)解释器的众多演练之一。在网上某处可能有一个你最喜欢的语言。

答案 2 :(得分:1)

对于解释器,解析器通常会做两件事

  1. 生成p代码
  2. 将项目添加到符号表
  3. 在此之后,executor将在符号表中执行p代码和查找标识符等。

    解析器解析它接收的标记流,并且在解析阶段找到的任何符号(如变量,函数,复杂数据类型结构等)的同时生成更简单的执行p-code的效率更高。输入符号表并在p代码中引用。

    执行程序然后处理p代码流并执行指令并使用符号表查找它在符号表中遇到的任何标识符。