① 编译程序有编译和翻译两种方式分别对其说明并比较 急 在线等
编译程序 编译程序
compiler
把用高级程序设计语言书写的源程序,翻译成等价的计算机汇编语言或机器语言的目标程序的翻译程序。编译程序属于采用生成性实现途径实现的翻译程序。它以高级程序设计语言书写的源程序作为输入,而以汇编语言或机器语言表示的目标程序作为输出。编译出的目标程序通常还要经历运行阶段,以便在运行程序的支持下运行,加工初始数据,算出所需的计算结果。编译程序的实现算法较为复杂。这是因为它所翻译的语句与目标语言的指令不是一一对应关系,而是一多对应关系;同时也因为它要处理递归调用、动态存储分配、多种数据类型,以及语句间的紧密依赖关系。但是,由于高级程序设计语言书写的程序具有易读、易移植和表达能力强等特点,编译程序广泛地用于翻译规模较大、复杂性较高、且需要高效运行的高级语言书写的源程序。
功能 编译程序的基本功能是把源程序翻译成目标程序。但是,作为一个具有实际应用价值的编译系统,除了基本功能之外,还应具备语法检查、调试措施、修改手段、覆盖处理、目标程序优化、不同语言合用以及人-机联系等重要功能。①语法检查:检查源程序是否合乎语法。如果不符合语法,编译程序要指出语法错误的部位、性质和有关信息。编译程序应使用户一次上机,能够尽可能多地查出错误。②调试措施:检查源程序是否合乎设计者的意图。为此,要求编译程序在编译出的目标程序中安置一些输出指令,以便在目标程序运行时能输出程序动态执行情况的信息,如变量值的更改、程序执行时所经历的线路等。这些信息有助于用户核实和验证源程序是否表达了算法要求。③修改手段:为用户提供简便的修改源程序的手段。编译程序通常要提供批量修改手段(用于修改数量较大或临时不易修改的错误)和现场修改手段(用于运行时修改数量较少、临时易改的错误)。④覆盖处理:主要是为处理程序长、数据量大的大型问题程序而设置的。基本思想是让一些程序段和数据公用某些存储区,其中只存放当前要用的程序或数据;其余暂时不用的程序和数据,先存放在磁盘等辅助存储器中,待需要时动态地调入。⑤目标程序优化:提高目标程序的质量,即占用的存储空间少,程序的运行时间短。依据优化目标的不同,编译程序可选择实现表达式优化、循环优化或程序全局优化。目标程序优化有的在源程序级上进行,有的在目标程序级上进行。⑥不同语言合用:其功能有助于用户利用多种程序设计语言编写应用程序或套用已有的不同语言书写的程序模块。最为常见的是高级语言和汇编语言的合用。这不但可以弥补高级语言难于表达某些非数值加工操作或直接控制、访问外围设备和硬件寄存器之不足,而且还有利于用汇编语言编写核心部分程序,以提高运行效率。⑦人-机联系:确定编译程序实现方案时达到精心设计的功能。目的是便于用户在编译和运行阶段及时了解内部工作情况,有效地监督、控制系统的运行。
早期编译程序的实现方案,是把上述各项功能完全收纳在编译程序之中。然而,习惯做法是在操作系统的支持下,配置调试程序、编辑程序和连接装配程序,用以协助实现程序的调试、修改、覆盖处理,以及不同语言合用功能。但在设计编译程序时,仍须精心考虑如何与这些子系统衔接等问题。
工作过程 编译程序必须分析源程序,然后综合成目标程序。首先,检查源程序的正确性,并把它分解成若干基本成分;其次,再根据这些基本成分建立相应等价的目标程序部分。为了完成这些工作,编译程序要在分析阶段建立一些表格,改造源程序为中间语言形式,以便在分析和综合时易于引用和加工(图1)。
数据结构 分析和综合时所用的主要数据结构,包括符号表、常数表和中间语言程序。符号表由源程序中所用的标识符连同它们的属性组成,其中属性包括种类(如变量、数组、结构、函数、过程等)、类型(如整型、实型、字符串、复型、标号等),以及目标程序所需的其他信息。常数表由源程序中用的常数组成,其中包括常数的机内表示,以及分配给它们的目标程序地址。中间语言程序是将源程序翻译为目标程序前引入的一种中间形式的程序,其表示形式的选择取决于编译程序以后如何使用和加工它。常用的中间语言形式有波兰表示、三元组、四元组以及间接三元组等。
分析部分 源程序的分析是经过词法分析、语法分析和语义分析三个步骤实现的。词法分析由词法分析程序(又称为扫描程序)完成,其任务是识别单词(即标识符、常数、保留字,以及各种运算符、标点符号等)、造符号表和常数表,以及将源程序换码为编译程序易于分析和加工的内部形式。语法分析程序是编译程序的核心部分,其主要任务是根据语言的语法规则,检查源程序是否合乎语法。如不合乎语法,则输出语法出错信息;如合乎语法,则分解源程序的语法结构,构造中间语言形式的内部程序。语法分析的目的是掌握单词是怎样组成语句的,以及语句又是如何组成程序的。语义分析程序是进一步检查合法程序结构的语义正确性,其目的是保证标识符和常数的正确使用,把必要的信息收集和保存到符号表或中间语言程序中,并进行相应的语义处理。
综合部分 综合阶段必须根据符号表和中间语言程序产生出目标程序,其主要工作包括代码优化、存储分配和代码生成。代码优化是通过重排和改变程序中的某些操作,以产生更加有效的目标程序。存储分配的任务是为程序和数据分配运行时的存储单元。代码生成的主要任务是产生与中间语言程序符等价的目标程序,顺序加工中间语言程序,并利用符号表和常数表中的信息生成一系列的汇编语言或机器语言指令。
结构 编译过程分为分析和综合两个部分,并进一步划分为词法分析、语法分析、 语义分析、 代码优化、存储分配和代码生成等六个相继的逻辑步骤。这六个步骤只表示编译程序各部分之间的逻辑联系,而不是时间关系。编译过程既可以按照这六个逻辑步骤顺序地执行,也可以按照平行互锁方式去执行。在确定编译程序的具体结构时,常常分若干遍实现。对于源程序或中间语言程序,从头到尾扫视一次并实现所规定的工作称作一遍。每一遍可以完成一个或相连几个逻辑步骤的工作。例如,可以把词法分析作为第一遍;语法分析和语义分析作为第二遍;代码优化和存储分配作为第三遍;代码生成作为第四遍。反之,为了适应较小的存储空间或提高目标程序质量,也可以把一个逻辑步骤的工作分为几遍去执行。例如,代码优化可划分为代码优化准备工作和实际代码优化两遍进行。
一个编译程序是否分遍,以及如何分遍,根据具体情况而定。其判别标准可以是存储容量的大小、源语言的繁简、解题范围的宽窄,以及设计、编制人员的多少等。分遍的好处是各遍功能独立单纯、相互联系简单、逻辑结构清晰、优化准备工作充分。缺点是各遍之中不可避免地要有些重复的部分,而且遍和遍之间要有交接工作,因之增加了编译程序的长度和编译时间。
一遍编译程序是一种极端情况,整个编译程序同时驻留在内存,彼此之间采用调用转接方式连接在一起(图2)。当语法分析程序需要新符号时,它就调用词法分析程序;当它识别出某一语法结构时,它就调用语义分析程序。语义分析程序对识别出的结构进行语义检查,并调用“存储分配”和“代码生成”程序生成相应的目标语言指令。
随着程序设计语言在形式化、结构化、直观化和智能化等方面的发展,作为实现相应语言功能的编译程序,也正向自动程序设计的目标发展,以便提供理想的程序设计工具。
参考书目
陈火旺、钱家骅、孙永强编:《编译原理》,国防工业出版社,北京,1980。
A.V.Aho, Principles of Compiler Design,Addison Wes-ley, Reading, Massachusetts, 1977.
--------------------------------------------------------------------------------
编译程序 (compiler)
将用高级程序设计语言书写的源程序,翻译成等价的用计算机汇编语言、机器语言或某种中间语言表示的目标程序的翻译程序。用户利用编译程序实现数据处理任务时,先要经历编译阶段,再经历运行阶段。编译阶段以源程序作为输入,以目标程序作为输出,其主要任务是将源程序翻译成目标程序。运行阶段的任务是运行所编译出的目标程序,实现源程序中指定的数据处理任务,其工作通常包括:输入初始数据,对数据或文件进行数据加工,输出必要信息和加工结果等。编译程序的实现算法较为复杂。这是因为它所翻译的语句与目标语言的指令不是一一对应关系,而是一多对应关系;同时因为它要在编译阶段处理递归调用、动态存储分配、多种数据类型 实现 、 代码生成与代码优化等繁杂技术问题;还要在运行阶段提供良好、有效的运行环境。由于高级程序设计语言书写的程序具有易读、易移植和表达能力强等特点,所以编译程序广泛地用于翻译规模较大、复杂性较高、且需要高效运行的高级语言书写的源程序。
功能 编译程序的基本功能是把源程序翻译成目标程序。此外,还要具备语法检查、调试措施、修改手段、覆盖处理、目标程序优化、不同语言合用以及人机联系等具有实际应用价值的重要功能。①语法检查。检查源程序是否合乎语法 。②调试措施。检查源程序是否合乎用户的设计意图。③修改手段。为用户提供简便的修改源程序的手段。④覆盖处理。主要为处理程序较长、数据量较大的大型问题程序而设置。基本思想是让一些程序段和数据公用某些存储区,其中只存放当前要用的程序段或数据,其余暂时不用的程序段和数据均存放在磁盘等辅助存储器中,待需要时动态地调入存储区中运行。⑤目标程序优化。提高目标程序的质量,即使编译出的目标程序运行时间短、占用存储少。⑥不同语言合用 。便于用户利用多种程序设计语言编写应用程序或套用已有的不同语言书写的程序模块。最为常见的是高级语言和汇编语言的合用。⑦人机联系。便于用户在编译和运行阶段及时了解系统内部工作情况,有效地监督、控制系统的运行。
早期编译程序的实现方案,是把上述各项功能完全收纳在编译程序之中 。后来的习惯方法是在操作系统的支持下,配置编辑程序、调试程序、连接装配程序等实用程序或工具软件,目的是创造一个良好的开发环境和运行环境,便于应用软件的编程、修改、调试、集成以及报表生成、界面设计等工作。但编译程序设计者设计编译方案时,仍需精心考虑上述各项功能,较好地解决目标程序与这些实用程序或软件工具之间的配合与衔接等问题。
工作过程 编译程序必须分析源程序,然后综合成目标程序。为达到这个目的,编译程序要在分析阶段建立一些表格,改造源程序为中间语言形式,以便在分析和综合时易于引用和加工。
数据结构 分析和综合时所用的主要数据结构,包括符号表、常数表和中间语言程序。符号表由源程序中所用的标识符连同它们的属性组成,其中属性包括种类(如变量、数组、结构、函数、过程等)、类型(如整型、实型、字符串、复型、标号等),以及目标程序所需的其他信息。常数表由源程序中用的常数组成,其中包括常数的机内表示以及分配给它们的目标程序地址。中间语言程序是将源程序翻译成目标程序前引入的一种中间形式的程序,其表示形式的选择取决于编译程序以后如何使用它和如何加工它。常用的中间语言形式有波兰表示、三元组、四元组以及间接三元组等。
分析部分 源程序的分析是经过词法分析、语法分析和语义分析三个步骤实现的。词法分析由词法分析程序(又称为扫描程序 )完成,其任务是识别单词(即标识符 、常数、保留字,以及各种运算符、标点符号等)、造符号表和常数表,以及将源程序换码为编译程序易于分析和加工的内部形式。语法分析程序是编译程序的核心部分,其主要任务是根据语言的语法规则,检查源程序是否合乎语法,并分解源程序。如果不合乎语法,则输出语法出错信息;如果合乎语法,则分解源程 序的语法结构, 构造中间语 言形式的内部程序。语法分析的目的是掌握单词是怎样组成语句的,以及语句又是如何组成程序的。语义分析程序进一步检查合法程序结构的语义正确性,其目的是保证标识符和常数的正确使用,把必要的信息收集和保存到符号表或中间语言程序中,并进行相应的语义处理。
综合部分 综合阶段根据符号表和中间语言程序产生出目标程序,其主要工作包括代码优化、存储分配和代码生成。代码优化是通过重排和改变程序中的某些操作,以产生更加有效的目标程序。存储分配是为程序和数据分配运行时的存储单元。 代码生成是产 生与中间语 言程序等价的目标程序,亦即,顺序加工中间语言程序,利用符号表和常数表中的信息生成一系列的汇编语言或机器语言指令。
动态 20世纪80年代以后,程序设计语言在形式化、结构化、直观化和智能化等方面有了长足的进步和发展,主要表现在两个方面:①随着程序设计理论和方法的发展,相继推出了一系列新型程序设计语言,如结构化程序设计语言、并发程序设计语言、分布式程序设计语言、函数式程序设计语言、智能化程序设计语言、面向对象程序设计语言等;②基于语法、语义和语用方面的研究成果,从不同的角度和层次上深刻地揭示了程序设计语言的内在规律和外在表现形式。与此相应地,作为实现程序设计语言重要手段之一的编译程序,在体系结构、设计思想、实现技术和处理内容等方面均有不同程度的发展、变化和扩充。另外,编译程序已作为实现编程的重要软件工具,被纳入到软件支援环境的基本层软件工具之中。因此,规划编译程序实现方案时,应从所处的具体软件支援环境出发,既要遵循整个环境的全局性要求和规定,又要精心考虑与其他诸层软件 工具之间的相互支援、配合和衔接关系。
② 简述将源程序编译成可执行程序的过程
一个源程序到一个可执行程序的过程:预编译、编译、汇编、链接。其中,编译是主要部分,其中又分为六个部分:词法分析、语法分析、语义分析、中间代码生成、目标代码生成和优化。
预编译:主要处理源代码文件中的以“#”开头的预编译指令。处理规则如下:
1、删除所有的#define,展开所有的宏定义。
2、处理所有的条件预编译指令,如“#if”、“#endif”、“#ifdef”、“#elif”和“#else”。
3、处理“#include”预编译指令,将文件内容替换到它的位置,这个过程是递归进行的,文件中包含其他文件。
4、删除所有的注释,“//”和“/**/”。
5、保留所有的#pragma 编译器指令,编译器需要用到他们,如:#pragma once 是为了防止有文件被重复引用。
6、添加行号和文件标识,便于编译时编译器产生调试用的行号信息,和编译时产生编译错误或警告是能够显示行号。
(2)便于与编译扩展阅读:
编译过程中语法分析器只是完成了对表达式语法层面的分析,语义分析器则对表达式是否有意义进行判断,其分析的语义是静态语义——在编译期能分期的语义,相对应的动态语义是在运行期才能确定的语义。
其中,静态语义通常包括:声明和类型的匹配,类型的转换,那么语义分析就会对这些方面进行检查,例如将一个int型赋值给int*型时,语义分析程序会发现这个类型不匹配,编译器就会报错。
③ 简单描述编译的几个处理步骤
编译过程分为分析和综合两个部分,并进一步划分为词法分析、语法分析、语义分析、代码优化、存储分配和代码生成等六个相继的逻辑步骤。这六个步骤只表示编译程序各部分之间的逻辑联系,而不是时间关系。
编译过程既可以按照这六个逻辑步骤顺序地执行,也可以按照平行互锁方式去执行。在确定编译程序的具体结构时,常常分若干遍实现。对于源程序或中间语言程序,从头到尾扫视一次并实现所规定的工作称作一遍。每一遍可以完成一个或相连几个逻辑步骤的工作。
(3)便于与编译扩展阅读:
对于c编译程序来说,其语言的特点如下:
1、c语言是一种结构化语言。它层次清晰,便于按模块化方式组织程序,易于调试和维护,而且表现能力和处理能力极强。
2、c语言具有丰富的运算符和数据类型,便于实现各类复杂的数据结构。它还可以直接访问内存的物理地址,进行位(bit)一级的操作。
3、由于c语言实现了对硬件的编程操作,因此集高级语言和低级语言的功能于一体。它既可用于系统软件的开发,也适合于应用软件的开发。
4、此外,c语言还具有效率高、可移植性强等特点。因此它广泛地移植到了各类各型计算机上,从而形成了多种版本。
④ 编译程序是什么意思编译是什么意思
编译程序(Compiler,compiling program)也称为编译器,是指把用高级程序设计语言书写的源程序,翻译成等价的机器语言格式目标程序的翻译程序。
解释程序是一种语言处理程序,在词法、语法和语义分析方面与编译程序的工作原理基本相同,但在运行用户程序时,它直接执行源程序或源程序的内部形式(中间代码)。
(4)便于与编译扩展阅读:
结构:
编译过程分为分析和综合两个部分,并进一步划分为词法分析、语法分析、语义分析、代码优化、存储分配和代码生成等六个相继的逻辑步骤。这六个步骤只表示编译程序各部分之间的逻辑联系,而不是时间关系。
编译过程既可以按照这六个逻辑步骤顺序地执行,也可以按照平行互锁方式去执行。在确定编译程序的具体结构时,常常分若干遍实现。对于源程序或中间语言程序,从头到尾扫视一次并实现所规定的工作称作一遍。每一遍可以完成一个或相连几个逻辑步骤的工作。
可以把词法分析作为第一遍;语法分析和语义分析作为第二遍;代码优化和存储分配作为第三遍;代码生成作为第四遍。反之,为了适应较小的存储空间或提高目标程序质量,也可以把一个逻辑步骤的工作分为几遍去执行。
⑤ c语言程序,预编译的作用
我们在用c做开发的时候,有时候项目很大,所写的程序会很长。这样我们如果还是写在一个文件中,会出现管理上的问题和查看上的不方便,因此我们可以分多个文件写我们的程序,这样把一个功能的程序写到一个文件里,便于查看也便于管理。但是把他们合起来的时候。头文件会多次包含预编译,预编译的处理就可以用来防止头文件的重复包含和编译。
第二,使用宏定义可以提高程序的通用性和易读性,减少不一致性,减少输入错误便于修改。展开宏也是预编译处理中的一项功能。
还有条件编译处理也是预处理中的一项功能。
⑥ 如何更好的掌握编译器的设计与实现
1. 阅读相关书籍:编译原理、编译器设计、编译器实现等;
2. 自学相关编程语言:C、C++、Java等;
3. 实践:可以使用开源的编译器框架,例如ANTLR,搭建自己的编译器;
4. 了解编译器的各个组成部分,并学习它们的工作原理;
5. 阅读技术文章,了解编译器的设计和实现的最新进展;
6. 加入开源项目,编写和维护编译器;
7. 在论坛上交流,和更多的编译器开发者分享心得体会;
8. 参加学术会议,接触到最新的研究成果;
9. 尝试着自己设计一个编译器,用实践来加深理解。
⑦ “编译”与“编译器”是什么意思
编译是动词
编译器是名词
编译(compilation , compile)
1、利用编译程序从源语言编写的源程序产生目标程序的过程。
2、用编译程序产生目标程序的动作。
编译就是把高级语言变成计算机可以识别的2进制语言,计算机只认识1和0,编译程序把人们熟悉的语言换成2进制的。
编译程序把一个源程序翻译成目标程序的工作过程分为五个阶段:词法分析;语法分析;中间代码生成;代码优化;目标代码生成。主要是进行词法分析和语法分析,又称为源程序分析,分析过程中发现有语法错误,给出提示信息。
(1) 词法分析
词法分析的任务是对由字符组成的单词进行处理,从左至右逐个字符地对源程序进行扫描,产生一个个的单词符号,把作为字符串的源程序改造成为单词符号串的中间程序。执行词法分析的程序称为词法分析程序或扫描器。
源程序中的单词符号经扫描器分析,一般产生二元式:单词种别;单词自身的值。单词种别通常用整数编码,如果一个种别只含一个单词符号,那么对这个单词符号,种别编码就完全代表它自身的值了。若一个种别含有许多个单词符号,那么,对于它的每个单词符号,除了给出种别编码以外,还应给出自身的值。
词法分析器一般来说有两种方法构造:手工构造和自动生成。手工构造可使用状态图进行工作,自动生成使用确定的有限自动机来实现。
(2) 语法分析
编译程序的语法分析器以单词符号作为输入,分析单词符号串是否形成符合语法规则的语法单位,如表达式、赋值、循环等,最后看是否构成一个符合要求的程序,按该语言使用的语法规则分析检查每条语句是否有正确的逻辑结构,程序是最终的一个语法单位。编译程序的语法规则可用上下文无关文法来刻画。
语法分析的方法分为两种:自上而下分析法和自下而上分析法。自上而下就是从文法的开始符号出发,向下推导,推出句子。而自下而上分析法采用的是移进归约法,基本思想是:用一个寄存符号的先进后出栈,把输入符号一个一个地移进栈里,当栈顶形成某个产生式的一个候选式时,即把栈顶的这一部分归约成该产生式的左邻符号。
(3) 中间代码生成
中间代码是源程序的一种内部表示,或称中间语言。中间代码的作用是可使编译程序的结构在逻辑上更为简单明确,特别是可使目标代码的优化比较容易实现。中间代码即为中间语言程序,中间语言的复杂性介于源程序语言和机器语言之间。中间语言有多种形式,常见的有逆波兰记号、四元式、三元式和树。
(4) 代码优化
代码优化是指对程序进行多种等价变换,使得从变换后的程序出发,能生成更有效的目标代码。所谓等价,是指不改变程序的运行结果。所谓有效,主要指目标代码运行时间较短,以及占用的存储空间较小。这种变换称为优化。
有两类优化:一类是对语法分析后的中间代码进行优化,它不依赖于具体的计算机;另一类是在生成目标代码时进行的,它在很大程度上依赖于具体的计算机。对于前一类优化,根据它所涉及的程序范围可分为局部优化、循环优化和全局优化三个不同的级别。
(5) 目标代码生成
目标代码生成是编译的最后一个阶段。目标代码生成器把语法分析后或优化后的中间代码变换成目标代码。目标代码有三种形式:
① 可以立即执行的机器语言代码,所有地址都重定位;
② 待装配的机器语言模块,当需要执行时,由连接装入程序把它们和某些运行程序连接起来,转换成能执行的机器语言代码;
③ 汇编语言代码,须经过汇编程序汇编后,成为可执行的机器语言代码。
目标代码生成阶段应考虑直接影响到目标代码速度的三个问题:一是如何生成较短的目标代码;二是如何充分利用计算机中的寄存器,减少目标代码访问存储单元的次数;三是如何充分利用计算机指令系统的特点,以提高目标代码的质量。
编译器,是将便于人编写,阅读,维护的高级计算机语言翻译为计算机能解读、运行的低阶机器语言的程序。编译器将原始程序(Source program)作为输入,翻译产生使用目标语言(Target language)的等价程序。源代码一般为高阶语言 (High-level language), 如 Pascal、C++、Java 等,而目标语言则是汇编语言或目标机器的目标代码(Object code),有时也称作机器代码(Machine code)。
一个现代编译器的主要工作流程如下:
源代码 (source code) → 预处理器 (preprocessor) → 编译器 (compiler) → 汇编程序 (assembler) → 目标代码 (object code) → 连接器 (Linker) → 可执行程序 (executables)
工作原理
[编辑本段]
编译是从源代码(通常为高阶语言)到能直接被计算机或虚拟机执行的目标代码(通常为低阶语言或机器语言)的翻译过程。然而,也存在从低阶语言到高阶语言的编译器,这类编译器中用来从由高阶语言生成的低阶语言代码重新生成高阶语言代码的又被叫做反编译器。也有从一种高阶语言生成另一种高阶语言的编译器,或者生成一种需要进一步处理的的中间代码的编译器(又叫级联)。
典型的编译器输出是由包含入口点的名字和地址, 以及外部调用(到不在这个目标文件中的函数调用)的机器代码所组成的目标文件。一组目标文件,不必是同一编译器产生,但使用的编译器必需采用同样的输出格式,可以链接在一起并生成可以由用户直接执行的可执行程序。
编译器种类
[编辑本段]
编译器可以生成用来在与编译器本身所在的计算机和操作系统(平台)相同的环境下运行的目标代码,这种编译器又叫做“本地”编译器。另外,编译器也可以生成用来在其它平台上运行的目标代码,这种编译器又叫做交叉编译器。交叉编译器在生成新的硬件平台时非常有用。“源码到源码编译器”是指用一种高阶语言作为输入,输出也是高阶语言的编译器。例如: 自动并行化编译器经常采用一种高阶语言作为输入,转换其中的代码,并用并行代码注释对它进行注释(如OpenMP)或者用语言构造进行注释(如FORTRAN的DOALL指令)。
预处理器(preprocessor)
作用是通过代入预定义等程序段将源程序补充完整。
编译器前端(frontend)
前端主要负责解析(parse)输入的源代码,由语法分析器和语意分析器协同工作。语法分析器负责把源代码中的‘单词’(Token)找出来,语意分析器把这些分散的单词按预先定义好的语法组装成有意义的表达式,语句 ,函数等等。 例如“a = b + c;”前端语法分析器看到的是“a, =, b , +, c;”,语意分析器按定义的语法,先把他们组装成表达式“b + c”,再组装成“a = b + c”的语句。 前端还负责语义(semantic checking)的检查,例如检测参与运算的变量是否是同一类型的,简单的错误处理。最终的结果常常是一个抽象的语法树(abstract syntax tree,或 AST),这样后端可以在此基础上进一步优化,处理。
编译器后端(backend)
编译器后端主要负责分析,优化中间代码(Intermediate representation)以及生成机器代码(Code Generation)。
一般说来所有的编译器分析,优化,变型都可以分成两大类: 函数内(intraproceral)还是函数之间(interproceral)进行。很明显,函数间的分析,优化更准确,但需要更长的时间来完成。
编译器分析(compiler analysis)的对象是前端生成并传递过来的中间代码,现代的优化型编译器(optimizing compiler)常常用好几种层次的中间代码来表示程序,高层的中间代码(high level IR)接近输入的源代码的格式,与输入语言相关(language dependent),包含更多的全局性的信息,和源代码的结构;中层的中间代码(middle level IR)与输入语言无关,低层的中间代码(Low level IR)与机器语言类似。 不同的分析,优化发生在最适合的那一层中间代码上。
常见的编译分析有函数调用树(call tree),控制流程图(Control flow graph),以及在此基础上的 变量定义-使用,使用-定义链(define-use/use-define or u-d/d-u chain),变量别名分析(alias analysis),指针分析(pointer analysis),数据依赖分析(data dependence analysis)等等。
上述的程序分析结果是编译器优化(compiler optimization)和程序变形(compiler transformation)的前提条件。常见的优化和变新有:函数内嵌(inlining),无用代码删除(Dead code elimination),标准化循环结构(loop normalization),循环体展开(loop unrolling),循环体合并,分裂(loop fusion,loop fission),数组填充(array padding),等等。 优化和变形的目标是减少代码的长度,提高内存(memory),缓存(cache)的使用率,减少读写磁盘,访问网络数据的频率。更高级的优化甚至可以把序列化的代码(serial code)变成并行运算,多线程的代码(parallelized,multi-threaded code)。
机器代码的生成是优化变型后的中间代码转换成机器指令的过程。现代编译器主要采用生成汇编代码(assembly code)的策略,而不直接生成二进制的目标代码(binary object code)。即使在代码生成阶段,高级编译器仍然要做很多分析,优化,变形的工作。例如如何分配寄存器(register allocatioin),如何选择合适的机器指令(instruction selection),如何合并几句代码成一句等等。
编译语言与直译语言对比
[编辑本段]
许多人将高阶程序语言分为两类: 编译型语言 和 直译型语言 。然而,实际上,这些语言中的大多数既可用编译型实现也可用直译型实现,分类实际上反映的是那种语言常见的实现方式。(但是,某些直译型语言,很难用编译型实现。比如那些允许 在线代码更改 的直译型语言。)
历史
[编辑本段]
上世纪50年代,IBM的John Backus带领一个研究小组对FORTRAN语言及其编译器进行开发。但由于当时人们对编译理论了解不多,开发工作变得既复杂又艰苦。与此同时,Noam Chomsky开始了他对自然语言结构的研究。他的发现最终使得编译器的结构异常简单,甚至还带有了一些自动化。Chomsky的研究导致了根据语言文法的难易程度以及识别它们所需要的算法来对语言分类。正如现在所称的Chomsky架构(Chomsky Hierarchy),它包括了文法的四个层次:0型文法、1型文法、2型文法和3型文法,且其中的每一个都是其前者的特殊情况。2型文法(或上下文无关文法)被证明是程序设计语言中最有用的,而且今天它已代表着程序设计语言结构的标准方式。分析问题(parsing problem,用于上下文无关文法识别的有效算法)的研究是在60年代和70年代,它相当完善的解决了这个问题。现在它已是编译原理中的一个标准部分。
有限状态自动机(Finite Automaton)和正则表达式(Regular Expression)同上下文无关文法紧密相关,它们与Chomsky的3型文法相对应。对它们的研究与Chomsky的研究几乎同时开始,并且引出了表示程序设计语言的单词的符号方式。
人们接着又深化了生成有效目标代码的方法,这就是最初的编译器,它们被一直使用至今。人们通常将其称为优化技术(Optimization Technique),但因其从未真正地得到过被优化了的目标代码而仅仅改进了它的有效性,因此实际上应称作代码改进技术(Code Improvement Technique)。
当分析问题变得好懂起来时,人们就在开发程序上花费了很大的功夫来研究这一部分的编译器自动构造。这些程序最初被称为编译器的编译器(Compiler-compiler),但更确切地应称为分析程序生成器(Parser Generator),这是因为它们仅仅能够自动处理编译的一部分。这些程序中最着名的是Yacc(Yet Another Compiler-compiler),它是由Steve Johnson在1975年为Unix系统编写的。类似的,有限状态自动机的研究也发展了一种称为扫描程序生成器(Scanner Generator)的工具,Lex(与Yacc同时,由Mike Lesk为Unix系统开发)是这其中的佼佼者。
在70年代后期和80年代早期,大量的项目都贯注于编译器其它部分的生成自动化,这其中就包括了代码生成。这些尝试并未取得多少成功,这大概是因为操作太复杂而人们又对其不甚了解。
编译器设计最近的发展包括:首先,编译器包括了更加复杂算法的应用程序它用于推断或简化程序中的信息;这又与更为复杂的程序设计语言的发展结合在一起。其中典型的有用于函数语言编译的Hindley-Milner类型检查的统一算法。其次,编译器已越来越成为基于窗口的交互开发环境(Interactive Development Environment,IDE)的一部分,它包括了编辑器、连接程序、调试程序以及项目管理程序。这样的IDE标准并没有多少,但是对标准的窗口环境进行开发已成为方向。另一方面,尽管近年来在编译原理领域进行了大量的研究,但是基本的编译器设计原理在近20年中都没有多大的改变,它现在正迅速地成为计算机科学课程中的中心环节。
在九十年代,作为GNU项目或其它开放源代码项目标一部分,许多免费编译器和编译器开发工具被开发出来。这些工具可用来编译所有的计算机程序语言。它们中的一些项目被认为是高质量的,而且对现代编译理论感兴趣的人可以很容易的得到它们的免费源代码。
大约在1999年,SGI公布了他们的一个工业化的并行化优化编译器Pro64的源代码,后被全世界多个编译器研究小组用来做研究平台,并命名为Open64。Open64的设计结构好,分析优化全面,是编译器高级研究的理想平台。
⑧ 编译过程中,源程序为什么要通过中间代码生成目标程序
源程序是指程序员编写的代码,可以被编译程序编译为目标程序。
如果是c++,那么后缀为.cpp
目标程序是编译程序将源程序编译后的结果,如果是c++,那么后缀是.o
编译程序一般是编译器公司(比如微软
intel他们都生产编译器)做的,它将源代码转化为机器可识别的文件,经过链接,生成可执行程序。
解释程序即解释器,它不需要经过编译阶段即可根据用户源程序执行。
程序语言分编译类和解释类语言。
⑨ 程序的编译与解释有什么区别
程序的编译和解释不是那么容易解释清楚的,建议先了解一下基本的知识,如果想要详细了解的话,建议去查一下,专业的书籍。
解释型语言的实现中,翻译器并不产生目标机器代码,而是产生易于执行的中间代码,这种中间代码与机器代码是不同的,中间代码的解释是由软件支持的,不能直接使用硬件,软件解释器通常会导致执行效率较低。对于解释型Basic语言,需要一个专门的解释器解释执行Basic程序,每条语言只有在执行才被翻译。这种解释型语言每执行一次就翻译一次,因而效率低下。
⑩ 编译原理全部的名词解释
书上有别那么懒!.
编译过程的六个阶段:词法分析,语法分析,语义分析,中间代码生成,代码优化,目标代码生成
解释程序:把某种语言的源程序转换成等价的另一种语言程序——目标语言程序,然后再执行目标程序.解释方式是接受某高级语言的一个语句输入,进行解释并控制计算机执行,马上得到这句的执行结果,然后再接受下一句.
编译程序:就是指这样一种程序,通过它能够将用高级语言编写的源程序转换成与之在逻辑上等价的低级语言形式的目标程序(机器语言程序或汇编语言程序).
解释程序和编译程序的根本区别:是否生成目标代码
句子的二义性(这里的二义性是指语法结构上的.):文法G[S]的一个句子如果能找到两种不同的最左推导(或最右推导),或者存在两棵不同的语法树,则称这个句子是二义性的.
文法的二义性:一个文法如果包含二义性的句子,则这个文法是二义文法,否则是无二义文法.
LL(1)的含义:(LL(1)文法是无二义的; LL(1)文法不含左递归)
第1个L:从左到右扫描输入串 第2个L:生成的是最左推导
1 :向右看1个输入符号便可决定选择哪个产生式
某些非LL(1)文法到LL(1)文法的等价变换: 1. 提取公因子 2. 消除左递归
文法符号的属性:单词的含义,即与文法符号相关的一些信息.如,类型、值、存储地址等.
一个属性文法(attribute grammar)是一个三元组A=(G, V, F)
G:上下文无关文法.
V:属性的有穷集.每个属性与文法的一个终结符或非终结符相连.属性与变量一样,可以进行计算和传递.
F:关于属性的断言或谓词(一组属性的计算规则)的有穷集.断言或语义规则与一个产生式相联,只引用该产生式左端或右端的终结符或非终结符相联的属性.
综合属性:若产生式左部的单非终结符A的属性值由右部各非终结符的属性值决定,则A的属性称为综合属
继承属性:若产生式右部符号B的属性值是根据左部非终结符的属性值或者右部其它符号的属性值决定的,则B的属性为继承属性.
(1)非终结符既可有综合属性也可有继承属性,但文法开始符号没有继承属性.
(2) 终结符只有综合属性,没有继承属性,它们由词法程序提供.
在计算时: 综合属性沿属性语法树向上传递;继承属性沿属性语法树向下传递.
语法制导翻译:是指在语法分析过程中,完成附加在所使用的产生式上的语义规则描述的动作.
语法制导翻译实现:对单词符号串进行语法分析,构造语法分析树,然后根据需要构造属性依赖图,遍历语法树并在语法树的各结点处按语义规则进行计算.
中间代码(中间语言)
1、是复杂性介于源程序语言和机器语言的一种表示形式.
2、一般,快速编译程序直接生成目标代码.
3、为了使编译程序结构在逻辑上更为简单明确,常采用中间代码,这样可以将与机器相关的某些实现细节置于代码生成阶段仔细处理,并且可以在中间代码一级进行优化工作,使得代码优化比较容易实现.
何谓中间代码:源程序的一种内部表示,不依赖目标机的结构,易于代码的机械生成.
为何要转换成中间代码:(1)逻辑结构清楚;利于不同目标机上实现同一种语言.
(2)便于移植,便于修改,便于进行与机器无关的优化.
中间代码的几种形式:逆波兰记号 ,三元式和树形表示 ,四元式
符号表的一般形式:一张符号表的的组成包括两项,即名字栏和信息栏.
信息栏包含许多子栏和标志位,用来记录相应名字和种种不同属性,名字栏也称主栏.主栏的内容称为关键字(key word).
符号表的功能:(1)收集符号属性 (2) 上下文语义的合法性检查的依据: 检查标识符属性在上下文中的一致性和合法性.(3)作为目标代码生成阶段地址分配的依据
符号的主要属性及作用:
1. 符号名 2. 符号的类型 (整型、实型、字符串型等))3. 符号的存储类别(公共、私有)
4. 符号的作用域及可视性 (全局、局部) 5. 符号变量的存储分配信息 (静态存储区、动态存储区)
存储分配方案策略:静态存储分配;动态存储分配:栈式、 堆式.
静态存储分配
1、基本策略
在编译时就安排好目标程序运行时的全部数据空间,并能确定每个数据项的单元地址.
2、适用的分配对象:子程序的目标代码段;全局数据目标(全局变量)
3、静态存储分配的要求:不允许递归调用,不含有可变数组.
FORTRAN程序是段结构,不允许递归,数据名大小、性质固定. 是典型的静态分配
动态存储分配
1、如果一个程序设计语言允许递归过程、可变数组或允许用户自由申请和释放空间,那么,就需要采用动态存储管理技术.
2、两种动态存储分配方式:栈式,堆式
栈式动态存储分配
分配策略:将整个程序的数据空间设计为一个栈.
【例】在具有递归结构的语言程序中,每当调用一个过程时,它所需的数据空间就分配在栈顶,每当过程工作结束时就释放这部分空间.
过程所需的数据空间包括两部分
一部分是生存期在本过程这次活动中的数据对象.如局部变量、参数单元、临时变量等;
另一部分则是用以管理过程活动的记录信息(连接数据).
活动记录(AR)
一个过程的一次执行所需要的信息使用一个连续的存储区来管理,这个区 (块)叫做一个活动记录.
构成
1、临时工作单元;2、局部变量;3、机器状态信息;4、存取链;
5、控制链;6、实参;7、返回地址
什么是代码优化
所谓优化,就是对代码进行等价变换,使得变换后的代码运行结果与变换前代码运行结果相同,而运行速度加快或占用存储空间减少.
优化原则:等价原则:经过优化后不应改变程序运行的结果.
有效原则:使优化后所产生的目标代码运行时间较短,占用的存储空间较小.
合算原则:以尽可能低的代价取得较好的优化效果.
常见的优化技术
(1) 删除多余运算(删除公共子表达式) (2) 代码外提 +删除归纳变量+ (3)强度削弱; (4)变换循环控制条件 (5)合并已知量与复写传播 (6)删除无用赋值
基本块定义
程序中只有一个入口和一个出口的一段顺序执行的语句序列,称为程序的一个基本块.
给我分数啊.