4.4 表达式及赋值语句的翻译
赋值语句翻译
赋值语句翻译一. 任务要求在理解翻译原理的基础上.用C 语言写一个实现赋值语句翻译的程序。
1定义赋值语句2分析出翻译中要解决的问题3明确翻译错误的表达以及处理4程序设计以及调试二. 实验目的.加深对语法制导翻译原理的理解,掌握将语法所识别的语法范畴变换为某种中间代码的语义翻译方法三. 赋值语句的定义编译过程的语义分析阶段将要完成两项主要工作.首先分析语言的含义.接着用一种中间代码将这种含义描述出来。
四元式主要由4 部分组成..op,arg1,arg2,result其中op 是运算符.arg1arg2 分别是第一和第二个运算对象.当op 是一目运算时.常常将运算对象定义为arg1。
例如.表达式-C 和赋值语句X=a 的四元式可分别表示为.@C-T=a-X四元式之间的联系是通过临时变量或已定义的变量来实现的.这样易于调整和变动四元式.也为中间代码的优化工作带来很大方便。
例如.下图表示了一个表达式 X = a * b + c / d 的四元式序列。
(1) ( *, a, b, T1 )(2) ( /, c, d, T2 )(3) ( +, T1, T2, T3 )(4) ( =, T3, -, X )图3.1 表达式的四元式序列编译系统中.有时将四元式表示成另一种更直观、更易理解的形式――三地址代码。
三地址代码形式定义为.X a op b其中X a b 可为变量名或临时变量名.a b 还可为常数.op 是运算符.这种表示法与赋值语句的区别是每个语句的右边只能有一个运算符。
图3.1 的四元式序列可以表示成如下三地址代码序列.(1) T1 = a * b(2) T2 = c / d(3) T3 = T1 + T2(4) X = T3三地址代码形式突出表现了每一个四元式中参加运算的对象和结果变量.因此有两个地址为操作对象的地址.第3 个为存放结果的临时变量.或用户自定义变量的地址。
这种表示形式有利于中间代码的优化和目标代码的生成。
C++基础:赋值表达式和逗号表达式
C++把赋值运算符连接⽽成的式⼦叫做赋值表达式,例如:a=b、a=b+c、a=3等。
赋值运算符是⼀个双⽬运算符,必须两个参与运算的值,其左边的值叫做l-value,通常是变量或赋值表达式,常量和常变量不可以作为赋值表达式的左值。
赋值运算符右端的值叫做r-value,通常⼀个常量、变量或表达式。
C++把逗号运算符连接的式⼦叫做逗号表达式,例如:“a,a*3”,“b+3,d/4”等。
逗号表达式右被称为顺序求值表达式,它的值是最右端的表达式的值。
例如,有如下逗号表达式:
a*=5,a+2
假设a=3,该逗号表达式的求值步骤是,先计算左侧的表达式a*=5,结果是a=15,然后计算右侧的表达式a+2,值是17,整条逗号表达式的值为17。
把赋值符和逗号连接的式⼦作为表达式看待是C++的特点之⼀,引⼊赋值表达式和逗号表达式使C++的语句变得⼗分灵活丰富。
合理的使⽤赋值表达式和逗号表达式可以⼤⼤精简代码,使程序更紧凑。
下⾯,我们来看⼀看使⽤这两种表达式时的技巧和应当注意到问题。
程序1:
#include
using namespace std;
int main()
{
unsigned short a;
short b=-1;
a=b;
cout<。
2023年大学_EDA技术与VHDL第二版(潘松著)课后习题答案下载
2023年EDA技术与VHDL第二版(潘松著)课后习题答案下载EDA技术与VHDL第二版(潘松著)课后答案下载第1章 EDA技术概述1.1 EDA技术及其发展1.1.1 EDA技术的发展1.1.2 EDA技术的涵义1.1.3 EDA技术的基本特征1.2 EDA技术的主要内容及主要的EDA厂商1.2.1 EDA技术的主要内容1.2.2 主要EDA厂商概述1.3 EDA技术实现目标1.3.1 超大规模可编程逻辑器件1.3.2 半定制或全定制ASIC1.3.3 混合ASIC1.4 EDA技术应用1.4.1 EDA技术应用形式1.4.2 EDA技术应用场合1.5 EDA技术的发展趋势1.5.1 可编程器件的发展趋势1.5.2 软件开发工具的发展趋势1.5.3 输入方式的发展趋势__小结思考题和习题第2章大规模可编程逻辑器件2.1 可编程逻辑器件概述2.1.1 PLD的'发展进程2.1.2 PLD的种类及分类方法2.2 简单可编程逻辑器件2.2.1 PLD电路的表示方法及有关符号 2.2.2 PROM基本结构2.2.3 PLA基本结构2.2.4 PAL基本结构2.2.5 GAL基本结构2.3 复杂可编程逻辑器件2.3.1 CPLD基本结构2.3.2 Altera公司器件2.4 现场可编程逻辑器件2.4.1 FPGA整体结构2.4.2 Xilinx公司FPGA器件2.5 在系统可编程逻辑器件2.5.1 ispLSl/pLSl的结构2.5.2 Lattice公司ispLSI系列器件 2.6 FPGA和CPLD的开发应用2.6.1 CPLD和FPGA的编程与配置2.6.2 FPGA和CPLD的性能比较2.6.3 FPGA和CPLD的应用选择__小结思考题和习题第3章 EDA设计流程与开发3.1 EDA设计流程3.1.1 设计输入3.1.2 综合3.1.3 适配3.1.4 时序仿真与功能仿真3.1.5 编程下载3.1.6 硬件测试3.2 ASIC及其设计流程3.2.1 ASIC设计方法3.2.2 一般的ASIC设计流程3.3 可编程逻辑器件的开发环境 3.4 硬件描述语言3.5 IP核__小结思考题和习题第4章硬件描述语言VHDL4.1 VHDL概述4.1.1 VHDL的发展历程4.1.2 VHDL的特点4.2 VHDL程序基本结构4.2.1 实体4.2.2 结构体4.2.3 库4.2.4 程序包4.2.5 配置4.3 VHDL基本要素4.3.1 文字规则4.3.2 数据对象4.3.3 数据类型4.3.4 运算操作符4.3.5 VHDL结构体描述方式 4.4 VHDL顺序语句4.4.1 赋值语句4.4.2 IF语句4.4.3 等待和断言语句4.4.4 cASE语句4.4.5 LOOP语句4.4.6 RETIARN语句4.4.7 过程调用语句4.4.8 REPORT语句4.5 VHDL并行语句4.5.1 进程语句4.5.2 块语句4.5.3 并行信号代人语句4.5.4 并行过程调用语句4.5.5 并行断言语句4.5.6 参数传递语句4.5.7 元件例化语句__小结思考题和习题第5章 QuartusⅡ软件及其应用5.1 基本设计流程5.1.1 建立工作库文件夹和编辑设计文件 5.1.2 创建工程5.1.3 编译前设计5.1.4 全程编译5.1.5 时序仿真5.1.6 应用RTL电路图观察器5.2 引脚设置和下载5.2.1 引脚锁定5.2.2 配置文件下载5.2.3 AS模式编程配置器件5.2.4 JTAG间接模式编程配置器件5.2.5 USBBlaster编程配置器件使用方法 __小结思考题和习题第6章 VHDL应用实例6.1 组合逻辑电路设计6.1.1 基本门电路设计6.1.2 译码器设计6.1.3 数据选择器设计6.1.4 三态门设计6.1.5 编码器设计6.1.6 数值比较器设计6.2 时序逻辑电路设计6.2.1 时钟信号和复位信号6.2.2 触发器设计6.2.3 寄存器和移位寄存器设计6.2.4 计数器设计6.2.5 存储器设计6.3 综合实例——数字秒表的设计__小结思考题和习题第7章状态机设计7.1 一般有限状态机7.1.1 数据类型定义语句7.1.2 为什么要使用状态机 7.1.3 一般有限状态机的设计 7.2 Moore型有限状态机设计 7.2.1 多进程有限状态机7.2.2 单进程有限状态机7.3 Mealy型有限状态机7.4 状态编码7.4.1 状态位直接输出型编码 7.4.2 顺序编码7.4.3 一位热码编码7.5 状态机处理__小结思考题和习题第8章 EDlA实验开发系统8.1 GW48型实验开发系统原理与应用8.1.1 系统性能及使用注意事项8.1.2 GW48系统主板结构与使用方法8.2 实验电路结构图8.2.1 实验电路信号资源符号图说明8.2.2 各实验电路结构图特点与适用范围简述8.3 GW48CK/GK/EK/PK2系统信号名与芯片引脚对照表 __小结思考题和习题第9章 EnA技术实验实验一:全加器的设计实验二:4位加减法器的设计实验三:基本D触发器的设计实验四:同步清零计数器的设计实验五:基本移位寄存器的设计串人/串出移位寄存器实验六:同步预置数串行输出移位寄存器的设计实验七:半整数分频器的设计实验八:音乐发生器的设计实验九:交通灯控制器的设计实验十:数字时钟的设计EDA技术与VHDL第二版(潘松著):内容简介《EDA技术与VHDL》主要内容有Altera公司可编程器件及器件的选用、QuartusⅡ开发工具的使用;VHDL硬件描述语言及丰富的数字电路和电子数字系统EDA设计实例。
表达式及赋值语句的翻译ppt课件
返填。
.
13
例如,假定E的四元式需要回填“真”出口的有p、 q、r这三个四元式,则它们可链接成如图4–6所示 的一条真值链(记作tc)。
(p) (x, x, x,0) …
(q) (x , x, x,p) …
(r) (x, x, x,q)
0是链尾标志 地址(r)是E.tc的链首
.
14
为了处理E.tc和E.fc这两项语义值,我们 需要引入如下的语义变量和函数:
(7) EB→E(1)∨ {Backpatch(E(1).fc,nxq);
EB.tc = E(1).tc; }
(8) E→EBE(2) {E.fc = E(2).fc;
E.tc = merge(EB.tc,E(2).tc);}
注意: EA 、EB是与E不同的非终结符, E(1) 、E(2)是与E相同的非终结符。
算术表达式:
– 算术运算符: +、-、*、/、^等 – 运算对象:操作数 – 算术运算符的运算顺序一般为^、 *、/、 +、-,
且满足左结合,其运算优先级高于布尔运算符, 且高于任何关系运算符。
.
9
为简单起见,我们遵循以上运算约定讨论下 述文法G[E]生成的布尔表达式:
G[E]:E→E∧E∣E∨E∣┐E∣(E)∣i∣i rop i
对于每个非终结符E,我们需要为它赋予两个语义
值E.tc和E.fc,以分别记录E所对应的四元式需要
回填“真”、“假”出口的四元式地址所构成的
链。这是因为在翻译过程中,常常会出现若干转
移四元式转向同一个目标但目标位置又未确定的
情况,此时可用“拉链”的方法将这些四元式链
接起来,待获得转移目标的四元式地址时再进行
4.4 表达式及赋值语句的翻译.
2018/12/15 4
语义子程序所涉及的语义变量、语义过程及函数说明:
(1) 语义变量E.place:即用E.place表示存放E值的变 量名在符号表中的入口地址或临时变量名的整数码。 (2) 语义函数newtemp( ):即每次调用newtemp( )时 都将回送一个代表新临时变量的整数码;临时变量名 按产生的顺序可设为T1、T2、……。 (3) 语义过程 emit(op,arg1,arg2,result) : emit 的功 能是产生一个四元式并填入四元式表中。
编 译 原 理 Principle of Compiling
郭 一 晶
厦门大学嘉庚学院 2008 年 9 月
2018/12/15 1
4.4 表达式及赋值语句的翻译
4.4.1 简单算术表达式和赋值语句的翻译 4.4.2 布尔表达式的翻译
2018/12/15
2
4.4.1 简单算术表达式和赋值语句的翻译
2018/12/15 6
(5) E→(E(1)) { E.place= E(1) .place ; } (6) E→i { p=lookup(); if (p!=NULL) E.place = p; /*另一种表示为E.place= entry(i)*/ else error( );}
T E(1) ∨ E(2) F F (a) T
“真”出口 “假”出口
T E(1) F
T
∧ E(2)
F (b)
“真”出口 “假”出口
2018/12/15
12
在自下而上的分析过程中,一个布尔式的真假出 口往往不能在产生四元式的同时就填上,我们只 好把这种未完成的四元式的地址 (编号)作为E的语 义值暂存起来,待到整个表达式的四元式产生完 毕之后,再来填写这个未填入的转移目标。
语法制导翻译和中间代码生成
例如:
产生式 语义子程序 (0)S` E {PRINT E•VAL} (1)E E (1)+E(2) {E•VAL= E (1) •VAL +E(2) •VAL } (2)E E (1)*E(2) {E•VAL= E (1) •VAL *E(2) •VAL } (3)E (E (1)) {E•VAL= E (1) •VAL } (4)E i {E•VAL= LEXVAL } 注:LEXVAL指的是词法分析送来的机内二进制整数
3、后缀表示式(逆波兰表达式) Operand1 Operand2 Operator 4、树形表示法
注:常用中间代码表示法是四元式。
赋值语句的翻译
仅含简单变量的表达式的赋值语句的翻译 1、赋值语句的文法 A i=E E E+E|E*E|-E|(E)|i 2、需要的语义过程 NEWTEMP函数:每次调用送回一个代表新临时 变量的序号,可认为是送回T1 、 T2这样的一些 临时变量 ENTRY(i)函数:用于查变量i的符号表入口地址
2、实例:对布尔式X+Y>Z∨A∧(┐B∨C)进行翻译: 解:语法制导得翻译是在语法分析的过程中进行的,若利
用G(B)文法的LR分析表对上句进行LR分析,在其过程中 进行语义分析;则得到的四元式序列是:
(+,X,Y,T1) ;E+E进行归约,识别了算术运算 (>, T1,Z, T2) ; E >E进行归约,识别了关系运算 (┐,B,_, T3) ; ┐E归约 (∨, T3,C, T4) ; E∨E进行归约 (∧,A, T4,T5) ; E∧E进行归约 (∨, T2, T5, T6) ; E∨E进行归约
四、常见的中间代码形式 1、四元式形式: (Operator,Operand1,Operand2,Result) 注: 1) Operand1,Operand2,Result 可能是用户自定 义的变量,也可能是编译时引进的变量。 这里 Operator是双目运算符,若只有一个运算量,则 是单目运算符。
第17讲 赋值语句的翻译
E.type:=integer else E.type:=real }
产生式E→E1 +E2 的语义动作
{ E.place:=newtemp;
if E1.type=integer and E2.type=integer then begin
函数newtemp的功能是,每次调用它时,将返 回一个不同的临时变量名字,如T1,T2,…
赋值语句生成三地址代码的S-属性文法
产生式 S→id:=E E→E1+E2
E→E1*E2
E→-E1
E→ (E1)
E→id
语义规则 S.code:=E.code || gen(id.place ‘:=’ E.place)
(6) L→id { L.place:=id.place; L.offset:=null }
A[i1,i2,…,ik] ((…i1 n2+i2)n3+i3)…)nk+ik) ×w + base-((…((low1 n2+low2)n3+low3)…)nk+lowk)×w
带数组元素引用的赋值语句翻译模式
L.offset
若L为简单变量,null 若L为下标变量,指存放可变部分的临时变量的名字
((…i1 n2+i2)n3+i3)…)nk+ik)×w + base-((…((low1 n2+low2)n3+low3)…)nk+lowk)×w
带数组元素引用的赋值语句
(1) S→L:=E (2) E→E+E (3) E→(E) (4) E→L (5) L→Elist ] (6) L→id (7) Elist→ Elist, E (8) Elist→id [ E
程序设计语言常用语法与翻译
信息学院软件工程教研室
4.1 逆波兰表示法
逆波兰表示表达式 ab* ab*c+ abcd/+* ab*cd*+
高级语言表示表达式 a* b a*b+c a*(b+c/d) a*b+c*d
信息学院软件工程教研室
高级语言表达式E的逆波兰表示法可这样定义:
信息学院软件工程教研室
最简单的情况E是一个布尔变量a,那么 有:
(jnz, a, , L1 ) 真出口 (jp, , , L2 ) 假出口
信息学院软件工程教研室
另外,布尔量间的运算除了一般的布尔 代数运算外,还有一种运算方法,称为 “短路布尔操作”。它的意义是:对于 一个二元布尔操作,如果根据第1个布尔 量的值就可以判断这个布尔结果,那么 就不必计算第2个布尔量了。就是说,在 某种情况下第2个布尔量被短路了。
→
对赋值语句文法定义的句子而言,相应 的抽象语法树如图所示。
信息学院软件工程教研室
4.3.3 if语句
if语句是控制语句的一种,它的文法被定 义为:
S if ( E)S | if ( E)S else S
这个语法有两个候选式,这两个候选式 的前半部分是一样的,即:。也就是说, 在一个符号串之后可能紧跟一个或跟其 他的符号串。由于可选的影响,这个文 法有二义性的,即所谓“悬挂问题”。
信息学院软件工程教研室
4.2 三地址代码
三地址代码是由下面一般形式的语句构成的序列。 x:=y op z 其中x、y、z是变量名或编译时产生的临时变量名; y、z还可以是常数;op代表某种操作符。这种中间 语言的特点有两个。 (1)非常接近汇编语言形式,包括汇编语言中最基 本的操作。 (2)每个语句中赋值号的右边只有一个操作符,使 得句子意义最小且不可分。例如,源语言表达式 x+y*z可被翻译成如下的句子序列: T1:=y*z T2:=x+T1
编译原理(4)语义-2(表达式及赋值语句的翻译)
计算布尔表达式的值有两种方法:
1、按照优先级和各变量的值,一步步求出结果;
2、优化计算: b = true; a = b ∨ c ; (不计算c, a=true)
b = false; a = b ∧ c ; (不计算c, a=false)
4.4 表达式及赋值语句的翻译
2、布尔表达式的计算
所以,按照优化方式计算布尔表达式,需要给出整个表达式 的真假出口。
练习布尔表达式 a∧b∨c≥d 的真假出口。
4.4 表达式及赋值语句的翻译
布尔表达式中,每个布尔分量一般至少对应两个四元式。
例如:E = E(1)∨E(2) = a∨b
if(a || b) c=1;
对应: (1)(jnz, a,_,真出口)
(2)(j,_,_,3)
(3)(jnz, b,_,真出口)
4.4 表达式及赋值语句的翻译 (3) 其它需要说明的问题:
1、对于每个非终结符E,我们需要为它赋予两个语义值 E.tc和E.fc,分别用来记录E所对应的四元式的真链和假链。 也就是说,为每个非终结符E添加两个属性:tc和fc;因此, 规约的时候,再次扩充语义栈,添加tc栈和fc栈;
2、nxq:这是一个int变量,翻译工作开始之前,初始值 是1,翻译工作开始之后,每执行一次emit(),nxq自增1, 即: nxq = 四元式个数+1;
Backpatch(p, int t){ Q=p; while(Q!=0) { q=四元式Q的第四区段内容; 把t填进四元式Q的第四区段; Q=q;
} // while } //Backpatch
(q) (_ , _ , _ , r) (p) (_ , _ , _ , q)
(r) (_ , _ , _ , t) (q) (_ , _ , _ , t) (p) (_ , _ , _ , t)
第5章 语法制导翻译1
2. Expr Name (1) Add Name ( 2 ) { Attribution: Name (1) . environment Expr . environment ; Name ( 2 ) . environment Expr . environment ;
int Entry(char *Name){ int i=LookUp(Name);
if(i) return i; else return Enter(Name);
翻译程序中使用的辅助函数(续)
⒋int Trip(int op,int arg1,int arg2)—根据给定 的参数产生一个三元式 (op,arg1,arg2) 并将它送入三元式表中,其返回值为表中序号。 为区分参数 arg 表示的是 三元式 还是变量,约定 当arg<0时表示三元式序号;arg>0表示变量在 符号表中登记项序号;arg=0表示参数为空。
文法符号及其语义属性
例如,文法G[E]: 产生式 语义子程序 E→E(1)+T {E.Val=E(1).val+T.val;} E→T {E.Val=T.Val;} T→digit {T.Val=digit;} 为了能在语法分析过程中平行地进行语 义处理,可在语法分析栈旁边并行地设 置一个语义信息栈
语法分 析栈 T + E … # … 语义分 析栈 T.Val ‘+’
5.2 属性文法与属性翻译文法
语法制导翻译方法的实质,就是根据文法中每个产 生式所蕴含的语义,为其配备一个(或多个)处理 语句或子程序,对所要完成的功能进行描述。 产生式的语义是由组成该产生式的文法符号的语义 所决定的。 将这些语义以“属性”的形式附加到各个文法符号 上,再根据产生式所蕴含的语义,给出每个文法符 号的属性的求值规则,从而形成一种附带有语义属 性的前后文无关文法,即属性文法。 语义属性主要有两类:综合属性和继承属性
编译原理 第4章 new1语义分析和中间代码生成
(3) E→(E(1))
(4) E→i
val[TOP]= val[TOP+1]
val[TOP]=lexval (注:lexval为i的整型内 部值)
文法的LR分析表见表3.20。
第4章 语义分析和中间代码生成
扩充分析栈工作的总控程序功能,使其在完成语法 分析的同时也能完成语义分析工作(这时的语法分析栈 已成为语义分析栈);即在用某一个规则进行归约之后, 调用相应的语义子程序完成与所用产生式相应的语义动 作,并将每次工作后的语义值保存在扩充后的“语义值” 栈中。
语义规则的左部符号E、T、F等的属性值的计算由其
各自相应的右部符号决定,这种属性也称为综合属性。 与产生式S→E关联的语义规则是一个函数print(E.val), 其功能是打印E产生式的值。S在语义规则中没有出现, 可以理解为其属性是一个虚属性。
第4章 语义分析和中间代码生成 简单变量类型说明的文法G[D]如下:
(2) 控制流检查,用以保证控制语句有合法的转向点。如C 语言中不允许goto语句转入case语句流;break语句需寻找包含它 的最小switch、while或for语句方可找到转向点,否则出错。 (3) 一致性检查,如在相同作用域中标识符只能说明一次、 case语句的标号不能相同等。
第4章 语义分析和中间代码生成
同,因此很容易将其翻译成四元式形式。
第4章 语义分析和中间代码生成
考虑以下文法G[A]:A→i=E
E→E+E∣E*E∣−E∣(E)∣i 在此,非终结符A代表“赋值句”。 为了实现由表达式到四元式的翻译,需要给文法 加上语义子程序,以便在进行归约的同时执行对应的
语义子程序。
第4章 语义分析和中间代码生成
第4章 语义分析和中间代码生成
精品文档-编译原理基础(第二版)(刘坚)-第4章
第4章 语法制导翻译生成中间代码
4.1.3 语义规则的两种形式 根据属性表示的抽象程度,语义规则可以有两种表示方
式。用抽象的属性和运算符号表示的语义规则称之为语法制导定 义,而用具体属性和运算表示的语义规则称之为翻译方案,语义 规则也被习惯地称为语义动作。
本章的重点是语义分析,为了突出重点并使分析过程 简单明了,许多的文法都采用简化了的二义文法,而默认解决 二义性的方法是为文法符号规定常规意义下的优先级和结合性。 例如表达式中算符的优先级是乘除法高于加减法,if-thenelse语句中else是右结合(移进先于归约)等等。
第4章 语法制导翻译生成中间代码
第4章 语法制导翻译生成中间代码
语法制导定义仅考虑“做什么”,用抽象的属性 表示文法符号所代表的语义,如用.post表示表达式的后缀 式;并用抽象的算符表示语义的计算,如用“||”表示两 个子表达式后缀式的连接运算。属性和运算的具体实现细 节不在语法制导定义的考虑范围。根据定义4.1可知.post 是一个综合属性。
第4章 语法制导翻译生成中间代码 【例4.1】 为下述文法所描述的中缀形式的算术表达式
加上适当的语义,得到表达式的后缀表示。其语法制导定义和翻 译方案可分别表示如下。
产生式
语法制导定义
翻译方案
L→E E → E1 + E2
E → num
print(E.post) E.post := E1.post || E2.post || '+';
第4章 语法制导翻译生成中间代码
产生式 L→E E → E1 + E2 E → num
1表达式语句表达式语句是指任何一...
第四章语句4.1.1表达式语句表达式语句出现得最多,因此,有人说C语言是表达式语言。
表达式语句与表达式之间虽然只差一个分号(;),但二者是截然不同的。
在程序中,有的地方需要用表达式,则不能写成表达式语句。
例如,在if语句或循环语句的条件中,要求用表达式作为条件,如果写成表达式语句(即末尾加了分号),则是错误的。
同样,在要求用表达式语句的地方,写成表达式(即少写一个分号),也是错误的。
所以,读者一定要搞清楚何时用表达式,何时用表达式语句,二者不要搞混了。
例如,b=a+3是一个表达式;而b=a十3;便是一个表达式语句,这是一个赋值表达式语句。
类似地,表达式语句还有:++i; (算术表达式语句)m>n7m:n; (条件表达式语句)b==5 (比较表达式语句)x&&++y||Z; (逻辑表达式语);printf("0n!\n")(函数调用也是表达式语句)i=a,j=5,k=7; (逗号表达式语句)等等。
有些表达式语句虽然是合法的,例如,m> n? m;n;但是,它并没有实际意义,需要将其表达式的值赋给某个变量才有意义。
例如,x=m>n? m:n;这是一个有意义的表达式语句,它将一个表达式m>n? m ; n的值赋给了变量x.虽然任何一个表达式加上分号都构成表达式语句,但在程序中要出现的是有意义的表达式语句。
4.1.2 空语句空语句是一种只有分号而没有表达式的特殊语句。
空语句是c语句中最简单的语句,因为它只由一个分号(;)组成。
空语句是一种不执行任何操作的语句。
说它是特殊语句是指它是一种"不做事情"的语句。
空语句在编程中也是有用的,它主要被用在需要一条不做事情的语句的地方。
例如,它可用来作循环体,则该循环是空循环。
下面是一个为了延迟一段时间的循环,其循环体可用空语句。
for<i=0: i<1000;i++)空语句还可以用在goto.语句中语句标号的后面,即需要goto语句转向一条什么事情都不做的语句,那么在该语句标号的后面可用空语句。
53 赋值语句的翻译
• 注释: || 表示代码序列的连接 注释:
例 5-7:
S
翻译 a:= -c+b*34
id
:= E1
E + E 21 id E2 * E 22 num
-
E 11 id
a:= -c+b*34的中间代码
• • • • t2:=0 - c t3:=b*34 t1:=t2+t3 a:=t1
c+b*34的中间代码的生成过程 a:= -c+b*34的中间代码的生成过程
实现赋值语句的翻译
基本子程序
–产生一条中间代码 gen(code) 产生一条中间代码 –产生新的临时变量 newtemp 产生新的临时变量
属性设置
–中间代码序列 code 中间代码序列 –存储位置 place 存储位置
赋值语句的四元式翻译
S → id := E S.code := E.code || gen( id.place':='E.place ) E → E1 + E2 E.place := newtemp; E.code := E1.code || E2.code || gen(E.place':='E1.place'+'E2.place) E → E1 * E2 E.place := newtemp; E.code := E1.code || E2.code || gen(E.place':='E1.place'*'E2.place)
S.next
循环语句的属性文法
S → while C do S1 C.false := S.next; S.begin := S1.next := newlabel; C.true := S1.begin := newlabel; S.code := gen( S.begin':' ) || C.code || gen( C.true':' ) || S1.code || gen( 'goto'S.begin ) 语义过程 –新标号的产生 newlabel 新标号的产生
第17讲 赋值语句的翻译
(5) L→Elist ] { L.place:=newtemp; emit(L.place ‘:=’ Elist.array ‘-’ C); L.offset:=newtemp; emit(L.offset ‘:=’ w ‘*’ Elist.place) }
视频区域
(6) L→id { L.place:=id.place; L.offset:=null }
||
gen(E.place
‘:=’
E1.plac视e 频‘+区’ E域2.place)
E.code:=E1.code || E2.code || gen(E.place ‘:=’ E1.place ‘*’ E2.place)
E.place:=newtemp;
E.code:=E1.code || gen(E.place ‘:=’ ‘uminus’ E1.place)
L.offset
若L为简单变量,null 若L为下标变量,指存放可变部分的临时变量的名字
((…i1 n2+i2)n3+i3)…)nk+ik)×w + base-((…((low1 n2+low2)n3+low3)…)nk+lowk)×w
带数组元素引用的赋值语句
(1) S→L:=E (2) E→E+E (3) E→(E) (4) E→L (5) L→Elist ] (6) L→id (7) Elist→ Elist, E (8) Elist→id [ E
A[i1,i2,…,ik] ((…i1 n2+i2)n3+i3)…)nk+ik) ×w + base-((…((low1 n2+low2)n3+low3)…)nk+lowk)×w
编译原理-算术表达式赋值句数组元素的引用布尔表达式
10
一维数组元素的地址计算:
跳过前i-1个单元
addr(A[i]) = a + (i-1)*w
首首首
W首 首 首
二维数组元素的地址计算: addr(A[i1,i2])=a+((i1-1)*d2+(i2-1))*w
跳过前i2-1个单元
跳过前i1-1行
11
n维数组元素的地址计算 addr(A[i1,i2,...,in]) =a+((i1-1)*d2*d3*...*dn+(i2-1)*d3*d4*...*dn+...+ (in-1))*w =a-(d2*d3*...*dn+d3*d4*...*dn+...+dn+1)*w +(i1*d2*d3*...*dn+i2*d3*d4*...*dn+...+in-1*dn+in)*w =a–c*w+v*w 根据假设条件③w=1: addr(A[i1,i2,...,in])=a–c+v 其中: c = d2*d3*d4...*dn+d3*d4*d5...*dn+*d4*d5*d6...*dn...+dn+1 = (d2+1)*d3*...*dn+d4*d5...*dn+...+dn+1 =((d2+1)*d3+1)*d4*d5...*dn+...+dn+1 ...... = (...((d2+1)*d3+1)*d4...+1)*dn+1 同理: v = (...((i1*d2+i2)*d3+i3)*d4...+in-1)*dn+in
赋值语句的名词解释
赋值语句的名词解释赋值语句是计算机编程中的重要概念之一。
它是一种用于将特定值赋给变量的操作,通常表示为"="号。
这个简单的符号代表着一种将右边的值赋给左边变量的行为。
赋值语句的基本形式是“变量名 = 值” ,其中变量名表示一个标识符,用于表示存储数据的位置,值代表要存储的数据。
在这个过程中,变量名被视为存储值的容器,而值则是要存储的内容。
赋值语句的核心目的是在计算机内存中创建一个变量,并将指定的值存储在该变量中。
赋值语句在程序设计中起到了至关重要的作用。
通过将值存储在变量中,程序可以在后续代码中使用这些值,以便进行后续计算、处理和展示。
在编程中,用户可以根据实际需求创建并使用多个变量,通过赋值语句,程序能够以一种灵活而高效的方式处理和管理这些变量。
赋值语句的执行过程遵循严格的规则。
首先,计算机会评估赋值语句右边的表达式,并计算出一个结果。
然后,计算机将这个结果赋值给左边的变量。
这个结果可以是一个数值、一个字符串、一个布尔值或其他数据类型,取决于变量的声明。
在赋值语句中,左边的变量必须事先声明。
声明一个变量的目的是为其分配内存空间,以便存储赋值的结果。
不同的编程语言对变量声明的方式有所不同,有些语言要求在使用变量之前显式声明,而有些语言则可以在使用变量时隐式声明。
除了基本的赋值语句形式之外,还存在一些扩展的赋值语句。
例如,"+="表示将右边的值与左边的变量相加,并将结果赋给变量。
其他常见的扩展赋值语句还包括“-=”、“*=”、“/=”等。
这些扩展语句简化了代码的书写,使得程序更加简洁和易读。
正如上述内容所示,赋值语句在计算机编程中具有重要地位。
通过赋值语句,程序可以存储和处理不同类型的数据。
这种灵活性有助于程序员创建出功能强大且高效的程序。
因此,了解和掌握赋值语句的概念及其使用方法对于每一个计算机程序员来说都至关重要。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
郭 一 晶
厦门大学嘉庚学院 2008 年 9 月
2016/6/23 1
4.4 表达式及赋值语句的翻译
4.4.1 简单算术表达式和赋值语句的翻译 4.4.2 布尔表达式的翻译
2016/6/23
2
4.4.1 简单算术表达式和赋值语句的翻译
2016/6/23 15
merge( )函数如下: merge(p1,p2) { if(p2= = 0) return(p1); else { p = p2; while (四元式p的第四区段内容不为0) p = 四元式p的第四区段内容; 把p1填进四元式p的第四区段; return (p2); } }
2016/6/23 18
文法G'[E]的每个产生式和相应的语义子程序: (1) E→i {E.tc=nxq; E.fc=nxq+1; emit(jnz,entry(i),_,0); emit(j,_,_,0);} (2) E→i(1) rop i(2) {E.tc=nxq; E.fc=nxq+1; emit(jrop, entry(i(1)), entry(i(2)),0); emit(j,_,_,0);} (3) E→(E(1) ) {E.tc = E(1).tc;E.fc = E(1).fc;} (4) E→┐E(1) {E.tc = E(1).fc;E.fc = E(1).tc;}
16
2016/6/23
Backpatch( )函数如下: Backpatch( p , t ) { Q = p; while (Q != 0) { q = 四元式Q的第四区段内容; 把t填进四元式Q的第四区段; Q = q; } }
2016/6/23 17
注意: EA 、EB是与E不同的非终结符,
E(1) 、E(2)是与E相同的非终结符。
2016/6/23 20
注
意:
整个布尔表达式所对应的四元式全部产 生之后,作为整个表达式的真假出口(转 移目标)仍尚待回填。
由产生式(2)也可看出关系表达式的优先 级高于布尔表达式。
2016/6/23
21
2016/6/23 9
为简单起见,我们遵循以上运算约定讨论下 述文法G[E]生成的布尔表达式: G[E]:E→E∧E∣E∨E∣┐E∣(E)∣i∣i rop i
注意: rop 代表六个关系运算符,即 < 、 <= 、 ==、!=、>=、>等。
2016/6/23
10
计算布尔表达式通常有两种方法: 1. 仿照计算算术表达式的文法,按布尔表 达式的运算顺序一步步地计算出真假值, 如1 ∨ (┐0∧0) ∨0。 2. 根据布尔运算的特点实施某种优化,省 略不影响运算结果的运算。例如,在计算 A∨B时,若计算出的A值为1,则B值就 无需再计算了;同样,在计算A∧B时若 发现A值为0,则B值也无需计算,A∧B 的值一定为0。 注 意:假定函数过程的工作不出现P102 的副作用情况。
2016/6/23 11
如何确定一个表达式的真假出口呢? 考虑表达式E(1)∨E(2),若E(1)为真,则立即知道E也 为真,因此,E(1)的真出口也就是整个E的真出口; 若E(1)为假,则E(2)必须被计值,此时E(2)的第一个四 元式就是E(1)的假出口。当然,E(2)的真假出口也就 是整个E的真假出口。类似的考虑适用于对E(1)∧E(2) 的翻译。
例如,假定E的四元式需要回填“真”出口的有p、 q、r这三个四元式,则它们可链接成如图4–6所示 的一条真值链(记作tc)。
(p)
(x, x, x,0) …
(x , x, x,p) …
0是链尾标志
(q)
(r)
2016/6/23
(x, x, x,q)
地址(r)是E.tc的链首
14
为了处理E.tc和E.fc这两项语义值,我们 需要引入如下的语义变量和函数: (1) nxq :始终指向下一条将要产生 的四元式的地址 ( 序号 ) ,其初值为 1 。每 当执行一次emit语句后,nxq自动增1。 (2) merge(p1,p2) :把以 p1 和 p2 为链首 的两条链合并为一条以 p2 为链首的链 ( 即 返回链首值p2)。 (3) Backpatch(p,t) :把链首 p 所链接 的每个四元式的第四区段 ( 即 result) 都改 写为地址t。
2016/6/23 26
2016/6/23
27
对于每个非终结符E,我们需要为它赋予两个语义 值E.tc和E.fc,以分别记录E所对应的四元式需要 回填“真”、“假”出口的四元式地址所构成的 链。这是因为在翻译过程中,常常会出现若干转 移四元式转向同一个目标但目标位置又未确定的 情况,此时可用“拉链”的方法将这些四元式链 接起来,待获得转移目标的四元式地址时再进行 返填。 2016/6/23 13
例4.2 试给出布尔表达式a∧b∨c≥d作为控 制条件的四元式中间代码。 [解答] 设四元式序号从100开始,则布尔 表达式 a∧b∨c≥d 的分析过程如图 4–7 所示。 顺序执行相应的语义子动作。
提示:先画出相应的语法树,再根据归约
2016/6/23
22
即: 100(jnz,a,_,102) 101(j,_,_,104) 102(jnz,b,_,106) 103(j,_,_,104) 104(j≥,c,d,106) 105(j,_,_,q) T: 106
T E(1) ∨ E(2) F F (a) T
“真”出口 “假”出口
T E(1) F
T
∧ E(2)
F (b)
“真”出口 “假”出口
2016/6/23
12
在自下而上的分析过程中,一个布尔式的真假出 口往往不能在产生四元式的同时就填上,我们只 好把这种未完成的四元式的地址 (编号)作为E的语 义值暂存起来,待到整个表达式的四元式产生完 毕之后,再来填写这个未填入的转移目标。
2016/6/23 4
语义子程序所涉及的语义变量、语义过程及函数说明:
(1) 语义变量E.place:即用E.place表示存放E值的变 量名在符号表中的入口地址或临时变量名的整数码。 (2) 语义函数newtemp( ):即每次调用newtemp( )时 都将回送一个代表新临时变量的整数码;临时变量名 按产生的顺序可设为T1、T2、……。 (3) 语义过程 emit(op,arg1,arg2,result) : emit 的功 能是产生一个四元式并填入四元式表中。
P101 例4.1试分析赋值语句X= −B*(C+D) 的语法制导翻译过程。
2016/6/23
7
4.4.2 布尔表达式的翻译
程序设计语言中的布尔表达式有两个作用, 一是计算逻辑值,更多的情况是二,用作改 变控制语句中的条件表达式,如在if-then, if-then-else或while-do语句中。 表达式:由运算符与运算对象组成。 布尔表达式:
为了便于实现布尔表达式的语法制导翻译,并 在扫描到“∧”与“∨”时能及时回填一些已 经确定了的待填转移目标,我们将前述文法 G[E]改写为下面的文法G‘[E],以利于编制相应 的语义子程序: G'[E]: E→EAE∣EBE∣┐E∣(E)∣i∣i rop i
EA→E∧
EB→E∨
注意: EA 、EB是与E不同的非终结符。
– 布尔运算符: ┐、∧、∨,或为not、and和or (注:
C语言中为!、&& 和 ||)。 – 运算对象:布尔变量、常量或关系表达式。 – 布尔运算符的运算顺序一般为┐、∧、∨,且∧ 和∨服从左结合,布尔算符的运算优先级低于任 何关系运算符。
2016/6/23 8
关系表达式: – 关系运算符: <、<=、==、!=、>=、>等 – 运算对象:算术表达式 – 关系运算符的优先级相同但不得结合,其运算 优先级高于布尔运算符,低于任何算术运算符。 算术表达式: – 算术运算符: +、-、*、/、^等 – 运算对象:操作数 – 算术运算符的运算顺序一般为^、 *、/、 +、-, 且满足左结合,其运算优先级高于布尔运算符, 且高于任何关系运算符。
简单变量:指普通变量和常数,但不含数 组元素及结构引用等复合型数据结构;
简单算术表达式:一种仅含简单变量的算 术表达式。 简单算术表达式的计值顺序与四元式出现 的顺序相同,因此容易将其翻译成四元式 形式,这些翻译方法稍加修改也可用于产 生三元式或间接三元式。
3
2016/6/23
考虑以下文法G[A]: A→i=E E→E+E∣E*E∣−E∣(E)∣i 在此,非终结符A代表“赋值语句”。 文法 G[A] 虽然是一个二义文法,但通过 确定运算符的结合性及规定运算符的优 先级就可避免二义性的发生。 为了实现由表达式到四元式的翻译,需 要给文法加上语义子程序,以便在进行 归约的同时执行对应的语义子程序。
2016/6/23 6
(5) E→(E(1)) { E.place= E(1) .place ; } (6) E→i { p=lookup(); if (p!=NULL) E.place = p; /*另一种表示为E.place= entry(i)*/ else error( );}
(jrop,X,Y,0) /*X、Y为关系运算符两侧的变量或值*/ ( j,_,_,0)