版权归原作者所有,如有侵权,请联系我们

[科普中国]-编译程序

科学百科
原创
科学百科为用户提供权威科普内容,打造知识科普阵地
收藏

编译程序(Compiler,compiling program)也称为编译器,是指把用高级程序设计语言书写的源程序,翻译成等价的机器语言格式目标程序的翻译程序。编译程序属于采用生成性实现途径实现的翻译程序。它以高级程序设计语言书写的源程序作为输入,而以汇编语言或机器语言表示的目标程序作为输出。编译出的目标程序通常还要经历运行阶段,以便在运行程序的支持下运行,加工初始数据,算出所需的计算结果。

定义编译程序词组可以有两种认识。

一、编译程序是一种动作,是根据编译原理技术,由高级程序设计语言编译器翻译成机器语言二进制代码行为。

二、编译程序是动名词,特指生成编译器的软件程序。1

简介编译程序compiler

编译程序的实现算法较为复杂。这是因为它所翻译的语句与目标语言的指令不是一一对应关系,而是一多对应关系;同时也因为它要处理递归调用、动态存储分配、多种数据类型,以及语句间的紧密依赖关系。但是,由于高级程序设计语言书写的程序具有易读、易移植和表达能力强等特点,编译程序广泛地用于翻译规模较大、复杂性较高、且需要高效运行的高级语言书写的源程序。

功能编译程序的基本功能是把源程序(高级语言)翻译成目标程序。但是,作为一个具有实际应用价值的编译系统,除了基本功能之外,还应具备语法检查、调试措施、修改手段、覆盖处理、目标程序优化、不同语言合用以及人-机联系等重要功能。①语法检查:检查源程序是否合乎语法。如果不符合语法,编译程序要指出语法错误的部位、性质和有关信息。编译程序应使用户一次上机,能够尽可能多地查出错误。②调试措施:检查源程序是否合乎设计者的意图。为此,要求编译程序在编译出的目标程序中安置一些输出指令,以便在目标程序运行时能输出程序动态执行情况的信息,如变量值的更改、程序执行时所经历的线路等。这些信息有助于用户核实和验证源程序是否表达了算法要求。③修改手段:为用户提供简便的修改源程序的手段。编译程序通常要提供批量修改手段(用于修改数量较大或临时不易修改的错误)和现场修改手段(用于运行时修改数量较少、临时易改的错误)。④覆盖处理:主要是为处理程序长、数据量大的大型问题程序而设置的。基本思想是让一些程序段和数据公用某些存储区,其中只存放当前要用的程序或数据;其余暂时不用的程序和数据,先存放在磁盘等辅助存储器中,待需要时动态地调入。⑤目标程序优化:提高目标程序的质量,即占用的存储空间少,程序的运行时间短。依据优化目标的不同,编译程序可选择实现表达式优化、循环优化或程序全局优化。目标程序优化有的在源程序级上进行,有的在目标程序级上进行。⑥不同语言合用:其功能有助于用户利用多种程序设计语言编写应用程序或套用已有的不同语言书写的程序模块。最为常见的是高级语言和汇编语言的合用。这不但可以弥补高级语言难于表达某些非数值加工操作或直接控制、访问外围设备和硬件寄存器之不足,而且还有利于用汇编语言编写核心部分程序,以提高运行效率。⑦人-机联系:确定编译程序实现方案时达到精心设计的功能。目的是便于用户在编译和运行阶段及时了解内部工作情况,有效地监督、控制系统的运行。早期编译程序的实现方案,是把上述各项功能完全收纳在编译程序之中。然而,习惯做法是在操作系统的支持下,配置调试程序、编辑程序和连接装配程序,用以协助实现程序的调试、修改、覆盖处理,以及不同语言合用功能。但在设计编译程序时,仍须精心考虑如何与这些子系统衔接等问题。2

特点编译程序必须分析源程序,然后综合成目标程序。首先,检查源程序的正确性,并把它分解成若干基本成分;其次,再根据这些基本成分建立相应等价的目标程序部分。为了完成这些工作,编译程序要在分析阶段建立一些表格,改造源程序为中间语言形式,以便在分析和综合时易于引用和加工(图1)。

数据结构分析和综合时所用的主要数据结构,包括符号表、常数表和中间语言程序。符号表由源程序中所用的标识符连同它们的属性组成,其中属性包括种类(如变量、数组、结构、函数、过程等)、类型(如整型、实型、字符串、复型、标号等),以及目标程序所需的其他信息。常数表由源程序中用的常数组成,其中包括常数的机内表示,以及分配给它们的目标程序地址。中间语言程序是将源程序翻译为目标程序前引入的一种中间形式的程序,其表示形式的选择取决于编译程序以后如何使用和加工它。常用的中间语言形式有波兰表示、三元组、四元组以及间接三元组等。

分析部分源程序的分析是经过词法分析、语法分析和语义分析三个步骤实现的。词法分析由词法分析程序(又称为扫描程序)完成,其任务是识别单词(即标识符、常数、保留字,以及各种运算符、标点符号等)、造符号表和常数表,以及将源程序换码为编译程序易于分析和加工的内部形式。语法分析程序是编译程序的核心部分,其主要任务是根据语言的语法规则,检查源程序是否合乎语法。如不合乎语法,则输出语法出错信息;如合乎语法,则分解源程序的语法结构,构造中间语言形式的内部程序。语法分析的目的是掌握单词是怎样组成语句的,以及语句又是如何组成程序的。语义分析程序是进一步检查合法程序结构的语义正确性,其目的是保证标识符和常数的正确使用,把必要的信息收集和保存到符号表或中间语言程序中,并进行相应的语义处理。

工作过程编译程序也叫编译系统,是把用高级语言编写的面向过程的源程序翻译成目标程序的语言处理程序。编译程序把一个源程序翻译成目标程序的工作过程分为五个阶段:词法分析;语法分析;中间代码生成;代码优化;目标代码生成。主要是进行词法分析和语法分析,又称为源程序分析,分析过程中发现有语法错误,给出提示信息。

(1) 词法分析

词法分析的任务是对由字符组成的单词进行处理,从左至右逐个字符地对源程序进行扫描,产生一个个的单词符号,把作为字符串的源程序改造成为单词符号串的中间程序。执行词法分析的程序称为词法分析程序或扫描器。

源程序中的单词符号经扫描器分析,一般产生二元式:单词种别;单词自身的值。单词种别通常用整数编码,如果一个种别只含一个单词符号,那么对这个单词符号,种别编码就完全代表它自身的值了。若一个种别含有许多个单词符号,那么,对于它的每个单词符号,除了给出种别编码以外,还应给出自身的值。

词法分析器一般来说有两种方法构造:手工构造和自动生成。手工构造可使用状态图进行工作,自动生成使用确定的有限自动机来实现。

(2) 语法分析

编译程序的语法分析器以单词符号作为输入,分析单词符号串是否形成符合语法规则的语法单位,如表达式、赋值、循环等,最后看是否构成一个符合要求的程序,按该语言使用的语法规则分析检查每条语句是否有正确的逻辑结构,程序是最终的一个语法单位。编译程序的语法规则可用上下文无关文法来刻画。

语法分析的方法分为两种:自上而下分析法和自下而上分析法。自上而下就是从文法的开始符号出发,向下推导,推出句子。而自下而上分析法采用的是移进归约法,基本思想是:用一个寄存符号的先进后出栈,把输入符号一个一个地移进栈里,当栈顶形成某个产生式的一个候选式时,即把栈顶的这一部分归约成该产生式的左邻符号。

(3) 中间代码生成

中间代码是源程序的一种内部表示,或称中间语言。中间代码的作用是可使编译程序的结构在逻辑上更为简单明确,特别是可使目标代码的优化比较容易实现。中间代码即为中间语言程序,中间语言的复杂性介于源程序语言和机器语言之间。中间语言有多种形式,常见的有逆波兰记号、四元式、三元式和树。

(4) 代码优化

代码优化是指对程序进行多种等价变换,使得从变换后的程序出发,能生成更有效的目标代码。所谓等价,是指不改变程序的运行结果。所谓有效,主要指目标代码运行时间较短,以及占用的存储空间较小。这种变换称为优化。

有两类优化:一类是对语法分析后的中间代码进行优化,它不依赖于具体的计算机;另一类是在生成目标代码时进行的,它在很大程度上依赖于具体的计算机。对于前一类优化,根据它所涉及的程序范围可分为局部优化、循环优化和全局优化三个不同的级别。

(5) 目标代码生成

目标代码生成是编译的最后一个阶段。目标代码生成器把语法分析后或优化后的中间代码变换成目标代码。目标代码有三种形式:

① 可以立即执行的机器语言代码,所有地址都重定位;

② 待装配的机器语言模块,当需要执行时,由连接装入程序把它们和某些运行程序连接起来,转换成能执行的机器语言代码;

③ 汇编语言代码,须经过汇编程序汇编后,成为可执行的机器语言代码。

目标代码生成阶段应考虑直接影响到目标代码速度的三个问题:一是如何生成较短的目标代码;二是如何充分利用计算机中的寄存器,减少目标代码访问存储单元的次数;三是如何充分利用计算机指令系统的特点,以提高目标代码的质量。3

综合部分综合阶段必须根据符号表和中间语言程序产生出目标程序,其主要工作包括代码优化、存储分配和代码生成。代码优化是通过重排和改变程序中的某些操作,以产生更加有效的目标程序。存储分配的任务是为程序和数据分配运行时的存储单元。代码生成的主要任务是产生与中间语言程序符等价的目标程序,顺序加工中间语言程序,并利用符号表和常数表中的信息生成一系列的汇编语言或机器语言指令。

结构编译过程分为分析和综合两个部分,并进一步划分为词法分析、语法分析、语义分析、代码优化、存储分配和代码生成等六个相继的逻辑步骤。这六个步骤只表示编译程序各部分之间的逻辑联系,而不是时间关系。编译过程既可以按照这六个逻辑步骤顺序地执行,也可以按照平行互锁方式去执行。在确定编译程序的具体结构时,常常分若干遍实现。对于源程序或中间语言程序,从头到尾扫视一次并实现所规定的工作称作一遍。每一遍可以完成一个或相连几个逻辑步骤的工作。例如,可以把词法分析作为第一遍;语法分析和语义分析作为第二遍;代码优化和存储分配作为第三遍;代码生成作为第四遍。反之,为了适应较小的存储空间或提高目标程序质量,也可以把一个逻辑步骤的工作分为几遍去执行。例如,代码优化可划分为代码优化准备工作和实际代码优化两遍进行。

一个编译程序是否分遍,以及如何分遍,根据具体情况而定。其判别标准可以是存储容量的大小、源语言的繁简、解题范围的宽窄,以及设计、编制人员的多少等。分遍的好处是各遍功能独立单纯、相互联系简单、逻辑结构清晰、优化准备工作充分。缺点是各遍之中不可避免地要有些重复的部分,而且遍和遍之间要有交接工作,因之增加了编译程序的长度和编译时间。

一遍编译程序是一种极端情况,整个编译程序同时驻留在内存,彼此之间采用调用转接方式连接在一起(图2)。当语法分析程序需要新符号时,它就调用词法分析程序;当它识别出某一语法结构时,它就调用语义分析程序。语义分析程序对识别出的结构进行语义检查,并调用“存储分配”和“代码生成”程序生成相应的目标语言指令。

随着程序设计语言在形式化、结构化、直观化和智能化等方面的发展,作为实现相应语言功能的编译程序,也正向自动程序设计的目标发展,以便提供理想的程序设计工具。

参考书目

陈火旺、钱家骅、孙永强编:《编译原理》,国防工业出版社,北京,1980。

A.V.Aho, Principles of Compiler Design,Addison Wes-ley, Reading, Massachusetts, 1977.

动态20世纪80年代以后,程序设计语言在形式化、结构化、直观化和智能化等方面有了长足的进步和发展,主要表现两个方面:①随着程序设计理论和方法的发展,相继推出了一系列新型程序设计语言,如结构化程序设计语言、并发程序设计语言、分布式程序设计语言、函数式程序设计语言、智能化程序设计语言、面向对象程序设计语言等;②基于语法、语义和语用方面的研究成果,从不同的角度和层次上深刻地揭示了程序设计语言的内在规律和外在表现形式。与此相应地,作为实现程序设计语言重要手段之一的编译程序,在体系结构、设计思想、实现技术和处理内容等方面均有不同程度的发展、变化和扩充。另外,编译程序已作为实现编程的重要软件工具,被纳入到软件支援环境的基本层软件工具之中。因此,规划编译程序实现方案时,应从所处的具体软件支援环境出发,既要遵循整个环境的全局性要求和规定,又要精心考虑与其他诸层软件 工具之间的相互支援、配合和衔接关系。

本词条内容贡献者为:

李嘉骞 - 博士 - 同济大学