1.4编译阶段的组合 在第1,2节所讨论的编译过程中阶段的划分是编译程序的逻辑组织。有时,常常把编 译的过程分为前端(front end)和后端(back end),前端由那样一些阶段组成:这些阶段的 工作主要依赖于源语言而与目标机无关。通常这些阶段包括词法分析、语法分析、语义分 析和中间代码生成,某些优化工作也可在前端做,也包括与前端每个阶段相关的出错处理 工作和符号表管理工作,后端工作指那些依赖于目标机面一般不依榄源语言,只与中间代 码有关的那些阶段,即目标代码生成,以及相关出错处理和符号表操作。 若按照这种组合方式实现编译程序,可以设想,某一编译程序的前端加上相应不同的 后端则可以为不同的机器构成同一个源语言的编译程序,也可以设想,不同语言编译的前 端生成同一种中间语言,再使用一个共同的后端,则可为同一机器生成几个语言的编译程 序。 一个编译过程可由一遍、两遍或多遍完成。所谓“遍”,也称作“趟”,是对源程序或其等 价的中间语言程序从头到尾扫视并完成规定任务的过程。每一遍扫视可完成上述一个阶 段或多个阶段的工作,例如一遍可以只完成词法分析工作,一遍完成词法分析和语法分析 工作:甚至一瑞完成整个绾译工作。对于多遍的编译程序,第一遍的输入是用户书写的游 程序,最后一遍的输出是目标语言程序,其余是上一遍的输出为下一遍的输入。在实际的 编译系统的设计中,编译的几个阶段的工作究竟应该怎样组合,即编译程序究竟分成几 遍,参考的因素主要是源语言和机器(目标机)的特征。比如源语言的结构直接影响编译的 遍的划分:像PL/1或A1.GOL68那样的语言,允许名字的说明出现在名字的使用之后, 那么在看到名字之前是不便为包含该名字的表达式生成代码的,这种语言的编译程序至 少分成两遍才容易生成代码。另外机器的情况,即编译程序工作的环境也影响编译程序的 遍数的划分。 一个多遍的编译程序可以较之一遍的编译程序少占内存,遍数多一点,整个 编译程序的逻辑结构可能清晰些,但遍数多即意味着增加读写中间文件的次数,势必消耗 较多时间,显然会比一遍的编译要慢。 1.5编译技术和软件工具 为了提高软件开发的效率和保证质量,人们除了要在软件工程中对软件开发过程所 要遵循的规范化或标准化外,还尽量使用先进的软件开发技术和相应的软件工具,而大部 分软件工具的开发,常常要用到编译技术和方法。实际上编译程序本身也是一种软件开发 工具。为了提高编程效率,缩短调试时间,软件工作人员研制了不少对源程序处理的工具。 这些工具的开发不同程度地用到编译程序各个部分的技术和方法。下面仅是一些例子 1.语言的结构化编辑器结构化编辑器是引导用户在语言的语法制导下编制程序, 能自动地提供关键字和与其匹配的关健字,如if后必须有then,begin和end的配对,左 右括号的配对等,这样可以减少语法上的错误,可加快对源程序的调试,提高效率和质量。 2.语言程序的调试工具调试是软件开发过程中一个重要环节,结构化编辑器只能 7
解决语法错误的问题,而对一个已通过编译的程序来说,需进一步了解的是程序执行的结 果与编程人员的意图是否一致,程序的执行是否实现预计的算法和功能。这种对算法的错 误或程序没能反应算法的功能等错误就需用调试器来协助解决调试器的功能愈强,实现 愈复杂,但它必须与语法分析,语义处理有紧密联系 3.语言程序测试工具语言程序的测试工具有两种:静态分析器和动态测试器。 静态分析器是对源程序进行静态地分析。它对源程序进行语法分析并制定相应表 格,检查变量定值与引用的关系。如某变量未被赋值就被引用,或定值后未被引用,或多余 的源代码等一些编译程序的语法分析发现不了的错误。 动态测试工具是在源程序的适当位置插入某些信息,并用测试用例记录(显示语句或 函数)程序运行时的实际路径。将运行结果与期望的结果进行比较分析,帮助编程人员查 找问题。这种测试工具在国内已有开发,如FORTRAN语言和C语言的测试工具, 4.高级语言之间的转换工具由于计算机硬件的不断更新换代,更新更好的程序设 计语言的推出为提高计算机的使用效率提供了良好条件,然而一些已有的非常成熟的软 件如何在新机器新语言情况下使用呢?为了减少重新编制程序所耗费的人力和时间,就要 解决如何把一种高级语言转换成另一种高级语言,乃至汇编语言转换成高级语言的问题。 这种转换工作要对被转换的语言进行词法和语法分析,只不过生成的目标语言是另一种 高级语言而已。这与实现一个完整的编译程序相比工作量要少些。在国内已研制出C, PASCAL,FORTRAN到Ada的翻泽器和IBM47OO汇编到C的转换器,其效果很好。 5,并行编译技术由于近几年并行机及多处理机的发展,对软件的并行处理技术提 出了新的要求。特别是并行编译技术发展很快,目前处理并行编译技术有两种方法, 第一种方法,运用重构技术把已有的串行语言编写的程序经过相关分析,分解成可并 行的成分,分配到多CPU或多处理机上运行,这种技术在国内已有FORTRAN和C语 言的并行重构处理系统,相当成功。 第二种方法,即在程序设计语言机制上允许用户自己编写并行语言程序,这当然比编 写串行语言对编程人员提出的要求更多。即用户自己必须知道程序各模块之间逻辑结构 关系及调用关系乃至运算量,以确定哪些模块可以并行执行,若编程者能按程序设计情况 编出并行程序,无疑并行程序效率将比第一种方法要好。 编译技术在软件工程的其它领域中也有广泛应用,本章不再介绍。 ·8
第2章PL/0编译程序的实现 为了使读者在系统地学习本教材以下各章节之前,对编译程序的构造得到一些感性 认识和初步了解,本章推荐了世界若名计算机科学家N.W1rh先生编写的“PL/0语言的 编译程序”,并对其实现过程作了概括的分析说明,作为读者阅读PL0语言编译程序文 本的提示。对PL/O语言文法的表示只给出语法图和扩充的巴科斯-瑙尔范式(EBNF)的 描述形式,不作文法理论上的讨论。由于PL/0语言功能简单、结构清晰、可读性强,而又 具备了一般高级语言的必须部分,因而PL0语言的编译程序能充分体现一个高级语言 编译程序实现的基本技术和步骤。因此,“PL0语言编译程序”是 个非常合适的小型编 译程序的教学模型。所以,阅读“PL/0语言编译程序”文本后,可帮助读者对编译程序的 实现建立起整体概念。 2.1PL/0语言描述 本节将用语法图和扩充的巴科斯-瑙尔范式(EBNF)两种形式给出PL/0语言的语法 描述。 2.1.1PL/0语言的语法描述图 用语法图描述语法规则的优点是直观、易读。在图2.1的语法图中用椭圆和圆圈中的 程序一分程序一一⊙ 图2.1(a)程序语法描述图 分得序 ⊙ 0 CD-D一O一分程序 一一语句· 图216)分程序语法描述图 9
语句十 一den一(○一表达式 -cin-语句 钩⊙ -国一条件一©一语有 一的一条作-⊙一一曙向 回0c80 -四-①T表达① O 图21(c)语句语法描述图 (o一一表达式 表达式 图2.1(d)条件语法描述困 a-8 图2.1(e)表达式语法描述图 项一一因子 因子 图21()项语法描述图 ·10
因子 ident○ number ⑦一表达式一① 图2.1(g)因子语法描述图 英文字表示终结符,用长方形内的中文字表示非终结符。所谓终结符,是构成语言文法的 单词,是语法成分的最小单位。而每个非终结符是一个语法成分,在书写语言程序时并不 出现,它是由终结符和非终结符串、或终结符串定义的。例如,程序是由非终结符“分程 序'和终结符“.”这个串定义的,由于对某些非终结符可以递归定义,如:图中分程序、表达 式和语句,这就使得无穷的句子集可用有穷的文法描述。而通常称第一个非终结符如‘程 序’为文法的开始符号。 2.1.2PL/0语言文法的EBNF表示 EBNF表示的符号说明。 ):用左右尖括号括起来的中文字表示语法构造成分,或称语法单位,为非终结 符。 :=’:该符号的左部由右部定义,可读作‘定义为’。 ':表示或,为左部可由多个右部定义。 {':表示花括号内的语法成分可以重复。在不加上下界时可重复0到任意次数。 有上下界时为可重复次数的限制。 []':表示方括号内的成分为任选项。 ‘()':表示圆括号内的成分优先。 PL/O语言文法的EBNF表示为: 《程序):=分程序) (分程序):=[〈常量说明部分)门[(变量说明部分)门[〈过程说明部分)门语句》 (常量说明部分):=CONST(常量定义){,〈常量定义)}: (常量定义):=(标识符=〈无符号整数) 《无符号整数):=(数字){(数字)》 〈变量说明部分):=VAR〈标识符),(标识符)}: 〈标识符):=(字母》((字母)1(数字)》 〈过程说明部分:=〈过程首部)(分程序){,(过程说明部分)}: (过程首部):=PROCEDURE(标识符): (语句):=〈赋值语句)(条件语句)1〈当型循环语句)1(过程调用语句)1〈读语句)川 (写语句)1〈复合语句)(空 《赋值语句):=〈标识符):=(表达式) (复合语句):=BEGIN(语句){,(语句)}END 条件):=〈表达式)(关系运算符)(表达式)IODD(表达式) 11