龙书阅读笔记

星期三, 九月 20, 2006

1.1 Compilers

编译器是一个程序,把一个用一种语言(source language)编写的程序翻译成等价的另一种语言的程序(target language)(figure 1.1)。

重要部分之一:向用户报告源代码中的错误



一眼看,编译器的种类太多了
  • 源语言,从传统的Fortran,pascal到几乎每个领域的专用语言
  • 目标语言-可能是另外一种编程语言,也可能是机器语言,从microprocessor到supercomputer

分类:
single-pass,multi-pass,load-and-go,debugging,optimizing等等

虽然看起来很复杂,但是任何编译器执行的基本任务几乎是一样的。理解了这些任务,我们就可以用相同的基本技术构造适用于各种源语言和目标机器的编译器

1950以来,关于组织和编写编译器的知识大大提高了。


The Analysis-Synthesis Model of Compilation

编译有两部分:
分析和合成

  • 分析部分把源代码打碎成为连续的片段,创建了源程序的一个中间表现形式
  • 合成部分从中间表现形式构造出需要的目标程序

此两者中,合成需要更多的专用技术

分析阶段,源程序隐含的操作被判断并纪录在一个层次型的结构-tree中。一种特定类型的树,语法树.syntax tree-每一个节点代表一个操作,节点的子代表操作的参数,例如下面是一个赋值语句的语法树


许多操纵源程序的软件工具首先执行某种类型的分析,例子包括:
  1. structure editor: 取一个命令输入流,构造一个源程序。结构编辑器不但执行文本创建、修改一个普通文本编辑器的功能,同时它也分析程序文本,在源程序上加入一个适当的层次型结构。因此,结构编辑器能够执行对程序准备有用的额外任务。例如,它可以检查输入是否被正确格式化,可以自动提供关键字(例如,当用户输入while的时候,编辑器提供匹配的do,并且提醒用户他们之间必须有一个条件),可以从一个begin或左括号跳到匹配的end或者右括号。另外,这样一种编辑器的输出通常和一个编译器的分析阶段输出很象
  2. Pretty printers。分析程序,打印它,使得程序的结构清晰可见。
  3. Static checkers。读取一个程序,分析它,试图在不运行的情况下发现潜在的bug。分析部分往往和优化编译器采用的技术很相近。例如,一个静态检查器可以检测源代码中永远不会被执行的部分,或者某个变量可能在定义前被使用。另外,通过采用类型检查技术,它可以捕获诸如把一个real变量当作一个指针使用这样的逻辑错误。
  4. Interpreter。不产生目标程序,执行源程序隐含的操作。例如对一个赋值语句,一个解释器可能构造类似figure 1.2这样的一棵树,然后通过遍历这棵树执行该操作:
    • 在树的root,它发现需要执行一个赋值
      • 因此调用一个进程去计算右边的表达式
      • 然后把结果值放到一个可以和position这个标识符关联的地方
    • 在root的右子,进程会发现需要计算两个表达式的和
      • 它递归调用自己计算表达式rate+60的值
      • 然后把这个值和变量initial的值相加
传统上,我们把编译器考虑为一个把一种源语言翻译为汇编或者机器语言的程序。但是,很多看起来无关的地方也大量使用编译器技术。下面例子的分析部分非常类似一个传统的编译器:
  1. Text formatter: 一个文本格式器取一个字符流作为输入,大部分是文字,但某些是命令,指定段落、图表或者数学公式
  2. Silicon compiler 语言的变量代表的并非内存位置,而是电路板上的逻辑信号或信号
  3. Query interpreter,SQL

The Context of a Compiler

除了编译器外,可能还需要其它程序才能产生一个可执行的目标程序。源程序可能分成不同模块存放在不同的文件中。

收集源程序的任何可能交给单独的程序,叫做preprocessor。预处理器可能扩展缩写、宏到源程序语句中。

Figure 3.1是一个典型的“编译”。编译器创建的目标程序在运行前需要更多处理。图中的编译器创建汇编代码,被一个汇编器翻译为机器代码,和其它的库进程连接成为可以实际在机器上run的代码。


没有评论: