第七章语义分析与中间代码生成
07-第7章-中间代码生成-编译原理PDF精讲课件-中国科技大学(共13讲)

中国科学技术大学 计算机科学与技术学院 陈意云
第七章 中间代码生成
记号 分析 流 器 本章内容
–介绍几种常用的中间表示:后缀表示、图形表示 和三地址代码 –用语法制导定义和翻译方案来说明源语言的各种 构造怎样被翻译成中间形式
静态 检查 器
中间 代码 中间 代码 生成 代码 生成 器 器
7.1 中 间 语 言
7.1.2 图形表示 • 语法树是一种图形化的中间表示 • 有向无环图也是一种中间表示
assign a + + a assign +
+ c uminus d uminus c c d d b b (b) DAG (a) 语法树 a = (b + cd) + cd的图形表示
7.1 中 间 语 言
7.1.4 静态单赋值形式 • 一种便于某些代码优化的中间表示 • 和三地址代码的主要区别
– 所有赋值指令都是对不同名字的变量的赋值 – 一个变量在不同路径上都定值的解决办法 if (flag) x = 1; else x = 1; y = x a; 改成 if (flag) x1 = 1; else x2 = 1; x3 = (x1, x2); //由flag的值决定用x1还是x2
E E1 E2 E.nptr = mkNode( ‘’, E1.nptr, E2.nptr) E.nptr = mkUNode( ‘uminus’, E1.nptr) E E1 E (E1) F id E.nptr = E1.nptr E.nptr = mkLeaf (id, id.entry)
符号表实例
7.2 声 明 语 句
• 符号表的特点
–各过程有各自的符号表 –符号表之间有双向链 –构造符号表时需要符号表栈 –构造符号表需要活动记录栈 sort var a:…; x:…; readarray var i:…; exchange quicksort var k, v:…; partition var i, j:…;
编译原理实验报告

编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。
二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。
三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。
在本次实验中,我们使用有限自动机的理论来设计词法分析器。
首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。
然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。
在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。
(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。
在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。
首先,我们根据给定的语法规则,编写了相应的递归函数。
每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。
在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。
(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。
在本次实验中,我们使用了四元式作为中间代码的表示形式。
在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。
同时,根据语法树的结构,生成相应的四元式中间代码。
(四)代码优化代码优化的目的是提高生成代码的质量和效率。
在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。
通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。
第7章 语义分析与中间代码生成

(4) 无条件转移语句goto L,即下一个将被执 行的语句是标号为L的语句。 (5) 条件转移语句if x rop y goto L,其中rop为 关系运算符,如<、<=、==、!=、>、>=等。 若x和y满足关系rop就转去执行标号为L的语 句,否则继续按顺序执行本语句的下一条语 句。
(6) 过程调用语句par x和call p,n。源程序中的 过程调用语句p(x1, x2, …, xn)可用下列三地址 代码表示: par x1 par x2 par xn call p,n 其中,整数n为实参个数。 过程返回语句为return y,其中y为返回值, 可选。
{enter(, T.type, offset); offset := offset + T.width} {T.type := int; T.width := 4} {T.type := float; T.width := 8} {T.type := array(num.val, T(1).type); T.width := num.val * T(1).width} {T.type := pointer(T(1).type); T.width := 4}
2.三地址语句的种类 三地址语句非常类似于汇编代码,它可以 有符号标号和各种控制流语句。 常用的三地址语句: (1) x = y op z形式的赋值语句,其中op为二目 的算术运算符或逻辑运算符。 (2) x = op y形式的赋值语句,其中op为一目运 算符,如一目减uminus、逻辑否定not、移位 运算符以及类型转换符。 (3) x = y形式的复制语句,将y的值赋给x。
例如,赋值语句a = b * (c + d)的四元式代码: ① (+, c, d, t1) ② (*, b, t1, t2) ③ (=, t2, _, a) 约定:一元运算符一律使用arg1。此外,如果 op是一个算术或逻辑运算符,则result总是一 个新引进的临时变量,它用来存放运算结果。 结论:四元式出现的顺序与表达式计值的顺序 是一致的,四元式之间的联系是通过临时变量 实现的。四元式由于其表示更接近程序设计的 习惯而成为一种普遍采用的中间代码形式。
编译原理第三版课后习题答案

编译原理第三版课后习题答案编译原理是计算机科学中的一门重要课程,它研究的是如何将高级程序语言转换为机器语言的过程。
而《编译原理》第三版是目前被广泛采用的教材之一。
在学习过程中,课后习题是巩固知识、提高能力的重要环节。
本文将为读者提供《编译原理》第三版课后习题的答案,希望能够帮助读者更好地理解和掌握这门课程。
第一章:引论习题1.1:编译器和解释器有什么区别?答案:编译器将整个源程序转换为目标代码,然后一次性执行目标代码;而解释器则逐行解释源程序,并即时执行。
习题1.2:编译器的主要任务是什么?答案:编译器的主要任务是将高级程序语言转换为目标代码,包括词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成等过程。
第二章:词法分析习题2.1:什么是词法分析?答案:词法分析是将源程序中的字符序列划分为有意义的词素(token)序列的过程。
习题2.2:请给出识别下列词素的正则表达式:(1)整数:[0-9]+(2)浮点数:[0-9]+\.[0-9]+(3)标识符:[a-zA-Z_][a-zA-Z_0-9]*第三章:语法分析习题3.1:什么是语法分析?答案:语法分析是将词法分析得到的词素序列转换为语法树的过程。
习题3.2:请给出下列文法的FIRST集和FOLLOW集:S -> aAbA -> cA | ε答案:FIRST(S) = {a}FIRST(A) = {c, ε}FOLLOW(S) = {$}FOLLOW(A) = {b}第四章:语义分析习题4.1:什么是语义分析?答案:语义分析是对源程序进行静态和动态语义检查的过程。
习题4.2:请给出下列文法的语义动作:S -> if E then S1 else S2答案:1. 计算E的值2. 如果E的值为真,则执行S1;否则执行S2。
第五章:中间代码生成习题5.1:什么是中间代码?答案:中间代码是一种介于源代码和目标代码之间的表示形式,它将源代码转换为一种更容易进行优化和转换的形式。
编译原理与自动化代码生成

编译原理与自动化代码生成编译原理是计算机科学中的一个重要领域,它研究如何将高级程序语言翻译为计算机能够执行的低级指令,从而实现程序的执行。
自动化代码生成是编译原理中的一个关键步骤,它通过将程序中的高级语言代码转换为计算机识别的机器码,实现程序功能的自动化生成。
一、编译原理的基本概念与流程编译原理涉及到词法分析、语法分析、语义分析、中间代码生成、代码优化和代码生成等多个环节。
下面将简要介绍编译原理的基本流程。
1. 词法分析词法分析器将源代码分割为一个个词法单元,如关键字、标识符、运算符、常量等,并将这些词法单元以标记的形式传递给语法分析器。
2. 语法分析语法分析器将词法分析器传递的标记组织成语法树,检查程序语法的正确性。
常用的语法分析方法有递归下降分析、LL(1)分析和LR分析等。
3. 语义分析语义分析器主要对程序的语义进行检查,包括类型检查、符号表管理、语法错误修复等。
它会生成中间代码,为代码生成和优化做准备。
4. 中间代码生成中间代码是一种介于源代码和目标代码之间的代码形式,方便进行代码优化和代码生成。
常见的中间代码形式有三地址码、四元式和抽象语法树。
5. 代码优化代码优化是在保持程序功能不变的前提下,通过改进程序结构或重写代码,以提高运行效率。
常见的代码优化技术有常量传播、常量折叠、循环优化等。
6. 代码生成代码生成是将中间代码转换为目标代码的过程。
目标代码可以是可执行代码,也可以是汇编代码,具体取决于编译器的设定。
二、自动化代码生成的意义和方法自动化代码生成旨在提高程序开发的效率和质量,减少开发人员的工作量。
以下是常见的自动化代码生成方法。
1. 模板代码生成模板代码是指在开发过程中频繁出现的、类似的代码片段。
通过定义好模板,利用代码生成工具可以自动根据模板生成对应的代码。
2. 元编程元编程是一种编程范式,它允许程序在运行时生成、修改和执行其他程序。
通过元编程技术,可以实现动态生成代码和扩展程序的功能。
编译原理第七章中间代码生成汇编

*
b
*
b
uminus
c
a= b*-c + b*-c
c abc uminus * bc numinus *+ assign
抽象语法树
• 构造赋值语句语法树的语法制导定义: 产生式
S→id = E E→E1 + E2 E→E1 * E2 E→- E1 E→(E1)
• param x1 • param x2 • …… • param x2 • call p, n n表示实参个数。return y中y为过程返回的一个值
– 形如x = y[i]及x[i] = y的索引赋值。
– 形如x = &y, x = *y和*x = y的地址和指针赋值。象形式。 • 这些语句可以以带有操作符和操作数域的记录 来实现。四元式、三元式及间接三元式是三种 这样的表示。
x = y op z
其中,x、y和z是名字,常量或编译器生成的临时变量 op代表任何操作符(定点运算符、浮点运算符、逻辑运算 符等)
• 像x+y*z这样的表达式要翻译为:
T1 = y * z
T2 = x + T1 其中T1 ,T2为编译时产生的临时变量。
三地址语句的类型
• 三地址语句类似于汇编语言代码。语句可以有 符号标号,而且存在各种控制流语句。
– 临时变量也要填入符号表中。
三元式
• 为了避免把临时变量填入符号表,可以通过计 算临时值语句的位置来引用该临时变量。 • 这样三地址代码的记录只需要三个域op, arg1 和arg。
• 对于单目运算符op, arg1和arg2只需用其一。
编译原理中间代码生成

编译原理中间代码生成在编译原理中,中间代码生成是编译器的重要阶段之一、在这个阶段,编译器将源代码转换成一种中间表示形式,这种中间表示形式通常比源代码抽象得多,同时又比目标代码具体得多。
中间代码既能够方便地进行优化,又能够方便地转换成目标代码。
为什么需要中间代码呢?其一,中间代码可以方便地进行编译器优化。
编译器优化是编译器的一个核心功能,它能够对中间代码进行优化,以产生更高效的目标代码。
在中间代码生成阶段,编译器可以根据源代码特性进行一些优化,例如常量折叠、公共子表达式消除、循环不变式移动等。
其二,中间代码可以方便地进行目标代码生成。
中间代码通常比较高级,比目标代码更具有表达力。
通过中间代码,编译器可以将源代码转换成与目标机器无关的形式,然后再根据目标机器的特性进行进一步的优化和转换,最终生成目标代码。
中间代码生成的过程通常可以分为以下几步:1.词法分析和语法分析:首先需要将源代码转换成抽象语法树。
这个过程涉及到词法分析和语法分析两个步骤。
词法分析将源代码划分成一个个的词法单元,例如标识符、关键字、运算符等等。
语法分析将词法单元组成树状结构,形成抽象语法树。
2.语义分析:在语义分析阶段,编译器会对抽象语法树进行静态语义检查,以确保源代码符合语言的语义规定。
同时,还会进行类型检查和类型推导等操作。
3.中间代码生成:在中间代码生成阶段,编译器会将抽象语法树转换成一种中间表示形式,例如三地址码、四元式、特定的中间代码形式等。
这种中间表示形式通常比较高级,能够方便进行编译器的优化和转换。
4.中间代码优化:中间代码生成的结果通常不是最优的,因为生成中间代码时考虑的主要是功能的正确性,并没有考虑性能的问题。
在中间代码生成之后,编译器会对中间代码进行各种优化,以产生更高效的代码。
例如常量折叠、循环优化、死代码删除等等。
5.中间代码转换:在完成了中间代码的优化之后,编译器还可以对中间代码进行进一步的转换。
这个转换的目的是将中间代码转换成更具体、更低级的形式,例如目标机器的汇编代码。
编译习题答案

习题11-1 说明解释程序和编译程序的区别。
答:通常,翻译程序可分为解释程序、汇编程序和编译程序。
所谓解释程序是一种将源程序按动态顺序逐句进行分析解释编译,边解释边执行、不产生目标程序的一种翻译程序。
这种翻译程序结构简单、占用内存较少,易于在执行过程中对源程序进行修改,但工作效率低,只适合一些规模较小的语言,如解释BASIC等。
而编译程序(也称编译器)是源语言为某种高级语言,目标语言为相应于某一计算机的汇编语言或机器语言的一种翻译程序。
这种编译程序将源程序翻译成执行时可完全独立于源程序的经优化的目标语言代码,因而运行效率高。
更为重要的是,它使工作于高级语言环境下的程序设计人员,不必考虑与机器有关的繁琐细节,却能完成机器语言所能完成的绝大多数工作。
在解释方式下,并不生成目标代码,而是直接执行源程序本身。
这是编译方式与解释方式的根本区别。
1-2 简述高级语言程序按编译方式的执行过程。
答:高级语言程序按编译方式的执行过程一般可分为两个阶段:编译阶段和运行阶段。
其中,编译阶段完成由源程序到目标程序的翻译,若目标程序是汇编语言程序,还需再通过汇编程序进一步翻译成机器语言程序。
而运行阶段的任务是在目标计算机上执行编译阶段所得到的目标程序。
但目标程序往往不能由计算机直接执行,一般还应有运行系统进行配合,这个运行系统包括链接程序和由这样一些子程序组成的系统库,如标准函数计算子程序、数组动态存储子程序等。
由链接程序将目标程序和系统库连接在一起,最终形成一个可执行程序,在计算机上直接执行。
1-3 什么是编译系统?答:通常将编译程序、链接程序、系统库、源程序编辑程序等软件组成的系统称为编译系统。
1-4 编译过程通常有哪几个阶段?简述各阶段的主要任务。
答:程序设计语言的编译过程一般可以分为词法分析、语法分析、语义分析和中间代码生成、代码优化、目标代码生成5个阶段。
词法分析是编译过程的第一个阶段。
该阶段的主要任务是从构成源程序的字符串中识别出一个个具有独立意义的最小语法单位——单词,并指出其属性。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
3
7.1.1逆波兰表示法 7.1.1逆波兰表示法
逆波兰表示法是把运算量(操作数)写在前面, 逆波兰表示法是把运算量(操作数)写在前面, 把算符写在后面(后缀),也称后缀表示法。 ),也称后缀表示法 把算符写在后面(后缀),也称后缀表示法。 例如:a+b写成 写成ab+, a*b写成 写成ab* .用这种办法表 例如:a+b写成ab+, a*b写成ab* .用这种办法表 示的表达式称为后缀式。 示的表达式称为后缀式。 一个表达式E的后缀形式定义: 一个表达式E的后缀形式定义: 1)如果E是一个变量或常量,则E的后缀式是E自 如果E是一个变量或常量, 的后缀式是E 身。 2)如果E是E1 op E2形式的表达式,这里op是任 如果E E2形式的表达式 这里op是任 形式的表达式, 何二元操作符, 的后缀式为E1’E2’op 何二元操作符,则E的后缀式为E1’E2’op ,这里 E’和E2’分别为E1和E2的后缀式。 E’和E2’分别为 和E2的后缀式 分别为E1 的后缀式。 3)如果E是(E1)形式的表达式,则E1的后缀式 如果E E1)形式的表达式, E1的后缀式 就是E的后缀式。 就是E的后缀式。
9
其他三地址种类
goto l param x (n是参数个数 是参数个数) call p, n (n是参数个数) return x x := y[i] x[i] := y x := &y x := *y *x = y 无条件转移 实在参数 过程调用 过程返回 数组运算 指针运算
10
生成三地址代码时,临时变量的名字对应抽 生成三地址代码时, 象语法树的内部结点。对于产生式E 象语法树的内部结点。对于产生式E →E1+E2的左端的非终结符号 而言, →E1+E2的左端的非终结符号E而言,它的 的左端的非终结符号E 经过计算得出的值往往放到一个新的临时变 量T中。 赋值语句id:=E的三地址代码包括 的三地址代码包括: 赋值语句id:=E的三地址代码包括:对表达 求值并置于变量T 式E求值并置于变量T中,然后进行赋值 id.place:=T。 id.place:=T。如果一个表达式仅有一个单个 标示符,例如y,则由 自身保留表达式的值。 则由y 标示符,例如y,则由y自身保留表达式的值。
7
7.1.3三地址代码 三地址代码
一般形式 x := y op z 其中 x, y, z 为变量名、常数或编译产生的 为变量名、 临时变量; 临时变量; Op代表运算符号如定点运算符、浮点运算符、 Op代表运算符号如定点运算符、浮点运算符、 代表运算符号如定点运算符 逻辑运算符等等。 逻辑运算符等等。 每个语句的右边只能有一个运算符。例如,源 每个语句的右边只能有一个运算符。例如, 语言表达式x+y*z可被翻译为如下语句序列: x+y*z可被翻译为如下语句序列 语言表达式x+y*z可被翻译为如下语句序列: T1:=y*z T2:=x+T1 其中T1 T2为编译时产生的临时变量。 其中T1,T2为编译时产生的临时变量。 T1, 为编译时产生的临时变量
表中的@表示求负运算符。 表中的@表示求负运算符。 凡只需一个运算符的算符一律规定使用ARG1 凡只需一个运算符的算符一律规定使用ARG1
16
2.三元式
为了避免把临时变量填入到符号表, 为了避免把临时变量填入到符号表,三元 式是由算符OP,两个操作数域ARG1 ARG2组 OP,两个操作数域ARG1和 式是由算符OP,两个操作数域ARG1和ARG2组 成。两操作数域或者是指向符号表的指针 或者是指向三元式表的指针。 ,或者是指向三元式表的指针。
第七章 语义分析和中间代码产生
紧接在词法分析和语法分析之后,编译程序 要做的工作就是进行静态语义检查和翻译。 静态语义检查通常包括: 1)类型检查 2)控制流检查 3)一致性检查 4)相关名字检查 其它如名字的作用域分析等也都是静态语义 分析的工作。
1
虽然源程序可以直接翻译为目标语言代码,但是许 多编译程序却采用了独立于机器的、复杂性介于源 语言和机器语言之间的中间语言。这样的好处是: 1)便于进行与机器无关的代码优化工作; 2)使编译程序改变目标机更容易; 3)使编译程序的结构在逻辑上更为简单明确。以 中间语言为界面,编译前端和后端的接口更清晰。 静态语义检查和中间代码产生在编译程序中的地位 如图7.1 如图7.1
5
逆波兰表示法中栈的使用
后缀式的计值用栈实现非常方便,一般 后缀式的计值用栈实现非常方便, 的计值过程是:自左至右扫描后缀式, 的计值过程是:自左至右扫描后缀式,每 碰到运算量就把它推进栈,每碰到K 碰到运算量就把它推进栈,每碰到K目算 符就把它作用于栈顶部的k个项, 符就把它作用于栈顶部的k个项,并用运 算的结果来代替这k个项( 算的结果来代替这k个项(运算的结果仅 有一项)。 有一项)。
15
例如:赋值语句A:=-B*(C+D)的四元式表示。 A:=例如:赋值语句A:= B*(C+D)的四元式表示。 的四元式表示
OP ARG1 ARG2 (1) @ (2) + (3) * (4) := B C T1 T3 — D T2 — RESULT T1 T2 T3 A 注解 T1为临时变量 T2为临时变量 T3为临时变量 赋值运算
12
表7.3 对赋值语句产生三地址代码的属性文法 S → id := E E → E1 + E2
S.code := E.code || gen( id.place':='E.place E.place := newtemp; E.code := E1.code || E2.code || gen(E.place':='E1.place'+'E2
语法分析器 静态检查器 中间代码产生器 代码 语法分析器
中间
图7.1静态检查和中间代码产生的地位
2
7.1中间语言 7.1中间语言
在6.2.4节中介绍了抽象语法树,它是源 6.2.4节中介绍了抽象语法树, 节中介绍了抽象语法树 程序的中间表示方法之一。 程序的中间表示方法之一。在此将介绍其 它几种常见的中间语言形式。 它几种常见的中间语言形式。 常见的中间语言有:后缀式( 常见的中间语言有:后缀式(逆波兰表示 ),树型表示 三元式和四元式等。 树型表示, 法),树型表示,三元式和四元式等。
表达式的三元式: 表达式的三元式:w*x+(y+z) (1) *, w, x (2) +, y, z (3) +, (1), (2) 第三个三元 式中的操作数(1) 式中的操作数 (2)表示第 和第 表示第(1)和第 表示第 (2)条三元式的计 条三元式的计 算结果。 算结果。
E → ( E1 ) E → id E → num
E.place:= E1.place; E.code:= E1.code E.place:= id.place; E.code:= ' ' E.place:= num.val;E.code:= ' ' ;
注释: || 表示代码序列的连接 注释:
14
三地址语句可看成中间代码的一种抽象形 通常有三种表示方法:四元式、 式。通常有三种表示方法:四元式、三元 间接三元式。 式、间接三元式。 1.四元式 1.四元式 四元式是一种比较普遍采用的中间代码形 四元式的四个组成部分是:算符OP, OP,第 式.四元式的四个组成部分是:算符OP,第 一运算量ARG1,第二运算量ARG2 ARG1,第二运算量ARG2以及运算结 一运算量ARG1,第二运算量ARG2以及运算结 RESULT.其中 其中, 果RESULT.其中,运算量和运算结果有时指 用户自定义的变量, 用户自定义的变量,有时指编译程序引进 的临时变量。 的临时变量。 如果OP是一个算术或逻辑算符, OP是一个算术或逻辑算符 如果OP是一个算术或逻辑算符,则RESULT 总是一个新引进的临时变量, 总是一个新引进的临时变量,它用来存放 运算结果。 运算结果。
6
7.1.2图表示法 图表示法
图表示法包括DAG与抽象语法树 图表示法包括DAG与抽象语法树 无循环有向图DAG:与抽象语法树一样, 无循环有向图DAG:与抽象语法树一样, 对表达式中的每个子表达式,DAG中都有 对表达式中的每个子表达式,DAG中都有 一个结点。 一个结点。一个内部结点代表一个操作符 它的孩子代表操作数。 ,它的孩子代表操作数。 不同点: DAG中代表公共子表达式的结 不同点:在DAG中代表公共子表达式的结 点具有多个父结点, 点具有多个父结点,而在一棵抽象语法树 中公共子表达式被表示为重复的子树。 中公共子表达式被表示为重复的子树。 可见P167 可见P167
8
之所以称为三地址代码是因为每条语句通常包含 三个地址,两个用来表示操作数, 三个地址,两个用来表示操作数,一个用来存放 结果。对于后面给出的三地址代码中, 结果。对于后面给出的三地址代码中,用户定义 的名字在实际实现时将由指乡符号表中的相应名 字入口的指针所代替。 字入口的指针所代替。 常用的三地址语句种类 1)x := y op z 2)x := op y 3)x := y 4)if x relop y goto l 双目运算 单目运算 赋值 条件转移
4
逆波兰表示法用不着使用括号, 逆波兰表示法用不着使用括号,根据运算量和算 符出现的先后位置, 符出现的先后位置,以及每个算符的目数就完全 决定一个表达式的分解。 决定一个表达式的分解。 例如: (a+b)*c将被表示成 例如: (a+b)*c将被表示成 ab+c* 所代表的表达式是a*(b+c) abc+* 所代表的表达式是a*(b+c) 所代表的表达式是(a+b)*(c+d) Ab+cd+* 所代表的表达式是(a+b)*(c+d) 把一般表达式翻译为后缀式是很容易的。 7.1给 把一般表达式翻译为后缀式是很容易的。表7.1给 出了把表达式翻译为后缀式的语义规则描述, 出了把表达式翻译为后缀式的语义规则描述,其 E.code表示 后缀形式,op表示任意二元操作符 表示E 中E.code表示E后缀形式,op表示任意二元操作符 ||”表示后缀形式的连接。 ,“||”表示后缀形式的连接。 产生式 E→E1 op E2 E →(E1) E → id 语义规则 E.code:=E1.code||E2.code||op E.code:=E1.code E.code:=id