语法制导翻译
编译原理分知识点习题 语法制导和翻译
解答:所谓语法制导翻译,是指在语法规则的制导下,通过计算语义规则,完成对输入符号串的翻译。
由于使用属性文法时把语法规则和语义规则分开,但在使用语法规则进行推导或规约的同时又使用这些语义规则来知道翻译与最终产生目标代码,所以称为语法制导翻译。
D →attrlist namelist|attrlist(D)
Namelist→id,namelist|id
Attrlist→A attrlist|A
A →decimLeabharlann Baidul|fixed|float|real
D→ attrlist (D) 的含义是:在括号中的声明提到的所有名字有attrlist中给出的属性,而不管声明嵌套多少层。写一个翻译方案,它将每个名字的属性添入符号表。
GEN(+,E1.PLACE, E2.PLACE,E.PLACE)}
(3)E::= E1*E2{ E.PLACE:=NEWTEMP;
GEN(*,E1.PLACE, E2.PLACE,E.PLACE)}
(4)E::=-E1{ E.PLACE:=NEWTEMP;
GEN(@,E1.PLACE,__,E.PLACE)}
namelist→namelist1,i
namelist→i
相应的语义动作为:
06第6章 语法制导翻译技术PPT课件
2020/7/29
11
6.4 自顶向下语法制导翻译
自顶向下的语法制导翻译有递归下降翻译和LL(1)翻译。 递归下降翻译(在适当位置插入实现动作符号的子程序):
例:算术表达式翻译 文法如下:(@为输 出其后的符号串) ① E→E+T@+ ② E→T ③ T→T*F@* ④ T→F ⑤ F→(E) ⑥ F→a@a ⑦ F→b@b ⑧ F→c@c
⑤ F→(E) ⑥ F→a ⑦ F→b ⑧ F→c
① E→E+T@+ ② E→T ③ T→T*F@* ④ T→F
⑤ F→(E) ⑥ F→a@a ⑦ F→b@b ⑧ F→c@c 8
6.3 语法制导翻译
语法制导翻译:给定一输入序列,根据翻译文法得到翻译该输 入序列的活动序列,从活动序列中分离出动作符号串,然后执 行该动作符号串所规定的动作,从而得到翻译结果。
else error();
} 2020/7/29
E→TE’ E’ →+T@+E’|ε T→FT’ T’ →*F @* T’|ε F→(E)|a@a| b@b| c@c
15
➢ 对ຫໍສະໝຸດ Baidu产生式T’ →*F @* T’|ε ▪ FIRST(*F @* T’)={*} ▪ FOLLOW(T’)={#,+,)}
② E→T
③ T→T*F ⑦ F→b
第四章语法制导的翻译
第四章语法制导的翻译
在3.7节用Yacc写的例子中,我们看到一种有用的描述形式:语言结构的属性附加在代表语言结构的文法符号上,这些属性值由附加在文法产生式的语义动作来计算,这些语义动作在归约对应的产生式时进行计算,由此得到结果。这种描述形式可用来描述编译器的语义分析,因此本章系统地研究这种称之为“语法制导下的语言翻译”的描述方法及其实现。它的语义动作(有时称为语义规则)的计算可以产生代码、把信息存入符号表、显示出错信息、或完成其它工作。语义规则的计算结果就是我们所要的记号流的翻译。
本章讨论语义规则和产生式相联系的两种方式:语法制导的定义和翻译方案。语法制导定义是较抽象的翻译说明,它隐蔽了一些实现细节;而翻译方案陈述了一些实现细节,主要是指明了语义规则的计算次序。在第五章说明语义检查和第七章描述中间代码生成时,大量使用这两种方法。
本章还讨论语法制导定义和翻译方案的实现方法。概念上的方法是,首先分析输入的记号串,建立分析树,然后从分析树得到描述结点属性间依赖关系的有向图,从这个依赖图得到语义规则的计算次序,然后进行计算,最终得到翻译的结果。实际的实现并不需要按上面步骤逐步进行,本章将讨论几种不同限制下的实现方法。
4.1语法制导的定义
语法制导的定义是上下文无关文法的推广,其中每个文法符号都有一个属性集合,它分成两个子集,分别叫做该文法符号的综合属性集合和继承属性集合。如果我们把分析树上的结点看成是保存对应文法符号的属性的记录,那么属性对应记录的域。属性可以表示任何东西:串、数、类型、内存单元,或其它想表示的东西。分析树结点的属性值由该结点所用产生式的语义规则定义。在语法制导定义中,我们把其中的文法称为基础文法。
编译原理(龙书)课后习题解答(详细)
编译原理(龙书)课后习题解答(详细)
编译原理(龙书)课后题解答
第一章
1.1.1 :翻译和编译的区别?
答:翻译通常指自然语言的翻译,将一种自然语言的表述翻译成另一种自然语言的表述,而编译指的是将一种高级语言翻译为机器语言(或汇编语言)的过程。
1.1.2 :简述编译器的工作过程?
答:编译器的工作过程包括以下三个阶段:
(1) 词法分析:将输入的字符流分解成一个个的单词符号,构成一个单词符号序列;
(2) 语法分析:根据语法规则分析单词符号序列中各个单词之间的关系,确定它们的语法结构,并生成抽象语法树;
(3) 代码生成:根据抽象语法树生成目标程序(机器语言或汇编语言),并输出执行文件。
1.2.1 :解释器和编译器的区别?
答:解释器和编译器的主要区别在于执行方式。编译器将源程序编译成机器语言或汇编语言等,在运行时无需重新编译,程序会一次性运行完毕;而解释器则是边翻译边执行,每次执行都需要进行一次翻译,一次只执行一部分。
1.2.2 :Java语言采用的是解释执行还是编译执行?
答:Java一般是编译成字节码的形式,然后由Java虚拟机(JVM)进行解释执行。但是,Java也有JIT(即时编译器)的存在,当某一段代码被多次执行时,JIT会将其编译成机器语言,提升代码的执行效率。
第二章
2.1.1 :使用BNF范式定义简单的加法表达式和乘法表达式
答:
<加法表达式> ::= <加法表达式> "+" <乘法表达式> | <乘法表达式>
<乘法表达式> ::= <乘法表达式> "*" <单项式> | <单项式>
语法制导翻译
静态语义分析 这一步才真正开始考虑程序设计语言的实际意义 静态语义分析的作用:检查出源程序中的静态语义错误
并且将语义正确的语句翻译成中间代码 该过程中通常使用的方法是语法制导翻译
1
第四章 语法制导翻译生成中间代码
语法制导翻译是处理语义的基本方法,它以语法分析为基础, 在语法分析得到语言结构的结果时,对附着于此结构的语 义进行处理,如计算表达式的值、生成中间代码等。
4. 注释分析树上看继承属性与综合属性 继承属性是自上而下计算的 综合属性是自下而上计算的
提醒:除非特别提醒,本章讨论的语法制导翻译是综合属性。
L (print(35+8+))
E .post=35+8+
E .post=35+ + E .post=8
E .post=3 + E .post=5 8
b := f(c1, c2, ..., ck)
(4.1)
6
4.1 语法制导翻译简介
A→α 的语义规则 b := f(c1, c2, ..., ck)
(4.1)
语义规则中的属性存在下述性质与关系。
① 若b是A的属性,c1, c2, ..., ck是α中文法符号的属性,或者 A的其它属性,则称b是A的综合属性。
5
4.1 语法制导翻译简介
语法制导翻译
编译原理
11
8+5*2 n的注释分析树 (annotated parse tree)
E.val = 8
L E.val = 18
+
n T.val = 10
T.val = 8
T.val = 5
*wk.baidu.com
F.val = 2
F.val = 8
F.val = 5
digit.lexval = 2
2
介绍一种形式化的语义描述方法:语法制导的翻译, 包括两种具体形式
▪ 语法制导定义(Syntax-Directed Definitions, SDD): 定义翻译所必须的语义属性和语义规则,一般 不涉及计算顺序。
▪ 翻译模式(translation schemes): 给出语义规则 的计算顺序。
编译原理
5
5.1.1综合属性和继承属性
综合属性:在分析树结点N上的非终结符A的综合 属性是由N上的产生式所关联的语义规则来定义的。 A是产生式的头。结点N上的综合属性只能通过N的 子结点的属性值或结点N本身的属性值计算得到。
继承属性:在分析树结点N上的非终结符B的继承 属性是由N的父结点上的产生式所关联的语义规则 来定义的。 B出现在产生式的体中。结点N上的继 承属性只能通过N的父结点的属性值、结点N本身 的属性值或N的兄弟结点的属性值计算得到。
编译原理 第5章语法制导的翻译
23
5.2.1 依赖图
依赖图描述了某棵特定的分析树上的各个属 性实例之间的信息流(计算顺序)
从实例a1到实例a2的有向边表示计算a2时需要 a1的值。(必须先计算a2,再计算a1)
24
5.2.1 依赖图
依赖图的构造方法 for 分析树中的每个结点n do for 与结点n对应的文法符号的每个属性a do 在依赖图中为a构造一个结点; for 分析树的每个结点n do for 结点n所用产生式对应的每条 语义规则 b:=f(c1,c2,…,ck ) do for i:=1 to k do 从结点ci到结点b构造一条有向边;
32
受控的副作用
受控副作用的例子
L→En
变量声明的SDD中的副作用
通过副作用打印出E的值 总是在最后执行,且不会影响其它属性的求值 addType将标识符的类型信息加入到标识符表中。 只要标识符不被重复声明,标识符的类型信息总是正确的。
print(E.val)
33
5.3 语法制导的翻译方案
10
5.1 语法制导定义
5.语法制导的翻译 在产生式体中加入语义动作,并在适当的时 候执行这些语义动作
E→E1+T
{print ‘+’;}
11
5.1.1 继承属性和综合属性
属性文法和语法制导翻译
语义规则 print(E.val) E.val := E1.val + T.val E.val := T.val T.val := T1.val * F.val T.val := F.val F.val := E.val F.val := digit.lexval
S-属性文法
S-属性文法
在语法树中,一个结点的综合属性的值由其子结点的 属性值决定。 仅使用综合属性的属性文法称为S-属性定义 S属性定义的分析树的分析方法——自底向上的在每个 节点用语义规则来计算综合属性值。
为每个包括过程调用的语义规则引入一个虚综合属性b,把每条 语义规则都变成b=f(c1,c2,...,ck)的形式 依赖图的每个结点表示一个属性 边表示属性间的依赖关系。如果属性b依赖于属性c,那么从c到 b就有一条有向边
依赖图举例
D T.type=real
L .in=real
产生式 D→TL T→int T→real L→L1 , id
Y e=0 f=0
h=0 Z g=1
z
x
y
z
第三遍扫描
一遍扫描的处理方法
在语法分析的同时计算属性值,而不是语法分析构造语法树 之后进行属性的计算,而且无需构造实际的语法树。 一遍扫描的处理方法与语法分析器密切相关的因素:
所采用的语法分析方法 属性的计算顺序
L-属性文法可用于一遍扫描的自顶向下分析,而S-属性文法适 合于一遍扫描的自底向上分析。 此时的语法制导翻译可理解为:直观上说为文法中每个产生 式配上一组语义规则,并且在语法分析的同时执行这些语义 规则
语法制导的翻译
• 继承属性(inherited attribute):结点N的属性值由N的 父结点所关联的语义规则来定义。
– 依赖于N的父结点、N本身和N的兄弟结点上的属性值。
• 不允许N的继承属性通过N的子结点上的属性来定义, 但是允许N的综合属性依赖于N本身的继承属性。
• 在递归子程序法中实现L属性
– 对于每个非终结符号A,其对应的过程的参数 为继承属性,返回值为综合属性
• 在处理规则AX1X2…Xn时,
– 在 们调 为用 参X数i(调)之用前X计i()算;Xi的继承属性值,然后以它 – 在产生式对应代码的最后计算A的综合属性
– 注意:如果所有的文法符号的属性计算按上面 的方式进行,计算顺序必然和依赖关系一致。
– S属性的SDD – L属性的SDD
• 对于这些类型的SDD,我们可以确定属性的计 算顺序,且可以把不需要的属性(及分析树结 点)抛弃以提高效率
a
21
S属性的SDD
• 每个属性都是综合属性
• 都是根据子构造的属性计算出父构造的属性。
• 在依赖图中,总是通过子结点的属性值来计算 父结点的属性值。可以和自顶向下、自底向上 的语法分析过程一起计算
a
25
L属性SDD的例子
• 非L属性的例子:
– ABC
A.s=B.b; B.i=f(C.c, A.s)
第8讲 语法制导翻译_1
例
产生式 (1) L E n
(2) E E1 + T (3) E T (4) T T1 * F (5) T F
(6) F ( E )
(7) F digit
语义规பைடு நூலகம் L.val = E.val E.val = E1.val + T.val E.val = T.val
T.val = T1.val × Fval
T.val = F.val F.val = E.val F.val = digit.lexval
第五章 语法制导翻译
语法制导定义SDD
哈尔滨工业大学 陈鄞
第五章 语法制导翻译
SDD的求值顺序
哈尔滨工业大学 陈鄞
SDD的求值顺序
SDD为CFG中的文法符号设置语义属性。对于 给定的输入串x,应用语义规则计算分析树中各 结点对应的属性值
每个S-属性定义都是L-属性定义
L-SDD的正式定义
一个SDD是L-属性定义,当且仅当它的每个属性要
么是一个综合属性,要么是满足如下条件的继承属
性:假设存在一个产生式A→X1X2…Xn,其右部符 号Xi (1 i n)的继承属性仅依赖于下列属性:
A的继承属性
为什么不能是综合属性?
产生式中Xi左边的符号 X1, X2, … , Xi-1 的属性 Xi本身的属性,但Xi 的全部属性不能在依赖图中形成环路
《编译原理》第5章 语法制导翻译
5.2.4 表达式的无环有向图
◆无环有向图 (Directed Acyclic Graph,简称dag) 用途:提取表达式中的公共子表达式, 以取得目标程序的局部优化。 方法:执行mknode和mkleaf时,检查是 否已有相同的结点,若有,则返回相应结 点的指针。
例5.9 表达式 a+a*(b-c)+(b-c)*d 的dag
5.2.1 语法树
产生式s→if B then S1 else S2的语法树 if-then-else / | \ B S1 S2 赋值语句的语法树 assignment variable expression 在语法树中,运算符号和关键字都不在叶结点, 而是在内部结点中出现。
5.2.2 构造表达式的语法树
分析树法: 输入串→分析树→依赖图→计算次序 基于规则的方Hale Waihona Puke Baidu: 在构造编译器时,用手工或专 门的工具来分析语义规则,确定属性值的计算顺序。 忽略语义规则的方法:在分析过程中翻译,那么 计算顺序由分析方法来确定而表面上与语义规则无 关。这种方法限制了能被实现的语法制导定义的种 类。 后两种方法不必显式构造依赖图,因此时空效率 更高。
语义处理
总目标:生成等价的中间代码
2. 代码结构
计算学科:对信息(数据表示)描述和变 换算法的系统研究 变换:源、目标以及源与目标的对应关系 语句的代码结构 语句分类: 说明语句——符号表的查填 可执行语句——指令代码
第四章-语法制导的翻译-复习+习题
15
例
题
1
top
S
S.num
... ... state val
栈 为文法 S→(L)|a L→L,S|S 写一个语法制导定义,它输出括号的对数。 写一个语法制导定义,它输出括号的对数。
S′ → S S→(L) S→a L → L1 , S L→S
print (val[top]) val[top]) val[topval[top-2] := val[top-1] val[topval[top] := 0 val[topval[top-2]:= val[top-2]+val[top] val[top-
16
例
题
2
外层括号数目 为文法 S→(L)|a L→L,S|S 写一个翻译方案,它输出每个a的嵌套深度。例如, 写一个翻译方案,它输出每个a的嵌套深度。例如,对 ),输出的结果是1 2。 于( a , ( a , a) ),输出的结果是1 2 2。 S′ → {S. depth := 0 } S ′ S → {L. depth := S. depth + 1 } ( L ) S → a {print (S. depth) } L → {L1. depth := L. depth }L1 , {S. depth := L. depth }S L → {S. depth := L. depth }S
编译原理 语法制导翻译
例5.6
例5.5依赖图的边:小数字大数字
按编号排列满足要求的拓扑排序
a4=real; a5=real; addtype(id3.entry, a5); a7=a5; addtype(id2.entry, a7); a9=a7; addtype(id1.entry, a9);
5.2 构造语法树
5.3 自底向上计算S-属性定义
与LR(1)分析器结合
在栈中保存语法符号的属性值
归约时,利用栈中语法符号(产生式右部)
属性值计算新的(左部符号的)综合属性值
自底向上计算S-属性定义示例
A XYZ A.a = f(X.x,Y.y,Z.z) val[ntop]=f(val[top-2], val[top-1], val[top])
digit.lexval:终结符只有综合属性,由词法分 析器提供 开始符号通常没有继承属性
5.1.2 综合属性
只有综合属性:S-属性定义
语法树自底向上计算属性
例5
5.1.3 继承属性
表达程序语言结构在上下文中的相互依
赖关系更加自然、方便
例5.3 变量定义
real id1, id2, id3;
作为中间表示形式——分离分析与翻译
在进行语法分析的同时进行翻译存在缺
陷:
适合分析的文法可能未反映自然的语言结构 分析顺序可能与翻译顺序不一致
编译原理分知识点习题-语法制导和翻译
1.一般情况下,为什么语义分析部分仅产生中间代码
解答:一般情况下,语义分析部分仅产生中间代码,其原因是:
可使难点分解,分别解决。
可对语义分析产生的中间代码进行优化,以产生高效率的目标代码。
语义分析通常与机器无关,目标代码往往与机器有关。把语义分析与目标代码生成分开,可让一个语义分析程序适用于多个目标代码生成程序。
2.(湖北省高等教育自学考试)什么是语法制导翻译为什么把这种方法叫语法制导翻译
解答:所谓语法制导翻译,是指在语法规则的制导下,通过计算语义规则,完成对输入符号串的翻译。
由于使用属性文法时把语法规则和语义规则分开,但在使用语法规则进行推导或规约的同时又使用这些语义规则来知道翻译与最终产生目标代码,所以称为语法制导翻译。
3.'
4.
5.给出将附值语句翻译成四元式的语法制导定义,允许右部表达式含有加法、乘法、取负、
括号运算。生成赋值语句X:=B*(C+D)+A的四元式。
解答:赋值语句的自下而上的语法制导翻译过程描述为:
规则语义动作
(1)A::=i:=E {GEN (:=,,__,ENTRY(i) ) }
(2)E::=E1+E2{:=NEWTEMP;
GEN(+,, ,}
(3)E::= E1*E2{ :=NEWTEMP;
'
GEN(*,, ,}
(4)E::=-E1{ :=NEWTEMP;
GEN(@,,__,}
(5)E::=(E1) {:= }
(6)E::=i {:= ENTRY(i) }
生成的赋值语句X:=B*(C+D)+A的四元式为:
(+,C,D,T1)
(
(*,B,T1,T2)
(+,T2,A,T3)
语法制导翻译
语法制导翻译
语法制导翻译是一种将源语言(通常为自然语言)的语法结构与目标语言的语法结构相对应的翻译方法。它通过语法分析器和语法制导翻译器来实现。在语法制导翻译中,源语言和目标语言的语法规则被定义成一个或多个上下文无关文法。
语法制导翻译的主要思想是在语法分析树中嵌入翻译动作,并通过语法制导翻译器将源语言转换为目标语言。语法制导翻译器的主要任务是对每个语法分析树节点进行翻译动作的定义,并将这些翻译动作与语法分析器的分析过程相结合,最终生成目标语言的语法结构。
语法制导翻译是机器翻译领域的一种重要研究方向,它可以有效地解决自然语言翻译中的语言差异和歧义问题。同时,它也是编译原理、计算机语言学等领域中的基础性问题。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
for循环语句翻译递归下降法输出三地址码/////////////
#define MAX 100
#include
#include
#include
char str[MAX];
char ch;
int turn;
char strToken[MAX];
int kind;
int n=0;//存放strtoken[]元素的个数
struct Word//结构体存放单词
{
int sort;
char word[MAX];//存放strtoken[]的内容
};
//record[x]=new Word;
Word *record[12];//放所有识别出来的单词,分别存放他们的编号以及字符串,x是其下标
////////////////////词法分析///////////////////////
int buffer()//载入
{
int i=0;
cout<<"输入程序,以“#”作为结束标志。"< for(int n=0;n<=MAX;n++) { for(;i<=MAX;i++) { scanf("%c",&str[i]); /////////////cin>>str[i]不可用,用C语言读入字符。 if(str[i]=='#') break;///////如果尾数为识别码#,则表示程序读完,跳出循环. } break; } return(i); bool IsLetter(char ch)///////////判断是否是字母 { if(ch>=65&&ch<=90||ch>=97&&ch<=122) return(true); else return(false); } bool IsDigit(char ch)//////////判断是否是数字 { if(ch>=48&&ch<=57) return(true); else return(false); } char GetChar(int i)///////读取字符 { char ch; ch=str[i]; return(ch); } char GetBC(char ch)////判断是不是空格或者换行,如果是,直接读取下一个字符直道不再空白为止{ if(ch==32||ch==10) { turn++; ch=GetChar(turn); ch=GetBC(ch);/////////递归实现 return(ch); } else return(ch); } void Concat()/////////////连接,即为strtoken[]赋值 { strToken[n]=ch; n++; int Reserve()/////以单词为单位查找保留字,是则返回编码,不是则返回0,用来区分标志符和保留字{ if(strcmp(strToken," DIM\0")==0)///////调用strcmp函数实现, return(1); else if(strcmp(strToken,"for\0")==0) return(2); else if(strcmp(strToken,"step\0")==0) return(3); else if(strcmp(strToken,"until\0")==0) return(4); else if(strcmp(strToken,"do\0")==0) return(5); else return(6); } void clear() { n=0; } /////////////*语法递归分析*///////////////// int A(int * c,int & q) { if(c[q++]==3) { if(c[q]==7) { q++; return 1; } else {cout<<"step右部出错"< }else {cout<<"error 'step'"< } int B(int * b,int & o) if(b[o++]==4) { if(b[o]==7) { o++; return 1; } else {cout<<"until右部出错"< }else {cout<<"error 'until'"< } int S2(int * d,int & h) { if(d[h++]==6) { if(d[h++]==8) { if((d[h]==6||d[h]==7)) {h++; return 1;} else {cout<<"赋值语句右部出错"< }else {cout<<"赋值语句缺少赋值运算符"< } int S1(int * m,int & n) { if(S2(m,n)) { if(A(m,n)) { if(B(m,n)) return 1; else return 0; }else return 0; }else return 0; } int S(int *a,int & z) { if (a[z++]==2) { if (S1(a,z)) { if(a[z++]==5) {