第5章 属性文法与语义分析
编译原理课件05语法制导翻译技术和中间代码生成
5.4 中间代码
四元式的特点: 1. 四元式出现的顺序和语法成份的计值 顺序相一致. 2. 四元式之间的联系是通过临时变量实 现的,这样易于调整和变动四元式. 3. 便于优化处理.
5.4 中间代码
编译系统中,有时将四元式表示成另一 种更直观,更易理解的形式——三地址代 码或三地址语句. 三地址代码形式定义为: result := arg1 OP arg2 三地址语句:语句中是三个量的赋值语句, 三地址语句 每个量占一个地址.
5.5 自下而上的语法制导翻译
例3 简单算术表达式翻译到四元式的 语义描述 例如,设有简单算术表达式的文法: E→E+E | E*E | (E) | i
T R / S T
c S a c
c R S
输入是bR / bTc / bSc /ac 输出为: 1 4 5 314 24 31 给出相应语义动作(翻 译方案) S→bTc { print "1"} { print "2"} S→a R T→R { print "3"} R→R/S { print "4"} R→S { print "5"}
5.1 概述
例如: 表达式 A+B*C 对运算对象进行类型检查, 对变 量进行先定义后使用检查 执行真正的翻译 如果静态语义正确, 语义处理则要执 行真正的翻译, 即生成程序的某种中间 代码的形式或直接生成目标代码.
5.1 概述
目前多数编译程序进行语义分析的方 法是采用语法制导翻译法 .它不是一种 采用语法制导翻译法 形式系统, 但它比较接近形式化. 语法制导翻译法使用属性文法为工具 来描述程序设计语言的语义.
5.4 中间代码
属性文法的名词解释
属性文法的名词解释属性文法(Attribute Grammar)是一种形式化的文法,用于描述计算机程序中的语法结构和语义信息之间的关系。
它是上下文无关文法(Context-Free Grammar)的扩展,引入了属性(Attribute)的概念,用于描述语法结构的特性和语义信息的传递。
属性文法的定义包括两个部分:语法规则和属性定义。
语法规则描述了语法结构的产生方式,属性定义则指定了每个语法结构的属性计算方式。
在属性文法中,语法结构可以是终结符、非终结符和属性。
终结符是语法中不可再分的最基本元素,例如数字、运算符等。
非终结符定义了可扩展的语法结构,例如表达式、语句等。
属性则用于描述语法结构的特性。
一个语法结构可以有多个属性,例如,一个表达式可以包含属性值、数据类型等。
属性文法中的语法规则由产生式表示。
产生式(Production)定义了从一个语法结构生成另一个语法结构的方式。
每个产生式都有一个左部和右部。
左部是一个非终结符,右部是由终结符、非终结符和属性组成的序列。
产生式的右部可以包含语义规则,用来计算属性值。
属性文法中的属性定义规定了每个语法结构的属性计算方式。
一个属性可以是综合属性(Synthesized Attribute)或继承属性(Inherited Attribute)。
综合属性定义了由当前语法结构计算的属性值,它的值只依赖于当前语法结构自身和它的子结构。
继承属性定义了由当前语法结构的父结构计算的属性值,它的值依赖于父结构的属性值和兄弟结构的属性值。
在属性文法的计算过程中,首先对终结符和非终结符的属性进行初始化。
然后按照产生式进行属性传递和计算。
属性传递分为自顶向下和自底向上两种方式。
自顶向下传递属性规定了属性值从父结构向子结构计算传递的方式,自底向上传递属性规定了属性值从子结构向父结构计算传递的方式。
属性文法的应用领域广泛。
在编译原理中,属性文法被用于描述语言的语法和语义。
它可以通过属性计算的方式对程序进行语义分析和优化。
编译原理之语法分析与语义分析
编译原理之语法分析与语义分析
语法分析(英语:syntactic analysis,也叫 parsing)是根据某种给定的对由单词序列(如英语单词序列)构成的输⼊⽂本进⾏分析并确定其语法结构的⼀种过程。
语法分析器使⽤由词法分析器⽣成的各个词法单元的第⼀个分量来创建树形的中间表⽰。
语义分析是审查源程序有⽆语义错误,为代码⽣成阶段收集类型信息。
语义分析器(semantic analyzer)使⽤语法树和符号表中的信息来检查源程序是否和语⾔定义的语义⼀致。
它同时也收集类型信息,并把这些信息存放在语法树或符号表中,以便在随后的中间代码⽣成过程中使⽤。
编译原理一些习题答案
第2章形式语言基础2.2 设有文法G[N]: N -> D | NDD -> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9(1)G[N]定义的语言是什么?(2)给出句子0123和268的最左推导和最右推导。
解答:(1)L(G[N])={(0|1|2|3|4|5|6|7|8|9)+} 或L(G[N])={α| α为可带前导0的正整数}(2)0123的最左推导:N ⇒ ND ⇒ NDD ⇒ NDDD ⇒ DDDD ⇒ 0DDD ⇒ 01DD ⇒ 012D ⇒ 0123 0123的最右推导:N ⇒ ND ⇒ N3 ⇒ ND3 ⇒ N23 ⇒ ND23 ⇒ N123 ⇒ D123 ⇒ 0123268的最左推导:N ⇒ ND ⇒ NDD ⇒ DDD ⇒ 2DDD ⇒ 26D ⇒ 268268的最右推导:N ⇒ ND ⇒ N8 ⇒ ND8 ⇒ N68 ⇒ D68 ⇒ 2682.4 写一个文法,使其语言是奇数的集合,且每个奇数不以0开头。
解答:首先分析题意,本题是希望构造一个文法,由它产生的句子是奇数,并且不以0开头,也就是说它的每个句子都是以1、3、5、7、9中的某个数结尾。
如果数字只有一位,则1、3、5、7、9就满足要求,如果有多位,则要求第1位不能是0,而中间有多少位,每位是什么数字(必须是数字)则没什么要求,因此,我们可以把这个文法分3部分来完成。
分别用3个非终结符来产生句子的第1位、中间部分和最后一位。
引入几个非终结符,其中,一个用作产生句子的开头,可以是1-9之间的数,不包括0,一个用来产生句子的结尾,为奇数,另一个则用来产生以非0整数开头后面跟任意多个数字的数字串,进行分解之后,这个文法就很好写了。
N -> 1 | 3 | 5 | 7 | 9 | BNB -> 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | B02.7 下面文法生成的语言是什么?G1:S->ABA->aA| εB->bc|bBc G2:S->aA|a A->aS解答:B ⇒ bcB ⇒ bBc⇒ bbccB ⇒ bBc⇒ bbBcc ⇒ bbbccc……A ⇒εA ⇒ aA ⇒ aA ⇒ aA ⇒ aaA ⇒ aa……∴S ⇒ AB ⇒ a m b n c n , 其中m≥0,n≥1即L(G1)={ a m b n c n | m≥0,n≥1} S ⇒ aS ⇒ aA ⇒ aaS ⇒ aaaS ⇒ aA ⇒ aaS ⇒ aaaA ⇒aaaaS ⇒ aaaaa ……∴S ⇒ a2n+1 , 其中n≥0即L(G2)={ a2n+1 | n≥0}2.11 已知文法G[S]: S->(AS)|(b)A->(SaA)|(a)请找出符号串(a)和(A((SaA)(b)))的短语、简单短语和句柄。
编译原理课件06属性文法和语法制导翻译
属性文法和语法制导翻译是编译原理领域的两个核心概念。本课程将深入探 讨这两个主题,让大家全面了解编译原理的精髓。
属性文法:理论基础
属性文法定义
与上下文无关文法的区别
属性文法定义了语法结构的属性, 包括终结符和非终结符上的属性 和符号间的依赖。
上下文无关文法的语法结构是确 定的,而属性文法的语法结构中 包含了属性的信息。
产生式规则
属性文法的产生式规则由形式化 的产生式和附加的语义规则组成。
语法制导翻译:应用实例
1 基本概念
语法制导翻译将属性值与语法树相结合,用 于将源语言转换为目标语言。
2 方法
语法制导翻译可以通过S属性翻译计算自底向 上地求解,或手动注入Semantic动作。
3 过程
语法制导翻译的过程包括生成属性语法树, 计算语法树的属性,以及将属性与具体操作 相结合。
4 应用实例
语法制导翻译可用于编译器和解释器中,例 如C语言和Java编译器。
语法制导翻译:方法与实践
1
构建属性语法树
将上下文无关文法转化为属性文法,并构建出属性语法树。下而上或自上而下的语法属性计算。
3
执行动作
根据语法属性的计算结果,执行对应的语义动作。
属性文法和语法制导翻译的应用举例
创造思维
转型准备
编译原理培养了我们的创造思维, 让我们能够从编译器底层的实现 中提升自己的能力。
编译原理培养了我们的技术能力 和团队协作精神,为我们的未来 职业道路打下了基础。
编译器
编译器使用语法制导翻译将高级语言转换为机 器代码。
代码生成
属性文法可以用于指令选择与寄存器分配,优 化生成的目标代码。
编译原理 第5章语法制导的翻译
属性和文法符号相关联 规则和产生式相关联
根据需要,将文法符号和某些属性相关联, 并通过语义规则来描述如何计算属性的值
E→E1+T E.code=E1.code || T.code || ‘+’ code表示了我们关心的表达式的逆波兰表示,规则说明 加法表达式的逆波兰表示由两个分量的逆波兰表示并置, 然后加上‘+’得到。
digitlexval=3
18
适用于自顶向下分析的SDD
前面的表达式文法存在直接左递归,因 此无法直接用自顶向下方法处理。 消除左递归之后,无法直接使用属性val 进行处理:
比如规则:T→FT’ T’→*FT’ T对应的项中,第一个因子对应于F, 而运算符在T’中。
19
相同表达式的不同文法的比较
38
例5.15 分析栈实现的例子
假设语法分析栈存放在一个被称为stack 的记录数组中,下标top指向栈顶;
stack[top]指向这个栈的栈顶;stack[top-1] 指向栈顶下一个位置; 如果不同的文法符号有不同的属性集合,我 们可以使用union来保存这些属性值。(归 约时,我们知道栈顶向下的各个符号分别是 什么)
语义翻译的流程
输 入 符 号 串 分 析 树 依 赖 图
语
义
规
则
的 计
实际上,编译中语义翻译的实现并不是 按图中的流程处理的;而是随语法分析 的进展,识别出一个语法结构,就对它 的语义进行分析和翻译。
算
9
5.1 语法制导定义
4.什么是语法制导定义(SDD) 上下文无关文法和属性/规则的结合;
第五章——属性文法
T1:= - c T2:=b * T1 T5:=T2+T2 a:=T5
(b)DAG的三地址代码
图示法
三地址代码特点:
1.三地址代码的语句类似于汇编语言代码。 2.语句可以带有符号标号,并且存在各种控 制流语句。 3.三地址代码可以存放在一个数组中。
三地址代码语句的具体实现: (记录)
第五章 语法制导翻译技术 中间代码生成
属性文法:Attributed
Grammar
描述语义的工具 语法制导翻译: Syntax-Directed Translation
几种中间代码表现形式
5.2 属性文法
接近形式化的语义描述方法
属性文法(A符号配 备若干相关的“属性”,对每个产生式都配备 一组属性的计算规则(语义规则Semantic Rules)。
A都有一组语义规则(Semantic Rules),每 条语义规则的形式为:
• b:=f(c1,c2,…,ck)
其中,f是一个函数,属性b与ci之间,或者
• (1)b是A的一个综合属性且c1,c2,…,ck是产生式右 边文法符号的属性;或者 • (2)b是产生式右边某文法符号的继承属性且 c1,c2,…,ck是A或产生式右边任何符号的属性。
简单算术表达式和赋值语句的翻译
(1) Aid := E { P:=lookup () ; if Pnil then emit( P“:=”E.place) else error } (2) EE1+E2 {E.place:= newtemp; emit(E.place“:=” E1.place“+”E2.place)}
E→T
T → T1 * F T→F
《编译原理》教学大纲
《编译原理》教学大纲大纲说明课程代码: 3225003总学时: 64 学时(讲课 48 学时,实验16 学时)总学分: 4课程类别:学科基础课适用专业 : 计算机科学与技术(专业)预修要求: C 语言程序设计、 C++ 程序设计、数据结构课程的性质、任务及地位:《编译原理》是计算机科学与技术专业的一门重要基础课。
通过对该课程的学习,使学生掌握编译过程中的相关原理和编译技术,让学生能初步进行编译程序的开发和维护,同时促进提高学生开发软件的能力。
教学目的与基本要求:本课程的目的,通过向学生讲述编译系统的结构、工作流程及编译程序各部分的设计原理和实现技术,使学生既掌握编译技术理论的基础与基本知识,也具有设计、实现、分析和维护编译程序等方面的初步能力。
本课程理论性较强。
因授课对象为工科学生,所以在强调编译系统的构造原理和实现方法的同时,为培养学生的实际工作能力,通过上机实践进一步加深学生对课堂教学内容的理解。
目的是要使学生牢固掌握相关的基本理论和基本方法,并能初步利用上述理论和方法解决简单实际问题。
教学方法和教学手段的建议:在教学方法上,贯彻理论联系实际、“精讲、多练”的原则,进行案例式、启发式的教学,对于一些实际性较强的问题要多采用课堂讨论等方式,以提高学生的思辨能力和学习的主动性;引导学生读书、理解、体悟、运用相结合;提高学生的学习兴趣与热情,培养与发挥学生的提出、分析及解决问题的能力。
教学手段:运用多媒体教学手段 +黑板 +上机实验的手段。
采取课堂讲授、课堂讨论、课后练习与自学等形式。
大纲的使用说明:大纲对课程性质、目的等作简单说明,同时列出各章节要学习的知识点、重点、难点,便于教学时教授重点的安排和学生自学安排。
大纲正文第一章引论学时: 4 学时(讲课 4 学时,实验 0 学时)了解编译的概念;理解编译程序的各组成部分及功能。
本章讲授要点:介绍程序设计语言与编译程序间的关系,主要内容包括:各级程序设计语言的定义、源程序的执行、编译程序的构造、编译程序的分类、形式语言理论与编译实现技术的联系。
编译原理语义分析
machunyan
西北工业大学软件与微电子学院
18
5.1 属性和属性文法-合成属性
如果给定一个产生式A→X1X2...Xn,相关属性 等式满足:A.a=f(X1.a1,…,X1.ak,..., Xn .a1,…,Xn.ak),则属性a是合成(综合)的, 例如:无符号数文法的val(十进制值)属性 从语法分析树角度看,如果一个节点(文法 符号)的某一属性值由其子节点的属性值来 计算,则称该属性为合成属性。
22
5.1 属性和属性文法-合成属性
文法规则 exp1→exp2+term exp1→exp2-term exp→term 语义规则 exp1.val=exp2.val+ term.val exp1.val= exp2.val-term.val exp.val=term.val
machunyan
西北工业大学软件与微电子学院
课程内容 第1章 概论 第2章 词法分析 第3章上下文无关文法 第4章语法分析 第5章语义分析 第6章运行时环境 第7章代码生成
2016/7/10
西北工业大学软件与微电子学院 machunyan
1
第5章 语义分析
程序设计语言的语义分为静态语义和动态语 义两种。 静态语义是指在编译阶段能够检查的语义; 动态语义是指在目标程序运行阶段能够检 查的语义。
machunyan 西北工业大学软件与微电子学院 26
5.1 属性和属性文法-合成属性
后序遍历语法树计算val属性的伪代码: 树节点的属性值由该节点所用产生式的语 义规则来定义(计算)。 后序遍历语法树.doc
machunyan
西北工业大学软件与微电子学院
27
编译原理-属性文法和语法制导翻译
编译原理-属性⽂法和语法制导翻译1.属性⽂法:在上下⽂⽆关⽂法的基础上,为每个⽂法符号引进⼀组属性,且让该⽂法中的重写规则附加上语义规则时,称该上下⽂⽆关⽂法为属性⽂法。
(属性⽂法往往以语法制导定义和翻译模式两种形式出现。
具体说明问度娘)注意:(1)属性与变量⼀样,可以进⾏计算和传递。
(2)属性加⼯的过程即是语义处理的过程。
(3)属性分为综合属性(⽤于“⾃下⽽上”传递信息)和继承属性(⽤于“⾃上⽽下”传递信息)。
(1. 语义规则的形式:产⽣式A—>α的语义规则的形式为b:=f(c1,c2,…,ck)。
就是属性b依赖于属性c1,c2,…,ck。
其中:f是⼀个函数;b—A的综合属性,且c1,c2,…,ck是α中⽂法符号的属性;b—α中某个⽂法符号的继承属性, 且c1,c2,…,ck是A或α中任何⽂法符号的属性.(2.VT—VN的属性(1) VT — 只有综合属性,由词法分析器提供.(2) VN — 既可有综合属性也可有继承属性; 开始符号S的所有继承属性作为属性计算前的初始值.(3.属性的计算/获得(1)由该产⽣式提供的计算规则计算获得:产⽣式右边的继承属性,产⽣式左边的综合属性。
(2)由其它产⽣式的属性规则计算或由属性计算器的参数提供:产⽣式左边的继承属性,产⽣式右边的综合属性2.综合属性:通常使⽤⾃底向上的⽅法(由⼦确⽗),S—属性⽂法:仅使⽤综合属性的属性⽂法.3.继承属性:⽤继承属性来表⽰程序设计语⾔结构中的上下⽂依赖关系很⽅便.(由⽗兄却该结点继承属性)4.基于属性⽂法的处理⽅法:(1.依赖图:继承属性和综合属性之间的相互依赖关系的有向图。
构造过程:为每个包含过程调⽤的语义引⼊⼀个虚综合属性b,改写为b=f(c1,c2,…,ck)的形式-->为每个属性设置⼀个结点--->若属性b依赖于属性c,则从属性c的结点有⼀条有向边连到属性b的结点。
(2. 属性的计算次序:(1)良定义的:若⼀个属性⽂法不存在属性之间的循环依赖关系,则称该⽂法为良定义的。
《编译原理课程教案》第5章:中间代码生成
例: 综合属性的计算
Eval:=19 +
L
n
Tval:=4
Eval:=15
Tval:=15
Tval:=3 Fval:=3 *
Fval:=4 Fval:=5
digitlexval:=4
0.L→En 1.E→E1+T 2.E→T 3.T→T1*F 4.T→F 5.F→(E) 6.F→digit 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
练习
• 求 -B+C*D 的逆波兰表示形式、三元式和 四元式
逆波兰:B – C D * + 三元式: (1) (-,B,) (2) (*,C,D) (3) (+,(1),(2)) 四元式: (1) (-,B, , t1) (2) (*,C,D,t2) (3) (+,t1,t2,t3)
到目前为止,已知 输入的语法单位, 又知道 要翻译的结果的形式, 翻译的方法是什么?
5+4# +4# +4#
#T*F #T# #E
F i
0. T L→En T*F
i s5
8+ 9
s6 r2 10 r4
s5 s5 s5
11
acc r2 #E+ r2 r4 r4 r6 r6
GOTO -15 E T F 1 -15 2 3
-158
#E+4 #E+F
r1 #E r3 r5
-15-2 -15-4 -19
构造语法树; 根据需要遍历语法树; 在语法树的各结点处按语义规则进行计算。
4.2 属性文法
2016/6/23 3
文 法 符 号 的 属 性 可 分 为 继 承 属 性 (Inherited Attribute) 与综合属性 (Synthesized Attribute) 两 类。
继承属性用于“自上而下”传递信息。继承属性由 相应语法树中结点的 父结点及兄弟结点属性计算 得到,即沿语法树向下传递,由根结点到分枝 ( 子 ) 结点,它反映了对上下文依赖的特性。继承属性可 以很方便地用来表示程序语言上下文的结构关系。 综合属性用于“自下而上”传递信息。综合属性由 相应语法分析树中结点的分枝结点 (即子结点)属性 计算得到,其传递方向与继承属性相反,即沿语法 分析树向上传递,从分枝结点到根结点。
2016/6/23 10
说 明: 1) addtype:把每个id的类型信息(由L.in继 承)记录在符号表的相关项id.entry中; 2) 非终结符T有一个综合属性type,其值为 int或float。语义规则L.in=T.type表示L.in的 属性值由相应说明语句指定的类型T.type 决定; 3) 属性L.in被确定后将随语法树的逐步生 成而传递到下边的有关结点使用,这种结 点属性称为继承属性。 4) 标识符的类型可以通过继承属性的复写 规则来传递。
2016/6/23 7
说 明:
1) 每一个非终结符都有一个属性val来表示整型 值,如 E.val表示E的整型值,而i.lexval则表示i 的整型内部值。 2) 与产生式关联的每一个语义规则的左部符号 E、 T、 F 等的属性值的计算由其各自相应的右 部符号决定,这种属性也称为综合属性。 3) 与产生式 S→E 关联的语义规则是一个函数 print(E.val),其功能是打印E产生式的值。 4) S在语义规则中没有出现,可以理解为其属 性是一个虚属性。
编译原理-第5章-语义分析
类型分析
作用:把类型表示转换成类型的内部表示
分析过程:读Token序列,识别出各种类型, 返回类型内部表示的地址
array [ 1 .. 10 ] of integer
arrKind … low=1 tp1=intPtr … up=10 tp2=intPtr IndexPtr= (1,subTy, intPtr , 1 ,10) … … ElemPtr=intPtr size=(up-low+1) * sizeof (int)
NameType
形式:id (类型标识符) 处理思想:
查符号表 无声明错 typekind ? TypePtr 为Ptr的值 Forward:=0
EnumType
形式:(a0,… ,an) 处理思想:
生成a0,……an的符号表EntryList: (ai,Ptr,consKind,i),Ptr需回填
int x; …… x(a,b);
语义分析概述
任务
进行语义检查和构造标识符的符号表
语义检查包括类型检查和一般的语义检查
类型检查:运算分量的类型是否相容、赋值语句 左右部的类型是否相容、形参和实参的类型是否 相容、函数说明中函数类型和返回值的类型是否 相容等;
一般的语义检查:V[E]、V.id、V↑、y+f(a,b)、 使用性标识符有否声明、定义性标识符有否重复 声明、标号有否重复声明和重复定位错误等;
生成内部表示: Ptr:=★(enumSize,enumTy,EntryList)
回填EntryList中的Ptr值 Forward:=0
SubRangeType
形式:c1..c2 处理思想:
从C1 求出其内部类型地址Ptr1和值N1; 从C2 求出其内部类型地址Ptr2和值N2; 检查Ptr1=Ptr2,N1 N2; Ptr:=★(subSize,subTy,Ptr1,N1,N2) Forward := 0
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
• 属性文法的基本思想
目是将语言结构的语义以属性(attribute)的形式赋予代表此结构 的文法符号,而属性的计算以语义规则(semantic rules)的形 式赋予由文法符号组成的产生式。在进行语法分析推导或归约的 同时通过语义规则实现对属性的计算,以达到对语义的处理。
5.2.1 名字的作用域
程序设计语言范围的划分可以有两种不同的方式,并列 的和嵌套的。例如,Pascal语言的过程定义可以是嵌套的,即 一个过程内部可以再定义另一个过程;而C/C++语言的过程 只能是并列的,即过程中不能再定义过程。但是C/C++允许 程序块(block)嵌套,每个程序块的范围以{ }界定, { }内 可以再嵌套{ } 。
例:下述源程序说明了C的程序块符合上述作用域规则。
main( )
{ int a=0; int b=0;
/* 最外层,不妨定为B0层 */
{ int b=1;
/* B1层,被B0嵌套 */
{ int a=2; int c=4; int d=5; /* B2层,被B1嵌套 */ printf("%d %d\n",a,b);
当从某个作用域退出时,从栈顶把该作用域的所有名字全 部摘走,存放在一个不活动的临时表中,以备后用。例如, 当分析从B2退出并进入B3时,则把栈顶条目a=2摘走,而将 条目b=3加入。这种临时摘走的方式也称为临时删除或假删除 ,只有确认某名字永远不会再被使用,才被真正删除。
设符号表中有n个条目,那么成功查找的平均时间复杂度是 n/2,不成功查找的时间复杂度是n+1。因此,在符号表中插 入n个名字和完成e次查找的时间复杂度应该是n(n+e)。当n和e 很大时,在线性表上进行查找的效率显然很低。
S1
S2
S3
S4
在线性表中,相同作用域中的名字,会相对集中地存放 在线性表的某一段中,进入或退出某作用域时,此作用域中 的所有名字会一同摘走。但是在散列表中,相同作用域的名 字会被散列在不同的子表中,无法一同摘走。为了便于这样 情况的删除,需要为每个元素在原来散列链(hash link)的 基础上,再设立一个作用域链(scope link)。
作业:下列文法由开始符号S产生一个二进制数,令属性val给出该数的值: S→L.L|L L → LB | B B→0|1
试设计求S.val的属性文法。其中,已知B的属性c,c给出由B产生的二进位 的值。例如101.101, S.val = 5.625,其中第一个二进位的值是4,最后一个 二进位的值是0.125。
名字
属性
a=0
int, B0
b=0
int, B0
b=1
int, B1
c=4
int, B2
d=5
int, B2
a=2
int, B2
对于任何一个名字,从栈顶开始,向栈底查找,遇到的 第一个符合条件的名字,即是所要查找的符号。当要插入一 个名字的时候,也是首先在符号表中查找,若查到,则返回 该名字在符号表中的位置(指针或下标),否则加入到栈顶。 在 上 表 中 , 如 果 当 前 分 析 到 的 作 用 域 是 B2 , 则 栈 顶 条 目 是 a=2,因此,在符号表中查找,遇到的第一个a和b分别是a=2 和b=1,正好符合作用域规则。
hash link:
链接所有具有相同hash值的元素,表头在表头数组中。 scope link: 链接所有在同一作用域中的元素,表头在作用域链中。
为此需要为每个名字添加一个指示作用域的属性,如下 图(a)所示,有一个属性存放当前作用域是在B0、B1、B2 还是B3中。
0 1 2 3 25 ...
则前面C源程序的散列表
1
b=3 B3
b=1 B1
b=0 B0 结构如图所示。
B3^
B1^
B0^
... 25
(b) 当前分析B3的散列表
(a)处在B2作用域中,而(b)处在B3作用域中,当分析从B2退出进入B3时, (c)所示的作用域表中B2节点的scope link B2^ 串起B2中声明的所有名字。
散列表的结构如图所示,m个子 表的表头构成一个表头数组,它以 i 散 列 函 数 的 值 ( hash 值 ) 为 下 标 , 具有相同hash值的节点被散列在相 k
同子表中,连接子表的链被称为散
列链。如果散列均匀,则时间复杂 m-1 度会降到原线性表的1/m。
其中:hash(S1)=hash(S2)=i hash(S3)=hash(S4)=k
散列表上的操作
对于散列表中的操作,可以如下进行:
9 查找:计算散列函数,然后从散列函数所指示的入口进 入某个线性表,在线性表中沿hash link查找。 9 插入:首先查找,以确定要插入的名字是否已在表中。 若不在,则要分别沿hash link和scope link插入到两个链中 ,方法都是插在表头。 9 删除:因为只有在退出作用域时才删除,因此把以作用 域链连在一起的所有元素从当前符号表中删除,但如果是 临时删除,则保留此作用域链,以便下次使用时直接沿作 用域链加入到散列链中即可。
(1)静态作用域原则(static-scope rule): 编译时就可以确定名字的作用域。
(2)最近嵌套原则(most closely nested):
① 程序块B中声明的各名字的作用域包括B; ② 如果B中引用的名字x不在B中声明,那么x可能在B 的某几个外围程序块B’1、B’2…中声明。如果某个含x 声明的程序块B’i比其它任何含x声明的程序块更接近被 嵌套的B,则B 中的x是那个在B’i中声明的x。
}
{ int b=3;
/* B3层,与B2并列,并列的名字作用域不交 */
printf("%d %d\n",a,b); }
声明
作用域
printf("%d %d\n",a,b); }
int a=0 int b=0
B0 – B2 B0 – B1
printf("%d %d\n",a,b); }
int b=1 int a=2
第五章 属性文法与语义分析
• 程序设计语言的语义 静态语义是指在编译阶段能检查的语义。它是 对程序约束的描述,可以分为类型规则和作用 域/可见性规则两大类。 动态语义是只有在目标码的运行阶段才能检查 的语义。
• 编译程序的语义处理工作: 静态语义检查 /生成某种中间代码 /解释执行
动态语义
• 语义处理方法
名字起作用的范围被称为名字的作用域。定义在并列的
两个范围内的名字其作用域互不相干,但是定义在嵌套的两 个范围内的名字,其作用域的问题就需要制定规则来限定, 以使任何一个名字在任何范围内含义都是无二义的。规定一 个名字在什么样的范围内应该表示什么意义的原则,被称为 名字的作用域规则。
通用的程序设计语言,如Pascal、C/C++、Ada等均遵守 下述两条原则:
词/语法分析器生成器LEX和YACC为使用者 提供用于描述属性的伪变量和语义栈,以支持语 法制导翻译,但是语义规则的书写,仍属于普通 程序设计的范畴。
5.1 属性文法是一个三元组:
A=(G, V, F) 其中
G: 是一个上下文无关文法 V: 有穷的属性集, 每个属性与文法的一个终结符或非终 结符相连,这些属性代表与文法符号相关的语义信息,如 它的类型、值、代码序列、符号表内容等等. 属性与变量 一样,可以进行计算和传递。属性加工的过程即是语义 处理的过程。 F: 关于属性的属性断言或一组属性的计算规则(称为语 义规则) . 如产生式A → α有一组形式为 b := f (c1, c2, …, ck )的语义规则,其中f 是函数,b和 c1, c2, …, ck 是该产生式文法符号的属性。
a=2 B2
a=0 B0
b=1 B1 c=3 B2
b=0 B0
B1^
B0^
d=4 B2 B2^
(a) 当前分析B2时的散列表
B0 B0^
#
B1 B1^ B2 B2^ #
# B3 B3^ #
d=4 B2
c=3 B2
a=2 B2
(c) 作用域表的内容
假设散列函数的计算公式
0
a=0 B0
为hash(s)=ord(s)-ord(‘a’),
B1 – B3表的实现
表处理技术请参考数据结构中的顺序查表法、折半查表法 及散列查表法。
(1)线性表 最简单和最容易实现符号表的数据结构是线性表。可以将 线性表表示为一个数组,也可以表示为一个单链表。为了正 确反映名字的作用域,线性表应具有栈的性质,即符号的加 入和删除,均在线性表的一端进行。前面的例子对应符号表 的线性表组织如下,可以将其看作是一个顶在下的栈。
(1) 属性文法仅考虑“做什么”:用抽象的属性表示文法符号所代表的语 义,如.post为表达式的后缀式表示;用抽象的算符表示语义的计算,如 用‘||’表示两个子表达式后缀式的连接运算。属性和运算的具体实现细 节,不在属性文法的考虑范围。
(2) 语法制导翻译方案不但需要考虑“做什么”还需考虑“如何做”:例中 翻译方案设计了一个数组post来存放表达式的后缀式。另外,在实现中 还要考虑计数器k的初值等相关问题。
例:简单台式计算器的属性文法
产生式
L→En E → E1 + T E→T T → T1 * F T→F F→ (E) F → digit
语义规则
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