第六章
属性:代表与文法符号相关的信息,和变量一样,可以进行计算和传递。
(1)综合属性
用于“自下而上”传递信息
在语法树中,一个结点的综合属性的值,由其子结点的属性值确定
(2)继承属性
用于“自上而下”传递信息。
在语法树中,一个结点的继承属性由此结点的父结点和/或兄弟结点的某些属性确定
(2)继承属性
用于“自上而下”传递信息。
在语法树中,一个结点的继承属性由此结点的父结点和/或兄弟结点的某些属性确定
4.语义规则所描述的工作
属性计算
静态语义检查
符号表操作
代码生成
在一个属性文法中,对应于每个产生式A都有一套与之相关联的语义规则,每条语义规则的形式为:
b:=f(c1,c2,…,ck)
这里f是一个函数,而且或者
(1)b是A的一个综合属性并且c1,c2,…ck是产生式右边文法符号的属性;或者
(2)b是产生式右边某个文法符号的一个继承属性并且c1,c2,…ck是A或产生式右边任何文法符号的属性
在这两种情况下,我们都说属性b依赖于属性c1,c2,…,ck.
注意:
(1)终结符只有综合属性,它由词法分析器提供
(2)非终结符既可以有综合属性也可以有继承属性,文法开始符号的所有继承属性作为属性计算前的初始值。
一个有向非循环图的拓扑序是图中结点的任何顺序m1,m2, …mk,使得边必须是从序列中前面的结点指向后面的结点。也就是说,如果mimj是mi到mj的一条边,那么在序列中mi必须出现在mj之前。
4.抽象语法树
这种经变换后的语法树称之为抽象语法树
分析器可以保存与栈中文法符号有关的综合属性值
每当进行归约时,新的属性值就由栈中正在归约的产生式右边符号的属性值来计算
可以通过扩充分析器中的栈来存放这些综合属性值
S-属性文法的翻译器通常可借助于LR分析器实现
属性的计算次序受分析方法所限定的分析树结点建立次序的限制
分析树的结点是自左向右生成
如果属性信息是自左向右流动,那么就有可能在分析的同时完成属性计算
翻译模式是语法制导定义的一种便于翻译的书写形式。其中属性与文法符号相对应,语义规则或语义动作用花括号{ }括起来,可被插入到产生式右部的任何合适的位置上。
这是一种语法分析和语义动作交错的表示法,他表达在按深度优先遍历分析树的过程中何时执行语义动作。
翻译模式给出了使用语义规则进行计算的顺序。可看成是分析过程中翻译的注释。
从翻译模式中消除左递归
对于一个翻译模式,若采用自顶向下分析,必须消除左递归和提取左公因子,在改写基本文法时考虑属性值的计算。
第七章
2.在语义正确的基础上生成一种中间代码或目标代码。
2.类型检查:按语言的类型规则,检查运算的合法性与运算分量类型的一致性,必要时作类型转换。
3.识别含义:根据语言的语义定义(形式或非形式),识别程序中各构造成分组合到一起的含义,并作相应的语义处理
5.一致性检查:在很多场合要求对象只能被说明一次。如:pascal语言规定同一个标识符在一个分程序中只能被说明一次等。
6.相关名字检查:如:Ada,循环或块可以有一个名字,它出现在这些结构的开头或结尾。编译程序必须检查这两个地方用的名字是否相同。
无循环有向图(DAG)
DAG与抽象语法树基本上一样,对表达式中的每个子表达式,DAG中都有一个结点。一个内部结点表示一个操作符,它的孩子表示操作数。
两者所不同的是,在一个DAG中代表公共子表达式的结点具有多个父结点,而在一棵抽象语法树中公共子表达式被表示为重复的子树。
逆波兰表示法
波兰表示是一种既不须考虑优先关系、又不用括号的一种表示表达式的方法(前缀式)。
现在我们要介绍的刚好是另一种波兰表示形式,称为后缀式,即运算符在后。
算符:OP
第一运算分量:ARG1
第二运算分量:ARG2
{E.val:=TRIP(OP,E1.val,E2.val)}
这儿TRIP(OP,ARG1,ARG2)是一个语义过程,它产生(OP,ARG1,ARG2)并放入三元式表中,返回三元式在表中的位置
(2)E→i {E.val:=Entry(i)}
Entry是一个语义过程,它查找i在符号表中的位置。若用LOOKUP(NAME)函数表示对NAME查找符号表,找到则返回表项位置,找不到则返回NULL。 于是可如下实现:
词法分析器扫描到标识符i时送回(种别码,i值),语法分析器把i放入语义变量i.LEXCAL中,这时就可以调用Entry过程:
无循环有向图(DAG)
DAG与抽象语法树基本上一样,对表达式中的每个子表达式,DAG中都有一个结点。一个内部结点表示一个操作符,它的孩子表示操作数。
两者所不同的是,在一个DAG中代表公共子表达式的结点具有多个父结点,而在一棵抽象语法树中公共子表达式被表示为重复的子树
三:某些语句的四元式及翻译
说明语句的翻译
为局部名字建立符号表条目
为它分配存储单元
符号表中包含名字的类型和分配给它的存储单元的相对地址等信息
程序语言中的说明语句都是给编译程序提供信息的,诸如类型、维数、每维的界种类等,因此一般不生成目标,只是在编译时把有关信息填入相应表格即可。
四:循环与分情况语句的翻译
例如F1→for i:=E1 对应的语义动作:
(1)产生四元式:emit(:=,E1.place,--,ENTRY(i));
(2)保留ENTRY(i):F1.place:=ENTRY(i);
(3)因为goto over 的转移地址暂时填不上,必须
建链:F1.chain:=nextquad;
(4)产生无条件转移指令:emit(j,--,--,0);
(5)保留again的地址:F1.quad:=nextquad;
五:过程调用的翻译
1. 过程调用主要解决两个问题:
(1)把程序控制转移到子程序(过程段),执行完毕再返回。这个问题很好解决。
(2)传递实在参数。我们前面谈到过几种不同的参数传递方式(传名、传值、传地址),它们的语义动作也就有所区别。
语法树
后缀式
三地址代码表示
语法树,有向非循环图和后缀式表示源程序的自然层次结构。
1. 用作计算逻辑值
2. 用作控制流语句如if-then,if-then-else和while-do等之中的条件表达式
控制流语句中的布尔表达式的翻译
回填
一遍扫描:语法制导翻译技术是属于一遍扫描分析