编译原理与技术讲义-第6章
编译原理第6章

2 执行派生类构造函数的顺序是:
调用基类构造函数,对基类数据成员初始化; ① 调用基类构造函数,对基类数据成员初始化; 调用子对象构造函数,对子对象数据成员初始化; ② 调用子对象构造函数,对子对象数据成员初始化; 再执行派生类构造函数本身, ③ 再执行派生类构造函数本身,对派生类数据成员初始化
6.5 同名覆盖和赋值兼容规则
(2)改造从基类吸收的成员。接收基类成员是程序人员不 改造从基类吸收的成员。
能选择的, 能选择的,但是程序人员可以对这些成员作某些调整改 造。 (3) 在声明派生类时增加的成员。这部分内容是很重要的, 的成员。这部分内容是很重要的, 它体现了派生类对基类功能的扩展。 它体现了派生类对基类功能的扩展。要根据需要仔细考 虑应当增加哪些成员,精心设计。 虑应当增加哪些成员,精心设计。
1、同名覆盖
可以在派生类中声明与基类同名的成员,这样, 可以在派生类中声明与基类同名的成员,这样,在派生类中就存在两个 同名的成员,通过及类对象只能使用新增的同名成员, 同名的成员,通过及类对象只能使用新增的同名成员,这就是同名覆盖 原则。 原则。
在派生类中增加一个与基类函数同名的display()函数: ()函数: 在派生类中增加一个与基类函数同名的 ()函数 void Student::diplay() {cout << "num:"<< num <<endl; cout <<"score:"<< score <<endl;} 在主函数中调用: 在主函数中调用: std.diplay(); 实际执行的是派生类Student中的新增的 中的新增的display()函数。 ()函数 实际执行的是派生类 中的新增的 ()函数。 如果想调用基类的display函数,需用基类类名限定: 函数, 如果想调用基类的 函数 需用基类类名限定: std.Person::display();
编译原理第6章(刘磊 机械工业出版社)

TypePtr Kind
Level Parm Class
例有声明如下:
CONST pai= 3.14 ; TYPE vector=ARRAY[1..10] OF integer; VAR x, y : real ; r, s : vector ; 设当前层数和可用offset值分别为L和0, 构造标识符 pai, vector, x, y, r 和s 的属性表示。
6.4 值的内部表示
非结构类型值的内部表示:
整型:有直接对应的机器表示。 实型:有直接对应的机器表示。 指针:无符号整型数。 有序类型:整数形式
有序类型的量表示:
整型常量:ord(N) = N 布尔常量:ord(false)=0, ord(true) = 1 字符常量:ord(C) = ASCⅡ (C) 枚举常量:设有枚举类型(D,A,B),则有 ord(D)=0,ord(A)=1,ord(B)=2 子界常量:设有子界类型C1..C2,则值空间 为[ord(C1)...ord(C2)]
TokenList
语义定义 自然语言描述规定
判定
三种内部表示
标识符的内部表示 类型的内部表示 值的内部表示
6.2
标识符种类:
标识符的内部表示
常量名、类型名、变量名、函数名、过程名、域名。 TYPE idkind=( consKind, typeKind, varKind, fieldKind, procKind,funcKind )
标准类型: Size sub: enum: array:
Size Size Size Kind HostType Elems Low Up Leng
Kind Kind Kind
编译原理讲义

编译原理讲义1)把⽤汇编语⾔或⾼级语⾔写成的程序转换成机器语⾔的程序,被称为翻译程序。
汇编语⾔的翻译程序称为汇编程序把⾼级语⾔的翻译程序称为编译程序。
可以采⽤边翻译边执⾏的解释执⾏⽅式,这种处理程序称为解释程序。
解释程序的结果是源程序的执⾏结果。
2)编译有哪些部分组成?每个部分的作⽤?词法分析:输⼊源程序,对构成源程序的字符串进⾏扫描和分析,识别出⼀个个的单词(符号)如关键字,标识符,常数,算符,界符。
语法分析:在词法分析的基础上,根据语⾔的语法规则,把单词符号分解成各类语法单位(如短语、句⼦等),并构造⼀棵能够正确反映该结构的语法树。
作⽤:通过语法分析确定整个输⼊是否构成语法上正确的“程序”。
注意:词法分析是种线性分析,⽽语法分析是⼀种层次分析。
中间代码⽣成:任务:语义分析的基础上按语⾔的语义规则进⾏初步的翻译(产⽣中间代码)中间代码:是⼀种含义明确、便于处理的记号系统,它通常独⽴具体的硬件;表⽰形式:四元式、三元式、间接三元式等中间代码优化:任务:对前阶段产⽣的中间代码进⾏加⼯变换,以期在最后阶段能产⽣出更为⾼效的⽬标代码。
⽬标代码⽣成:任务:把中间代码变换成特定机器上的低级语⾔代码(⽬标代码)⽬标代码形式:绝对指令代码、可重定位指令代码、汇编指令代码表格管理:错误处理:3)编译前后端的划分?前端:此法分析、语法分析、中间代码⽣成、中间代码优化。
后端:⽬标代码⽣成及和硬件有关的⼯作。
4)符号和符号串的概念1、字母表:它是⾮空有穷集。
例如:∑={a,b,c}或∑={1,2,3}2、符号:字母表中的元素称为符号。
3、符号串:符号的有穷序列,符号串也称为字。
⽤ε来表⽰空符号串。
例如:a,ab,abc,dsfsd4、长度:符号串的长度是指该串所包含的符号个数。
⽤|x|表⽰符号串x的长度。
例如:|a|=1,|abn|=35、连结:设x和y为符号串,则称xy 为他们的连结。
例如:x=aa,y=bb,则XY=aabb6、空集:不含任何元素的集合,记为Φ。
清华大学编译原理课件Chapter6

6.3 算符优先分析法
• 简单优先技术对符号表中的所有符号之间 建立优先关系。但是,有些情况下,不需 要对所有两个符号之间建立优先关系。 • 算符优先分析技术只在终结符号之间建立 优先关系。
33
算符优先分析法的基本思想
• 这种方法是效仿算术式的四则运算而建立 起来的。对于算术表达式,只需要按照运算符 之间的优先关系,就可以确定运算的顺序。不 需要考虑操作数就可以对表达式进行分析。 • 例如:E+T*F,只需要知道*的优先级高于 +,就可以知道T*F是句柄。 • 刚开始是对表达式文法进行分析,但是目 前已不限于此。在一般的文法中,终结符号的 地位相当于运算符号。 34
第6章 自底向上优先分析法
1
6.1 概 述
• 从推导的角度,从输入符号出发,试图 把它规约成识别符号。每一步都寻找特 定的某个类型的短语(一般是简单短语) 进行归约。在分析过程中,每次归约的 都是最左边的简单短语(或其它短语)。 • 从语法树的角度,以输入符号为树的叶 子结点,试图向根结点方向往上构造语 法树。
定理6.4的证明(续)
• 如果t=j-1,那么, 由句柄1,Sj-1 ◄ Sj;
由句柄2, Sj-1 = Sj 或者Sj-1 ► Sj;矛盾!
• 如果t=i+1,由句柄1,Si ► Si+1;
由句柄2,Si ◄ Si+1 或者 Si = Si+1。
• 如果i<= t <= j;那么
– Sj在句柄中:
– Si在句柄内部,但是Si+1在句柄之后,必然 有规则U→…Si,且存在规范句型…USi+1…。 – 如果Si+1在句柄内,而Si在句柄外,那么必 然存在规范句型…SiU…,且 有U→Si+1…。
编译原理 6章

尽管上面这些映射函数都不包含一个以上的对偶,但这个PDA 仍是非确定的。其中,前五个转换函数用于把输入符号移进栈 。接下来的六个用于完成归约工作,该PDA恰好识别L(G).
1 2 3 4 5 6
考虑输入串a*a+a,只 有下面的移动序列 才能够到达终止状 态: (q,$,a*a+a)├ (q,$a,*a+a)├ (q,$F,*a+a)├ (q,$T,*a+a)├ (q,$T*,a+a)├ (q,$T*a,+a)├
例6.5 考虑算术表 达式文法G3[E]: E→E+T E→T T→TF T→F F→(E) F→a
该文法的PDA映射函数δ为 δ(q,ε,a)={(q,a)} 根据规则6(①) δ(q,ε,+)={(q,+)} δ(q,ε,*)={(q,*)} δ(q,ε,‘(’)={(q,‘(’)} δ(q,ε,‘)’)={(q,‘)’)} δ(q,E+T,ε)={(q,E)} 根据规则6(②) δ(q, T,ε)={(q,E)} δ(q,T*F,ε)={(q,T)} δ(q,F,ε)={(q,T)} δ(q,(E),ε)={(q,F)} δ(q,a,ε)={(q,F)} δ(q,$E,ε)={(r,ε)} 根据规则6(③)
7 (q,$T*F,+a)├ 8 (q,$T,+a)├ 9 (q,$E,+a)├ 10 (q,$E+,a)├ 11 (q,$E+a,ε)├ 12 (q,$E+F,ε)├ 13 (q,$E+T,ε)├ 14 (q,$E,ε)├ 15 (r,ε,ε)├
E→E+T E→T T→TF T→F F→(E) F→a
关系积记为r1r2xr1r2y当且仅当存在w使得xr1w与wr2y传递闭包关系r的传递闭包记为rxyxry当且仅当存在n0使得xrny自反传递闭包关系r的传递闭包记为rxyxry当且仅当存在n0使得xrny其中r0为恒等布尔矩阵和关系?关系可用集合定义也可用布尔矩阵表示xry当且仅当mxy1?定理61mrtmrt?定理62mr1r2mr1mr2?定理63mr1r2mr1mr2?定理64mrmr传递闭包的warshall算法forj
编译原理 6章

布尔矩阵和关系
• 关系可用集合定义,也可用布尔矩阵表示 xRy 当且仅当M[x,y]=1 • • • • 定理6.1 M(RT)=M(R)T 定理6.2 M(R1+R2)=M(R1)+M(R2) 定理6.3 M(R1R2)=M(R1)M(R2) 定理6.4 M(R+)=M(R)+
传递闭包 的Warshall算法 算法
文法G(E): E→E+T | T T→T*F | F F→(E) | i
+ + * i ( ) > > > < > * < > > < > < < i < < ( < < ) > > > = >f+ Nhomakorabeaf*
fi
f(
f)
g+
g*
gi
g(
g)
+
f 4 f+, g+, f(, g) 3 g+,f(,g)
*
6.7.2 Bell 方法
• Bell方法:有向图构造法。 方法: 方法 有向图构造法。 ① 作两排结点:一排为f L ,另一排为g R; L>R, 从L到R连一有向弧; L<R, 从R到L连一有向弧; L=R, 从L到R和从R到L各连一有向弧; ② 计算各结点能到达的结点数(包括自己) 为该函数点的值。 ③ 按定义6.1的条件判断,若不满足则不存在 优先函数。
与文法有关的一些关系: 与文法有关的一些关系:
⑴ 关系和 x, y∈Σ,R1和R2是Σ上的两个关系,R1与 R2的两个关系和记为R1+R2。 x(R1+R2)y 当且仅当 xR1y或xR2y ⑵ 关系积 R1和R2是Σ上的两个关系,R1与R2的两个 关系积记为R1R2。 xR1R2y 当且仅当 存在w∈Σ,使得xR1w与wR2y ⑶ 传递闭包 关系R的传递闭包记为R+,x, y∈Σ, xR+y 当且仅当存在n>0,使得xRny ⑷ 自反传递闭包 关系R的传递闭包记为R*,x, y∈Σ, xR*y 当且仅当 存在n≥0,使得xRny ,其中R0为恒等
编译原理 第6章课件

第6章LR分析法教学要求:1.掌握:活前缀的概念,2.理解:LR (0 ), SLR (1), LR(1)和LALR(1)分析过程,各类分析表的构造3.了解:二义性文法在LR 分析中的应用目录 6.1 LR 分析概述6.2 LR (0) 分析6.3 SLR(1) 分析6.4 LR (1)分析6.5 LALR(1)分析6.6 二义性文法在LR 分析中的应用强调算符之间的优先关系的唯一性,这使得它的适应面比较窄算法在发现最左素短语的尾时,需要回头寻找对应的头LR(k)分析法可分析LR(k)文法产生的语言– L :从左到右扫描输入符号,– R :最右推导对应的最左归约(反序完成最右推导)– k :向前读入k 个符号,以便确定归约用的产生式LR 分析法正是给出一种能根据当前分析栈中的符号串和向右顺序查看输入串的K 个( K ≥0)符号就可唯一地确定分析器的动作是移进还是归约和用哪个产生式归约,因而也就能唯一地确定句柄。
LR 分析法的归约过程是规范推导的逆过程,所以LR 分析过程是一种规范归约过程。
6.1 LR分析概述L:从左到右扫描输入串R : 最右推导的逆过程分析器模型和分析算法• LR分析特征讨论说明:S[i] 为状态栈, X[i]为文法符号栈。
状态转换表用GOTO[S i ,X]= S j 表示,规定当栈顶状态为S i ,遇到当前文法符号为X 时应转向状态S j ,X 为终结符号或非终结符号。
ACTION[S i ,a]规定了栈顶状态为S i ,遇到输入符号为a 应执行的动作。
动作有如下四种: 移进: S j = GOTO[S i ,a]移入状态栈,a 移入到文法符号栈。
归约: 栈顶形成句柄为β时,文法有产生式 A →β,若 β的长度为r ,则从两个栈顶去掉r 个符号,把A 移入符号栈,S j =GOTO[S i ,A] 移入状态栈。
接受acc 报错LR 分析算法 置ip 指向输入串w 的第一个符号 令S 为栈顶状态 a 是ip 指向的符号 重复 begin if ACTION[S,a]=S j then begin PUSH j,a(进栈)ip 前进(指向下一输入符号) end else if ACTION[S,a]=r j (第j 条产生式为A →β)then beginpop |β| 项令当前栈顶状态为S’push GOTO[S’,A]和A(进栈)end else if ACTION[s,a]=accthen return (成功)else errorend.重复LR 文法:对于一个上下文无关文法(Context Free Grammar)-cfg 文法, 如果能 够构造一张 LR 分析表, 使得它的每一个入口均是唯一的(Sj,rj,acc,空白), 则称该 cfg 是LR 文法.LR分析:特征:规范的符号栈中的符号是规范句型的前缀,且不含句柄以后的任何符号(活前缀)分析决策依据:栈顶状态和现行输入符号.• 四种技术 LR(0) SLR(1) LR(1) LALR(1)6.2 LR(0) 分析LR(0)文法--------能力最弱,理论上最重要:存在FA 识别活前缀识别活前缀的DFA 如何构造(LR(0)项目集规范族的构造)LR(0)分析表的构造一、可归约前缀和子前缀最右推导过程(每条产生式尾部加上编号)S ⇒aAcBe[1] ⇒aAcd[4]e[1] ⇒aAb[3]cd[4]e[1]⇒ab[2]b[3]cd[4]e[1]归约时在栈里的句型的前缀 归约前可在栈里的规范句型(不含句柄) 的前缀 ab[2] aaAb[3] a,aAaAcd[4] a,aA,aAcaAcBe[1] a,aA,aAc,aAcB可归约前 子前缀活前缀(viable prefixes )G=(Vn,Vt,P,S),若有S’ ⇒ αA ω ⇒ αβω,γ是αβ的前缀,则称是文法G 的活 前缀. 其中S’是对原文法扩充(S’→S)增加的非终结符.? 为使S’不出现在任何产生式的右部.活前缀是规范句型(右句型)的前缀,但不超过句柄移进归约分析的栈中出现的内容加上余留输入构成规范句型二、识别活前缀的FA启示:可以把非终结符号和终结符号都看成一个FA 的输入符号,每把一个符号 进栈时看成已识别过了该符号,而状态进行转换,当识别到可归约前缀 时,相当于在栈顶形成了句柄,则认为达到了识别句柄的终态。
编译原理第6章_1

STACK REMAINING INPUT
1
(int + int)#
2(
int + int)#
3 (int
+ int)#
4 (T
+ int)#
5 (E
+ int)#
6 (E +
int)#
7 (E + int
)#
8 (E + T
)#
9 (E
)#
10 (E)
#
11 T
#
12 E
#
13 S
#
PARSER ACTION Shift Shift Reduce: T –> int Reduce: E –> T Shift Shift Reduce: T –> int Reduce: E –> E + T Shift Reduce: T –> (E) Reduce: E –> T Reduce: S –> E
的左部而得到的
文法要求
shift-reduce or reduce-reduce 冲突(conflicts)
分析程序不能决定是shift 还是 reduce 或者分析程序归约时有多个产生式可选
例子 (dangling else) : S –> if E then S | if E then S else S
LR分析算法
then begin pop || 项 令当前栈顶状态为S’ push GOTO[S’, A]和A(进栈)
end else if ACTION[s,a]=acc
then return (成功) else error end
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
9
编译原理与技术
青岛大学信息工程学院
6.2 符号表的主要属性及其作用
符号名 符号种属 符号类型 存储类别 作用域 存储分配信息 其它属性
–
符号名
符号名可以是变量名、函数名(操作名)、类型名、 符号名可以是变量名、函数名(操作名)、类型名、类对象名等 )、类型名 每个符号名通常由若干个(非空)的字符组成的字符串来表达, 每个符号名通常由若干个(非空)的字符组成的字符串来表达, 在语言中它们通常是一个变量、函数或对象的位移标志,因此在 在语言中它们通常是一个变量、函数或对象的位移标志, 符号表中的符号名作为表项的唯一区别一般是不允许重名的。 符号表中的符号名作为表项的唯一区别一般是不允许重名的。 符号名与它在符号表中的位置建立起一一对应的关系, 符号名与它在符号表中的位置建立起一一对应的关系,这使得我 们可以用一个符号在表中的位置来代替该符号名、访问其信息。 们可以用一个符号在表中的位置来代替该符号名、访问其信息。 通常把一个标识符在符号表中的位置值称为该标识符的内部代码。 通常把一个标识符在符号表中的位置值称为该标识符的内部代码。 在经过分析处理的源程序中, 在经过分析处理的源程序中,标识符不再是一个字符串而是一个 表示内部码的整数值,这不但便于识别, 表示内部码的整数值,这不但便于识别,而且也可以压缩存储和 表达的长度。 表达的长度。
编译原理与技术 青岛大学信息工程学院
8
6.2 符号表的主要属性及其作用
–
不同的符号类别包含了不同的属性, 不同的符号类别包含了不同的属性,由于它 们的信息不同, 们的信息不同,也就导致了符号表的组织有 较大的差别。例如, 较大的差别。例如,数量类型的变量名字和 过程名字: 过程名字:
对于一个变量名要记录其类型(如整型、实型、 对于一个变量名要记录其类型(如整型、实型、 布尔型等)、占用的存储字节以及相对与某个基 布尔型等)、占用的存储字节以及相对与某个基 )、 准位置的相对位置; 准位置的相对位置; 对一个过程名要记录的属性包括参数的个数及其 类型,该过程是否有返回值,过程中的变量声明, 类型,该过程是否有返回值,过程中的变量声明, 甚至过程声明(如果像Pascal语言允许嵌套过程 甚至过程声明(如果像 语言允许嵌套过程 声明)等信息。 声明)等信息。
编译原理与技术 青岛大学信息工程学院
5
6.1 符号表的作用
查找符号的属性
–
–
–
符号表存放了源程序中的各种类型的信息,比如数值、 符号表存放了源程序中的各种类型的信息,比如数值、 变量类型、参数传递的地址等, 变量类型、参数传递的地址等,在分析和翻译源程序 的过程中会被不断地查询。 的过程中会被不断地查询。 例如,对于上述的变量声明, 例如,对于上述的变量声明,如果源程序有代码 a + b时,就需要查找、计算表达式中运算数的类型 时 就需要查找、 和值,以便计算出表达式。 和值,以便计算出表达式。 又如,在源程序中如果出现了函数调用factory (6), 又如,在源程序中如果出现了函数调用 , 编译程序就需要查找到factory的声明,找到实参 的 的声明, 编译程序就需要查找到 的声明 找到实参6的 地址并传给形参n,执行函数factory的体,并返回值, 的体, 地址并传给形参 ,执行函数 的体 并返回值, 等。
10
编译原理与技术
青岛大学信息工程学院
6.2 符号表的主要属性名通常用标识符来表示。根据语言的定义, 语言中的符号名通常用标识符来表示。根据语言的定义,程序中 出现的重名标识符定义将按照该标识符在程序中的作用域和可视 规则进行相应的处理。而在程序的运行过程中, 规则进行相应的处理。而在程序的运行过程中,符号表中的符号 名始终是唯一的标志。 名始终是唯一的标志。 在一些允许操作重载、类继承的语言中,函数名、 在一些允许操作重载、类继承的语言中,函数名、操作名允许重 对于重载操作的标识符, 名,对于重载操作的标识符,它们可以通过参数的个数与类型以 及返回值的类型来区别;而对于操作的继承, 及返回值的类型来区别;而对于操作的继承,编译器可以构造继 承图,同时保存类结构, 承图,同时保存类结构,这样就可以为每个操作和属性找到唯一 的定义。 的定义。 例如,对应不同的参数类型,可以定义几个求和重载函数: 例如,对应不同的参数类型,可以定义几个求和重载函数: int sum ( int a, int b) double sum ( double a, double b) float sum(float a, float b, float c) ( ) 当某个函数中调用到重载函数时,编译器根据实参的类型和个数 当某个函数中调用到重载函数时, 去调用相应的函数。 去调用相应的函数。
11
编译原理与技术
青岛大学信息工程学院
6.2 符号表的主要属性及其作用
符号名 符号种属 符号类型 存储类别 作用域 存储分配信息 其它属性
–
符号种属
由于语言中符号所拥有的属性可能不同, 由于语言中符号所拥有的属性可能不同,其组织就可以采用不同 的数据结构,可以用符号的种属来区别每个符号的基本划分。 的数据结构,可以用符号的种属来区别每个符号的基本划分。 根据不同的语言,符号的种属可以包括:简单变量、结构型变量、 根据不同的语言,符号的种属可以包括:简单变量、结构型变量、 数组、过程、类型、类等。 数组、过程、类型、类等。 可以依据符号种属的划分来组织符号表, 可以依据符号种属的划分来组织符号表,一种方式是为每个种属 的标识符建立一张表,这样,可以对符号表类似地安排组织结构、 的标识符建立一张表,这样,可以对符号表类似地安排组织结构、 进行同样的操作; 进行同样的操作;另外一种方式把所有种属的标识符统一安排在 一张表中,根据符号的种属进行条件判断, 一张表中,根据符号的种属进行条件判断,对不同种属的特殊型 执行不同的存储安排和操作。 执行不同的存储安排和操作。
–
4 编译原理与技术 青岛大学信息工程学院
6.1 符号表的作用
–
下面是计算阶乘n!的 语言的函数声明 语言的函数声明: 例6.2 下面是计算阶乘 的C语言的函数声明:
int factory ( int n) { int t; if (n = = 0) | | n = = 1) t = 1; else t = n ∗ factory (n-1); - return t; }
编译原理与技术 青岛大学信息工程学院
7
6.1 符号表的作用
作为目标代码生成阶段地址分配的依据
– –
–
标识符由它定义的存储类型或它在程序中的位置来确定。 标识符由它定义的存储类型或它在程序中的位置来确定。 首先是要确定变量存储的区域。例如, 语言中, 首先是要确定变量存储的区域。例如,在Java语言中,整数的 语言中 类型(以及所占用的字节) 个字节)、 类型(以及所占用的字节)有byte(1个字节)、 ( 个字节)、short(2个字 ( 个字 )、int( 个字节 以及long(8个字节),而float类型占 个 个字节) 个字节), 类型占4个 节)、 (4个字节)以及 ( 个字节),而 类型占 字节, 类型占8个字节 字节,double类型占 个字节。又如,对寄存器变量,编译将尽 类型占 个字节。又如,对寄存器变量, 可能地把它们保留在机器的寄存器当中,以提高运行速度; 可能地把它们保留在机器的寄存器当中,以提高运行速度;而 对在一个文件中定义的外部变量,它们要在不同的源程序文件 对在一个文件中定义的外部变量, 之间访问, 之间访问,需要编译程序把它们放在所有源程序文件都可以方 便寻找到的存储器的位置。 便寻找到的存储器的位置。 其次,要根据标识符出现的顺序, 其次,要根据标识符出现的顺序,决定标识符在某个存储区域 中的具体位置, 中的具体位置,而有关区域的标志及其相对位置都是作为该标 识符的语义信息存放在它的符号表中的。 识符的语义信息存放在它的符号表中的。
编译原理与技术
第6章 章 符号表的组织和管理
青岛大学信息工程学院
主要内容
符号表的作用 符号表的主要属性及其作用 符号表的组织结构 名字的作用范围
2
编译原理与技术
青岛大学信息工程学院
6.1 符号表的作用
登记符号属性值
–
–
–
在源程序的各个分析阶段, 在源程序的各个分析阶段,编译程序根据标 识符的声明信息收集它属性的有关值, 识符的声明信息收集它属性的有关值,并把 它们存放在符合表中。 它们存放在符合表中。 每种语言规则定义了不同的符号属性; 每种语言规则定义了不同的符号属性;即使 是同一个语言, 是同一个语言,不同的编译程序也可能会定 义并且收集不同的属性信息。 义并且收集不同的属性信息。 现代编程语言中一般包括常数声明、 现代编程语言中一般包括常数声明、变量声 类型声明和过程/函数声明等四类声明 函数声明等四类声明。 明、类型声明和过程 函数声明等四类声明。 对于每类声明,编译程序要收集、 对于每类声明,编译程序要收集、存储和应 用的属性完全不同。 用的属性完全不同。
–
对于函数factory要记录的属性包括:函数的名称,各 要记录的属性包括:函数的名称, 对于函数 要记录的属性包括 种变量如参数、返回值、局部变量及其类型, 种变量如参数、返回值、局部变量及其类型,同时还 要记录函数的调用信息,以便在函数体执行完毕以后 要记录函数的调用信息, 返回到调用点,特别是对这种允许递归调用的函数, 返回到调用点,特别是对这种允许递归调用的函数, 要为每次调用保留上面提到的所有信息。 要为每次调用保留上面提到的所有信息。
编译原理与技术 青岛大学信息工程学院
3
6.1 符号表的作用
例6.1 C语言的变量声明 语言的变量声明 short int a; float b = 0.0; – 把标识符 声明为短整数型,把b声明为浮点 把标识符a声明为短整数型 声明为短整数型, 声明为浮点 类型,而且初始化为0。那么, 类型,而且初始化为 。那么,编译程序对每 个变量要记录它的类型, 个变量要记录它的类型,以便执行类型检查 和分配存储,比如短整型变量i占 个字节 个字节; 和分配存储,比如短整型变量 占2个字节;要 记录它在存储器中的位置( 记录它在存储器中的位置(相对位移或绝对 地址),以便目标程序运行时访问;若像b有 ),以便目标程序运行时访问 地址),以便目标程序运行时访问;若像 有 初始值,则还需要记录这个初始值。 初始值,则还需要记录这个初始值。