编译原理陈火旺版7章7
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
X.TYPE表示为X的类型 X.VAL表示为X的值
例:
对于文法: E →E+T | T T→ digit
产生式 语义子程序
1、E→ E(1)+T {E.Val=E(1).Val+T.Val 2、E→ T {E.Val=T.Val} 3、T→ digit {T.Val=digit}
例
语法分析栈 语义信息栈 T + E … # T.Val ‘ +’ E(1).Val … E … E.Val …
三元式
x:=(a+b)*c b:=a+b y:=c*(a+b)
(1)(+,a,b) (5) (+,a,b) (2)(*,(1),c) (6)(*,c,(5)) (3)(:=,x,(2)) (7)(:=,y,(6)) (4)(:=,b,(1))
间接三元式
执行表 (1) (2) (3) (4) (1) (2) (5)
后缀式的推广 条件语句的翻译: If e THEN S1 else S2
图表示法-抽象语法树
在语法树中去掉一些对翻译不必要的信 息后,获得的更有效的源程序的中间表示, 这种经过变换后的语法树称为抽象语法树。 在抽象语法树中,操作符和关键字都不 作为叶子节点出现,而是把它们作为内部 节点,即这些叶子节点的父节点。
例
a:=b*-c+b*-c
op (0) (1) uminus * arg1 c b (0) (2) (3) arg2
(2)
(3) (4)
uminus
* +
cΒιβλιοθήκη Baidu
b (1) a
(5)
assign
(4)
三元式和四元式的比较
相同点: 1、无论在一个三元式序列还是四元式序列 中,各个三元式或四元式都是按相应表达 式的实际运算顺序出现的;
assign • id + *
• •
•
a • • *
• •
id
id
b
c
id
id
b
c
uminus •
Uminus •
方法2
把所有的结点安排在一个记录的 数组中,结点的位置或索引作为 指向地点的指针。
0
id
id uminus * id id uminus * +
b
c 1 0 B C 5 4 3 6 7 2
例
a+a*(b-c)+(b-c)*d
+ + * a * d
b
c
抽象语法树的表示方法
1、每一个结点用一个记录来表示,该记 录包括一个运算符域和若干个指向子结 点的指针域。
例: a:=b*-c+b*-c
assign a * + * a assign + *
b
- b c 抽象语法树
c
b DAG
c
方法1
rop为: =,<>,<= <,>=,>
3.转向语句的四元式: 有以下三种跳转四元式:
•(jnz , a , - , p) 表示 if a goto p; •(jrop , x , y , p) 表示 if x rop y goto p; •( j , - , - , p) 表示 goto p;
4.条件语句的四元式: 例1:if a<b then x:=a+b else x:=a-b 对应的四元式为: (1) (j< , a , b , 3 ) 回填 (2) (j , - , - , 6 ) 回填 (3) (+ , a , b , T1 ) (4) (:= , T1 , - , x ) 回填 (5) ( j , - , - , 8 ) (6) ( - , a , b , T2 ) (7) (:= , T2 , - , x ) (8) …… 例2:if a<b and e>d then x:=a+b else x:=a-b 例3:if a<b or e>d then x:=a+b else x:=a-b
四元式:
arg1、arg2为参加 运算的两个分量 result为运算结果
一般形式:(Op,arg1,arg2,result)
举例说明:
1.表达式的四元式: 例1.a*b+c/d
若为单目运算,arg2为 空,用“-”表示
(* , a , b , T1) (/ , c , d , T2) (+ , T1 , T2 , T)
语义分析
在词法分析和语法分析之后,编译 程序要完成语义分析和翻译工作。由 于编译器完成的分析是静态定义的,所 以,语义分析也可称作静态语义分析 (static semantic analysis)。
语义分析的具体工作
1、类型检查;
2、控制流检查;
3、一致性检查;
4、相关名字检查
语法制导翻译
对文法中的每个产生式都附加一个语义动作或 语义子程序,且在语法分析过程中,每当需要使用 一个产生式进行推导或规约时,语法分析程序除执 行相应的语法分析动作之外,还要执行相应地语义 动作或语义子程序。每个语义子程序都指明了相应 产生式中各个符号的具体含义,并规定了使用该产 生式进行分析时所应采取的语义动作。
例
a:=b*-c+b*-c
op arg1 uminus c * b uminus c * b + := T2 T5 arg2 T1 T3 T4 result T1 T2 T3 T4 T5 a
三地址代码-三元式
三元式顾名思义就是带有三个域的记录结 构,他的一般形式为 (i)(op,arg1,arg2) 其中,(i)为三元式的编号,也代表了 该式的运算结果,op,arg1,arg2的含 义与四元式类似,区别在于arg可以是某 三元式的序号,表示用该三元式的结果作 为运算对象。
由此可见:抽象文法符号的具体语义信息,是在语法分析同 步的语义处理过程中获取和加工的。
属性文法
将语义以“属性”的形式附加到各 文法符号上,再根据产生式所蕴含的语 义,给出每个文法符号的属性的求值规 则,从而形成一种带有语义属性的前后 文无关文法,即属性文法。
属性
一个文法符号X的语义信息我们称之为语义 属性或简称为属性(Atrributes)
三地址代码-间接三元式
建立两个与三元式有关的表格,一个称 为三元式表,用于存放各三元式本身;另 一个称为执行表,它按照三元式的执行顺 序,依次列出相应各三元式在三元式表中 的位置,也就是说我们用一个三元式表连 同执行表来表示中间代码。通常我们称这 种表示方法为间接三元式。
例
x:=(a+b)*c b:=a+b y:=c*(a+b)
三地址码的各种形式:P170
1. 2. 3. 4. x:=y op z Goto L Param x x:=y[i] x := op z if x relop y goto L call p,n x[i]:=y x:=*y x:=y if a goto L return y *x:=y
5. x:=&y
源程序
语法分析
中间代码
优化
优化后中间代码
目标代码
代码生成
中间代码
中间代码也叫中间语言 (Intermediate code /language)是:源 程序的一种内部表示,不依赖目标机的结构, 复杂性介于源语言和机器语言之间。
中间代码的优点
1、逻辑结构清楚; 2、利于不同目标机上实现同一种语言; 3、利于进行与机器无关的优化;
中间代码常见的几种形式
1、后缀式 2、图表示法 抽象语法树、DAG图 3、三地址代码 三元式、四元式、间接三元式
后缀式
后缀式是波兰逻辑学家卢卡西维奇 (J.Lukasiewicz)提出的一种对表达式的 表示方法:每一运算符都置于其运算对象之 后,即操作数写在前面,算符写在后面。 它的特点是:表达式中各个运算是按运算符 出现的顺序进行的,故无需用括号来指示运 算顺序,因而又称为无括号式。
5.循环语句的四元式 待讨论循环语句的翻译时介绍。
语法制导的翻译方法:
就是对文法中的每个产生式都附加一个 语义动作或语义子程序,且在语法分析过程中, 每当需要使用一个产生式进行推导或归约时,语 法分析程序除执行相应的语法分析动作之外,还 要执行相应地语义动作或语义子程序。每个语义 子程序都指明了相应产生式中各个符号的具体含 义,并规定了使用该产生式进行分析时所应采取 的语义动作。 翻译过程见P171表7。3。 这种模式既把语法分析与语义处理分开,又 令其平行地进行,让其在同一遍扫描中同时完成 语法分析和语义处理两项工作。
实例
表达式(中缀式): A+B*(C-D)+E/(C-D) 后缀式: A B CD- * + E CD- /+ 表达式(中缀式):
(a=0∧ b>3)∨ (e ∧x >y) ∧∨ 后缀式: a0=b3 > ∧ e xy >
结论
从以上两个例子我们可得出: 1、在两种表示中,运算对象出现的顺序相同; 2、在后缀表示中,运算符按实际计算顺序 从左到右排列,且每一运算符总是跟在运算 对象之后。 翻译成后缀式的语义描述见P167表7.1。
赋值语句翻译为三地址码的属性文法 P171 ,表7.3
三地址代码—四元式
四元式实际上是一种“三地址语句”的 等价表示,是一个带有四个域的记录结构。 它 的一般形式为: (op,arg1,arg2,result) 需要指出的是:每个四元式只能有一个 运算符,所以,一个复杂的表达式只能由多 个四元式构成的序列表示。
(* , a , b , T1) (- , T1 , c , T2) (@ , T2 , -, T) @表示单目运算减
例2.-(a*b-c)
2.赋值语句的四元式:
把赋值看成一种运算,arg2为空 例1:x:=10 (:= , 10, - , x)
例2:x:= -(a*b-c)
(* , a , b , T1) (- , T1 , c , T2) (@ , T2 , - , T) (:= , T , - , x)
#
语法制导翻译的实质
根据文法中每个产生式所蕴含的语义, 为其配备一个(或多个)语句或子程序, 对所要完成的功能进行描述,在语法分 析过程中,当分析器使用该产生式进行 语法分析时(不论是推导还是规约), 除完成语法分析动作之外,还将调用为 其配备的语义子程序,进行相应地语义 处理,完成语义翻译工作。
例1
a+a*(b-c)+(b-c)*d + + a a * b c c * d
b
翻译成抽象语法树的属性文法见P169表7.2
图表示法-DAG图
DAG(Directed Acyclic Graph)有向无循环图
对表达式中的每个子表达式,DAG都有一个 结点,一个内部结点代表一个操作符,他的 孩子代表操作数。在一个DAG中代表公共子 表达式的节点 具有多个父结点(与抽象语 法树中公共子表达式被表示为重复的子树不 同)
x:=(a+b)*c b:=a+b y:=c*(a+b)
三元式表 (1)(+,a,b) (2)(*,(1),c) (3)(:=,x,(2)) (4)(:=,b,(1)) (5)(:=,y,(2))
三元式与间接三元式之间的区别
1、由于间接三元式在执行表中已经依次列出每 次要执行的那个三元式,若其中有相同的三元 式,则仅需在三元式表中保存其中之一,即三 元式的项数一般比执行表的项数少; 2、当进行代码优化需要挪动运算顺序时,则只 需对执行表进行相应地调整,而不必再改动三元 式本身,这样,就避免了前面讲到的因改变三元 式的顺序所引起的麻烦。
2、对同一表达式而言,所需的三元式或 四元式的个数一般都是相同的。
三元式和四元式的比较
不同点: 1、由于三元式没有result字段,且不需要临时变量, 故三元式比四元式占用的存储空间少; 2、在进行代码优化处理时,常常需要挪动一些运算 的位置,这对于三元式序列来说是很困难的,但对于 四元式来说,由于四元式之间的相互联系是通过临时 变量来实现的,所以,更改其中一些四元式给整个系 列带来的影响就比较小。
1 2 3 4 5 6 7 8 9 10
…
id
assign …
a
9 … 8 …
三地址代码
三地址代码最基本的用法形式: x:=y op z 其中x、y、z为名字、常数或编译时产生的 临时变量;op代表运算符号。每个语句的右边只 能有一个运算符。 例如:x+y*z可以翻译为: T1:=y*z T2:=x+T1 T1、T2位编译时产生的临时变量
第七章语义分析和中间代码生成
1、 编译程序的任务是把源语言程序翻译成目标程序, 有些编译程序在编译过程中,不产生中间语言,而 是直接从源语言程序翻译成目标语言程序。
源程序
编译程序
目标代码
以上编译过程省略了中间语言,它不利于编译所产生的目 标代码的优化.为了产生高质量的代码,可以将源语言程序首 先翻译成一种特殊形式的中间语言代码形式,并对其进行优化, 然后再将它翻译成最终的目标代码。
例:
对于文法: E →E+T | T T→ digit
产生式 语义子程序
1、E→ E(1)+T {E.Val=E(1).Val+T.Val 2、E→ T {E.Val=T.Val} 3、T→ digit {T.Val=digit}
例
语法分析栈 语义信息栈 T + E … # T.Val ‘ +’ E(1).Val … E … E.Val …
三元式
x:=(a+b)*c b:=a+b y:=c*(a+b)
(1)(+,a,b) (5) (+,a,b) (2)(*,(1),c) (6)(*,c,(5)) (3)(:=,x,(2)) (7)(:=,y,(6)) (4)(:=,b,(1))
间接三元式
执行表 (1) (2) (3) (4) (1) (2) (5)
后缀式的推广 条件语句的翻译: If e THEN S1 else S2
图表示法-抽象语法树
在语法树中去掉一些对翻译不必要的信 息后,获得的更有效的源程序的中间表示, 这种经过变换后的语法树称为抽象语法树。 在抽象语法树中,操作符和关键字都不 作为叶子节点出现,而是把它们作为内部 节点,即这些叶子节点的父节点。
例
a:=b*-c+b*-c
op (0) (1) uminus * arg1 c b (0) (2) (3) arg2
(2)
(3) (4)
uminus
* +
cΒιβλιοθήκη Baidu
b (1) a
(5)
assign
(4)
三元式和四元式的比较
相同点: 1、无论在一个三元式序列还是四元式序列 中,各个三元式或四元式都是按相应表达 式的实际运算顺序出现的;
assign • id + *
• •
•
a • • *
• •
id
id
b
c
id
id
b
c
uminus •
Uminus •
方法2
把所有的结点安排在一个记录的 数组中,结点的位置或索引作为 指向地点的指针。
0
id
id uminus * id id uminus * +
b
c 1 0 B C 5 4 3 6 7 2
例
a+a*(b-c)+(b-c)*d
+ + * a * d
b
c
抽象语法树的表示方法
1、每一个结点用一个记录来表示,该记 录包括一个运算符域和若干个指向子结 点的指针域。
例: a:=b*-c+b*-c
assign a * + * a assign + *
b
- b c 抽象语法树
c
b DAG
c
方法1
rop为: =,<>,<= <,>=,>
3.转向语句的四元式: 有以下三种跳转四元式:
•(jnz , a , - , p) 表示 if a goto p; •(jrop , x , y , p) 表示 if x rop y goto p; •( j , - , - , p) 表示 goto p;
4.条件语句的四元式: 例1:if a<b then x:=a+b else x:=a-b 对应的四元式为: (1) (j< , a , b , 3 ) 回填 (2) (j , - , - , 6 ) 回填 (3) (+ , a , b , T1 ) (4) (:= , T1 , - , x ) 回填 (5) ( j , - , - , 8 ) (6) ( - , a , b , T2 ) (7) (:= , T2 , - , x ) (8) …… 例2:if a<b and e>d then x:=a+b else x:=a-b 例3:if a<b or e>d then x:=a+b else x:=a-b
四元式:
arg1、arg2为参加 运算的两个分量 result为运算结果
一般形式:(Op,arg1,arg2,result)
举例说明:
1.表达式的四元式: 例1.a*b+c/d
若为单目运算,arg2为 空,用“-”表示
(* , a , b , T1) (/ , c , d , T2) (+ , T1 , T2 , T)
语义分析
在词法分析和语法分析之后,编译 程序要完成语义分析和翻译工作。由 于编译器完成的分析是静态定义的,所 以,语义分析也可称作静态语义分析 (static semantic analysis)。
语义分析的具体工作
1、类型检查;
2、控制流检查;
3、一致性检查;
4、相关名字检查
语法制导翻译
对文法中的每个产生式都附加一个语义动作或 语义子程序,且在语法分析过程中,每当需要使用 一个产生式进行推导或规约时,语法分析程序除执 行相应的语法分析动作之外,还要执行相应地语义 动作或语义子程序。每个语义子程序都指明了相应 产生式中各个符号的具体含义,并规定了使用该产 生式进行分析时所应采取的语义动作。
例
a:=b*-c+b*-c
op arg1 uminus c * b uminus c * b + := T2 T5 arg2 T1 T3 T4 result T1 T2 T3 T4 T5 a
三地址代码-三元式
三元式顾名思义就是带有三个域的记录结 构,他的一般形式为 (i)(op,arg1,arg2) 其中,(i)为三元式的编号,也代表了 该式的运算结果,op,arg1,arg2的含 义与四元式类似,区别在于arg可以是某 三元式的序号,表示用该三元式的结果作 为运算对象。
由此可见:抽象文法符号的具体语义信息,是在语法分析同 步的语义处理过程中获取和加工的。
属性文法
将语义以“属性”的形式附加到各 文法符号上,再根据产生式所蕴含的语 义,给出每个文法符号的属性的求值规 则,从而形成一种带有语义属性的前后 文无关文法,即属性文法。
属性
一个文法符号X的语义信息我们称之为语义 属性或简称为属性(Atrributes)
三地址代码-间接三元式
建立两个与三元式有关的表格,一个称 为三元式表,用于存放各三元式本身;另 一个称为执行表,它按照三元式的执行顺 序,依次列出相应各三元式在三元式表中 的位置,也就是说我们用一个三元式表连 同执行表来表示中间代码。通常我们称这 种表示方法为间接三元式。
例
x:=(a+b)*c b:=a+b y:=c*(a+b)
三地址码的各种形式:P170
1. 2. 3. 4. x:=y op z Goto L Param x x:=y[i] x := op z if x relop y goto L call p,n x[i]:=y x:=*y x:=y if a goto L return y *x:=y
5. x:=&y
源程序
语法分析
中间代码
优化
优化后中间代码
目标代码
代码生成
中间代码
中间代码也叫中间语言 (Intermediate code /language)是:源 程序的一种内部表示,不依赖目标机的结构, 复杂性介于源语言和机器语言之间。
中间代码的优点
1、逻辑结构清楚; 2、利于不同目标机上实现同一种语言; 3、利于进行与机器无关的优化;
中间代码常见的几种形式
1、后缀式 2、图表示法 抽象语法树、DAG图 3、三地址代码 三元式、四元式、间接三元式
后缀式
后缀式是波兰逻辑学家卢卡西维奇 (J.Lukasiewicz)提出的一种对表达式的 表示方法:每一运算符都置于其运算对象之 后,即操作数写在前面,算符写在后面。 它的特点是:表达式中各个运算是按运算符 出现的顺序进行的,故无需用括号来指示运 算顺序,因而又称为无括号式。
5.循环语句的四元式 待讨论循环语句的翻译时介绍。
语法制导的翻译方法:
就是对文法中的每个产生式都附加一个 语义动作或语义子程序,且在语法分析过程中, 每当需要使用一个产生式进行推导或归约时,语 法分析程序除执行相应的语法分析动作之外,还 要执行相应地语义动作或语义子程序。每个语义 子程序都指明了相应产生式中各个符号的具体含 义,并规定了使用该产生式进行分析时所应采取 的语义动作。 翻译过程见P171表7。3。 这种模式既把语法分析与语义处理分开,又 令其平行地进行,让其在同一遍扫描中同时完成 语法分析和语义处理两项工作。
实例
表达式(中缀式): A+B*(C-D)+E/(C-D) 后缀式: A B CD- * + E CD- /+ 表达式(中缀式):
(a=0∧ b>3)∨ (e ∧x >y) ∧∨ 后缀式: a0=b3 > ∧ e xy >
结论
从以上两个例子我们可得出: 1、在两种表示中,运算对象出现的顺序相同; 2、在后缀表示中,运算符按实际计算顺序 从左到右排列,且每一运算符总是跟在运算 对象之后。 翻译成后缀式的语义描述见P167表7.1。
赋值语句翻译为三地址码的属性文法 P171 ,表7.3
三地址代码—四元式
四元式实际上是一种“三地址语句”的 等价表示,是一个带有四个域的记录结构。 它 的一般形式为: (op,arg1,arg2,result) 需要指出的是:每个四元式只能有一个 运算符,所以,一个复杂的表达式只能由多 个四元式构成的序列表示。
(* , a , b , T1) (- , T1 , c , T2) (@ , T2 , -, T) @表示单目运算减
例2.-(a*b-c)
2.赋值语句的四元式:
把赋值看成一种运算,arg2为空 例1:x:=10 (:= , 10, - , x)
例2:x:= -(a*b-c)
(* , a , b , T1) (- , T1 , c , T2) (@ , T2 , - , T) (:= , T , - , x)
#
语法制导翻译的实质
根据文法中每个产生式所蕴含的语义, 为其配备一个(或多个)语句或子程序, 对所要完成的功能进行描述,在语法分 析过程中,当分析器使用该产生式进行 语法分析时(不论是推导还是规约), 除完成语法分析动作之外,还将调用为 其配备的语义子程序,进行相应地语义 处理,完成语义翻译工作。
例1
a+a*(b-c)+(b-c)*d + + a a * b c c * d
b
翻译成抽象语法树的属性文法见P169表7.2
图表示法-DAG图
DAG(Directed Acyclic Graph)有向无循环图
对表达式中的每个子表达式,DAG都有一个 结点,一个内部结点代表一个操作符,他的 孩子代表操作数。在一个DAG中代表公共子 表达式的节点 具有多个父结点(与抽象语 法树中公共子表达式被表示为重复的子树不 同)
x:=(a+b)*c b:=a+b y:=c*(a+b)
三元式表 (1)(+,a,b) (2)(*,(1),c) (3)(:=,x,(2)) (4)(:=,b,(1)) (5)(:=,y,(2))
三元式与间接三元式之间的区别
1、由于间接三元式在执行表中已经依次列出每 次要执行的那个三元式,若其中有相同的三元 式,则仅需在三元式表中保存其中之一,即三 元式的项数一般比执行表的项数少; 2、当进行代码优化需要挪动运算顺序时,则只 需对执行表进行相应地调整,而不必再改动三元 式本身,这样,就避免了前面讲到的因改变三元 式的顺序所引起的麻烦。
2、对同一表达式而言,所需的三元式或 四元式的个数一般都是相同的。
三元式和四元式的比较
不同点: 1、由于三元式没有result字段,且不需要临时变量, 故三元式比四元式占用的存储空间少; 2、在进行代码优化处理时,常常需要挪动一些运算 的位置,这对于三元式序列来说是很困难的,但对于 四元式来说,由于四元式之间的相互联系是通过临时 变量来实现的,所以,更改其中一些四元式给整个系 列带来的影响就比较小。
1 2 3 4 5 6 7 8 9 10
…
id
assign …
a
9 … 8 …
三地址代码
三地址代码最基本的用法形式: x:=y op z 其中x、y、z为名字、常数或编译时产生的 临时变量;op代表运算符号。每个语句的右边只 能有一个运算符。 例如:x+y*z可以翻译为: T1:=y*z T2:=x+T1 T1、T2位编译时产生的临时变量
第七章语义分析和中间代码生成
1、 编译程序的任务是把源语言程序翻译成目标程序, 有些编译程序在编译过程中,不产生中间语言,而 是直接从源语言程序翻译成目标语言程序。
源程序
编译程序
目标代码
以上编译过程省略了中间语言,它不利于编译所产生的目 标代码的优化.为了产生高质量的代码,可以将源语言程序首 先翻译成一种特殊形式的中间语言代码形式,并对其进行优化, 然后再将它翻译成最终的目标代码。