一、忘了标题。
- 将某一种 程序设计语言 写的 程序 翻译成等价的 另一种语言 的 程序 的程序, 称之为编译程序(compiler) 。
- 遍:对源程序或源程序的中间形式从头到尾扫描一遍,并做有关的分析加工,生成新的源程序的中间形式或生成目标程序。
二、形式语言与自动机基础
BNF : 用来表示语法 eg. <句子> -> <主语><谓语>
字母表(符号集):字母表是元素的非空有穷集合。字母表中的元素
称为符号或字符,因此字母表也称为符号集,用大写字母A或希腊字母∑表示符号串:由字母表中的符号组成的任何有穷序列称为符号串,也称为串或字符串。用小写希腊字母表示符号串,如如 ω =STR
- 前缀: ω 是一个符号串,从 ω 的尾部删去0个或若
干个符号之后剩余的部分称为 ω 的前缀。 (真前缀不是原符号串) - 后缀:从 ω 的首部删去0个或若干个符号之后剩余的部 分称为ω 的后缀。(真后缀不是原符号串)
- 子符号串:从一个符号串中删去它的一个前缀 和一个后缀之 后剩余的部分称为该符号串的子符号串或子串。
- 前缀: ω 是一个符号串,从 ω 的尾部删去0个或若
符号串的连接:设 ω 和 υ是两个符号串,如果将符号串 υ 直接拼接在符号串 ω 之后,则称此操作为符号串 ω 和 υ的连接,记作 ω υ。
eg. ω=abc,υ =xyz则 ω υ=abcxyz
符号串的方幂:设 ω 是某字母表上符号串,把 ω 自身连接 n 次得 到符号串 υ ,即 υ = ω ω … ω (n个 ω ) ,称 υ 是符号 串 ω 的n次幂,记作 υ = ω ^n。
符号串集合的乘积:设A、B 是两个符号串集合,AB表示A与B的乘积,则有定义 AB={ ω υ| ( ω ∈A)∧( υ∈B) }
如:设A={ab,c}, B={d,ef}, 则 AB={abd, abef, cd, cef}
符号串集合的方幂:设A是符号串集合,A自身的乘积可以用方幂表示。A0= { ε } A^1=A A^2=AA A^3= A^2A =AAA
符号串集合的并(并集)
符号串集合的闭包:
- 正闭包:设A为符号串集,A的正闭包记作A+,有 A+= A1∪ A2∪…∪ An∪…
- 自反闭包:A*定义为A的自反闭包,有 A*= A0∪ A+= { ε }∪ A+= A+∪{ ε }
文法:一部文法G是一个四元组 G =( VN, VT, S, P)
- VN:非空有限的非终结符号集(一般用大写字母表示)。其中 的元素称为非终结符,或语法变量,代表了一个语法范畴
- VT:非空有限的终结符号集(一般用小写字母表示)。
- S:文法的开始符号或识别符号,亦称公理,S ∈VN。S代表 语言最终要得到的语法范畴。
- P:有限产生式集。
产生式就是按一定格式书写的定义语法范畴的文法规则,它是一部文法的实体。
语言的非形式化定义:给定一部文法G, 从G的开始符号S出发,反复使 用产生式对非终结符进行替换,最后所得到的终结符 号串的全体,即为文法G所描述的语言L(G)。
如:设有文法G: S → P | aPb,P → ba | bQa,Q → ab ;
L(G)={ba, baba, abab, ababab}
直接推导=>:有 ν = α Aβ=> α γβ= ω ( α ,β,γ∈(VN∪VT)*),当且 仅当P中存在一条规则A ->γ,称 ν 直接推导出 ω (或 ω 直接归约到 ν ),记作: ν => ω 。
直接推导序列: 则 ν 经过n步(n>0)可以推导出ω ,记作:ν =(+)>ω 。当ν=>ω 或 ν=ω ,记作: ν(*)=>ω
句型:设有文法G[S],若 S =(*)> α ( α ∈(VT∪VN)*),则称
α 为G[S]的句型句子:设有文法G[S] , 若S =(*)>α ( α∈VT*) ,则称 α 为G[S]的句子。
最左(右)推导
规范推导/规范句型/规范归纳:最右推导也称为规范推导 。仅用规范推导得到的句型称为规范句型 。规范推导的逆序为规范归约。
递归文法:设有文法G,A→ γ是G的产生式,若 γ 具有 α A β的形式,或 γ
=(+)>α A β ,则称G是递归文法。- 若 α = ε ,则G为左递归文法。
- 若 β=ε ,则G为右递归文法
语言:文法 G所产生(描述)的语言L(G): L(G) = { α | α ∈VT*∧ S =(+)> α ,S是文法 G 的开始符号 }
文法等价:若 L(G1)= L(G2),则称文法G1和G2是等价的
EBNF:扩充BNF,假如{} () []
语法图:
- 由一组图组成,每个图定义了一个非终结符的产生式 。
- 每个图都有一个起始结点和一个终止结点,其他的结点标记为 文法符号。
- 终结符结点用圆形表示。
- 非终结符结点用方形表示。
- 从起始结点到终止结点的所有路径(标记为结点序列)定义候 选式。
语法分析树
二义文法:对一部文法G,如果至少存在一个句子,有两棵 ( 或两棵以上 )不同的分析树,则称该句子是二义性的。包含有二义性句子的文法称为二义文法。否则,该文法是无二义性的
- 文法二义与语义二义无关
文法二义性消除:构造G1′ ,使L( G1)=L( G1′)
文法分类:
- 0型(短语)文法:如果对文法G中的规则 α → β 不加任何限制,则称G 为0型文法或短语文法。
- 1型文法(上下文有关文法):设文法G=(VN,VT,S,P),对P中的每个产生式(除 S → ε 外,但此时S不得出现在任何产生式的右部 ) 限制为形如:α A β → α γ β其中,A∈VN, α , β ∈(VT∪VN)﹡, γ ∈(VT∪VN)+, 则称文法G为1型文法或上下文有关文法。
- 2型文法(上下文无关文法):设文法G =(VN,VT, S , P),对P中的每个产生 式限制形如: A→ α 其中,A∈VN, α ∈(VT∪VN)* 则称文法G为2型文法。
- 3型文法(正则文法、线性文法):设文法G=(VN,VT, S, P),对P中的每个产生式 形如: A→ α B 或A→ α 或者(A→B α 或 A→ α) 其中,A,B∈ VN, α ∈VT*,则称文法G为3型文法 (正则文法或线性文法)。
确定的有限状态自动机DFA:一个确定的有限自动机M ( DFA M)是一个五 元组 M =(Q, ∑ , f, q0, Z)
Q:状态的有限集合,每个元素qi(qi∈Q) 称为一 个状态。
∑ :输入字符的有限集合(或有穷字母表)。
f:状态转换函数:从Q× ∑ →Q的映射。 例如, f(p,a)=q, q、p∈Q, a∈ ∑ 。表示了在状 态p读入字符a后转入状态q。q也称为p的 后继状态
q0:M的唯一初态(也称开始状态),q0∈Q
Z: M的终态集(或接受状态集) Z⊆Q。
形式定义<->状态转换图 <-> 状态转换表
DFA识别机制:(识别方法)
L(M) 为全部接收的字符串
非确定的有限状态自动机NFA:一个非确定的有限自动机M ( NFA M)是一个五元组M =(Q,∑ , f, q0, Z)
- Q,∑ , Z, q0同DFA
- f:状态转换函数。 从Q×( ∑ ∪{ ε }) →2Q的映射。这里的后继状态不 是唯一的,它是状态集Q的子集。
识别机制:L(M) 为全部接收的字符串
NFA确定化
- 对任何一个NFA M,都存在一个DFA M ’ , 使 L(M’ )=L(M)。
确定化的算法-子集法:I是NFA M’ 状态集Q的一个子集。(即I⊆Q), 则ε-closure(I)为~~~
状态集合I的α弧转换Ia : Ia=ε-closure({p|∃q∈ ε -close(I),p∈f(q,a)})。
DFA化简
通过删除无关状态,合并等价状态的规约过程,直至得到规约机( 最小的DFA)
无关状态或多余状态或无用状态
如果从DFA M的初态开始,任何输入序列都不能到达的那些状态称为无关状态
等价状态、可区分状态
设DFAM的两个不同状态 q1,q2,如果对任意 输入字符串ω,从q1,q2状态出发,总是同时到达接收状态或拒绝状态之中,称q1,q2是等价的。
正则文法与有限自动机
设文法G=(VN, VT, S, P)为一右线性文法(左线性文法结论相同),则存在一有限自动机M=( Q, ∑ , f, q0, Z),使得:L(M)=L(G)
构造
- ∑ = VT
- q0= S
- Q= VN∪{qz}, qz为一附加状态且qz∉ VN
- Z= {qz}
- f:若P中有产生式B →a, 则qz∈f(B,a) 若P中有产生式B →aC,则C∈f(B,a) a∈VT∪{ε}
正规式与正规集
- ε和Ф是∑上的正规式,它们表示的正规集分别 为{ε}和Ф;
- 对任何a∈∑,a是∑上的正规式,它表示的正规集为{a};
- 若r,s都是正规式 , 对应的正规集分别为R和S , 则 (r|s)、(r·s)、(r)*也是正规式,它们表示的正规集分别是:R∪S,RS,R*。
- 有限次使用上述三条规则构成的表达式,称为∑上 的正规式,仅由这些正规式表示的集合为正规集
正规式与有限自动机的等价
- 字母表∑上的有限自动机M所接受的语言 L(M) 是∑上的一个正规集;
- 对于∑上的每一个正规式 r,存在一个∑上的有 限自动机M,使得:L(M)=L(r)。
三、词法分析
属性字:对所识别的单词的数据结构表示。
L1= ( T(Token),C(Code))
扫描器设计与实现
作为扫描器的状态转换图(FA)的构造
- 对语言的各类单词分别构造状态图
- 将各类状态图合并,构成一个能识别该语言所有单词的状态图。
- 将各类单词的状态图的初态合并为一个惟一初态;
- 调整冲突编号。
状态转换图实现之一:数据中心法
将状态转换图看成一种数据结构(状态表),用总控程序控制输入的源程序串在其上运行。
- 主表: 数据项= 状态 + 分表地址或子程序入口
- 分表: 数据项= 当前输入字符 + 转换状态
状态转换图实现之二:程序中心法
将状态转换图看成一个流程图,从初态开始对 它的每个节点(状态)编写一函数或直接跟踪状态 图从初态开始的转换完成所有分支的跟踪来编写程 序。
四、语法分析–自上而下分析法
不确定性
消除直接左递归:对P→P α|β, α 、 β ∈(VT∪VN)* 修改为P→ β P′, P′→ α P′|ε
消除间接左递归:
把间接左递归文法改写为直接左递归文法;
依次按照C,B,A的顺序向前带入,注意只替换A->Ba这种形式,A->aB无需替换
用消除直接左递归的方法改写文法
消除回溯:利用First和Follow
First集
设G是二型文法,则G中的任意 α∈V*的终结首符集FIRST( α )为 FIRST ( α ) = { a |α=> a ……,a∈VT } 若α =>ε, 则ε∈FIRST( α ) 。
算法:
计算FIRST(X)(X∈V)
- 若X是终结符,则FIRST(X)={X};
- 若X是非终结符,X的FIRST为其所有候选式的 FIRST集合的并集。
计算FIRST( α )( α ∈V*)
设 α =X1X2… Xk (Xi∈V)
- FIRST(X1)中的所有终结符号加到FIRST( α )中;
- 若对于某个i,a∈ FIRST(Xi)且X1X2… Xi-1⇒ ε, 则将a加到FIRST( α )中;
- 若对于所有的j=1,2,…,k, ε ∈ FIRST(Xj), 则将 ε 加到FIRST( α )中
对非终结符A的多个候选式的FIRST( αi)的相互两个彼此交集≠Φ,一般是因为 αi中有公共左因子,可 以通过提取左公因子来改造文法。(由BNF范式改 EBNF范式)
状态图构造(为文法G的每个VN )
- 建立1个初态和1个终态(函数返回态);
- 为每个产生式 A→ x1x2 … xn 建立从初态到终 态的路径,弧标记为x1,x2, …,xn ;
化简递归下降分析器(化简状态图)
LL(1)分析法
- 显式地维护一个状态栈,而不是通过隐式的递归调用来做自上而下的语法分析
- 逻辑结构:总控程序,LL(1)分析表,分析栈
Follow集
- 设上下文无关文法G,S是文法的开始符 号,对于文法G的任何非终结符A FOLLOW(A)={a|S=>…Aa…,a∈VT} 若S=>…A,则令#∈FOLLOW(A)。
- FOLLOW(A)的含义是指,在文法G的句型中,能够紧跟着A之后的一切终结符或“#”
- 算法:
- 对文法的开始符号S,令#∈FOLLOW(S) ;
- 若文法G中有形如A→ α Bβ的规则,且β≠ε, 则将FIRST(β)中的一切非ε符号加入 FOLLOW(B);
- 若G中有形如 A→α B 或 A→α Bβ的规则,且ε∈FIRST(β),则FOLLOW(A)中的全部元素 属于FOLLOW(B)
LL(1)分析表的构造
- 对文法G,若G中对非终结符A的产生式形如 A→ α | β 且 α 和 β 均不推出ε,则可产生LL(1)分析表的A行为:
- 对∀ a∈FIRST( α ) ,a列即 M (A,a) = { A→ α }
- 对∀ b∈FIRST( β ) ,b列即 M (A,b) = { A→ β }
- 对A→ α | β 且α 或 β 推出ε的情况,产生LL(1)分 析表的A行为,
- 若 α =>ε 对∀ a∈FIRST( α )∪FOLLOW(A), a列即 M (A,a) = { A→ α }
- 若 α 不推出空串, 对∀ a∈FIRST( α ) ,a列即 M (A,a) = { A→ α}
- 若 β=>ε 对∀ b∈FIRST( β )∪FOLLOW(A), b列即 M (A,b) = { A→ β }
- 若 β 不推出空串, 对∀ b∈FIRST( α ) ,b列即 M (A,b) = { A→β }
- 对文法G,若G中对非终结符A的产生式形如 A→ α | β 且 α 和 β 均不推出ε,则可产生LL(1)分析表的A行为:
LL(1)重要性质
- 任何LL(1)文法是无二义性的。
- 若一文法为左递归文法,则它必然是非 LL(1)文法。
- 非LL(1)语言是存在的。
- 存在一种算法,它能判定任一文法是否为 LL(1)文法。
- 不存在这样的算法,它能判定上下文无关 语言能否由LL(1)文法产生。
非左递归文法G为LL(1)文法⇔G的任何一个非 终结符 A,设关于A的产生式为 A→ α 1 | α 2 |…| α n 满足下面的条件:
- 每个候选式 α i,FIRST( α i)两两彼此互不相 交。
- 若有 α i =>0,则FIRST(α) ∩ FOLLOW(A) = ∅。
五、语法分析–自下而上分析法
短语:S是文法G的开始符号,α β δ 是G的一个句型,若 S =>α A δ 且A =(+)>β,则 β 是句型 α β δ 相对于A的短语
直接短语:S是文法G的开始符号,α β δ 是G的一个句型,若 S =>α A δ 且A→ β ,则 β 是句型 α β δ 相对于A的直接短语
句柄:一个句型的最左直接短语称为句柄
(所有短语根据子树的叶子节点判断即可)
算符优先分析法
- 基本思想:对给定的G按照一定原则求出G的文法符号间的优先关系,按照优先关系确定可归约子串实施归约。
算符文法(OG):设有一文法G,如果G中没有 U→…VW… 的规则,其中V,W,U∈ VN,则称文法G 是算符文法(OG)
算符文法的任何句型都不会含有两个相邻的非终结符
算符优先文法(OPG)
设G是一不含P→ε形式规则的算符文法,则对于任何a,b有:
- a≐b,当且仅当文法G中有形如 A→… ab… 或 A→… aBb…的规则:
- a⋖b,当且仅当文法G中有形如A→… aB…的规 则,其中B=>b… 或 B=> Cb… ;
- a⋗b,当且仅当文法G中有形如A→… Bb…的规 则,其中B => … a或 B=> … aC
算符优先关系表构造(貌似不考。)
素短语:设G是一个算符文法, β 是句型 α β δ 关于A 的短语且 β 含有至少一个终结符号,并且除自身外不再含有任何更小的带终结符号的短语,则 β 是句型 α β δ 关于A的素短语。
最左素短语:文法G的句型 α 的最左边的素短语为最左 素短语。
优先函数表的构造(貌似也不考。)
算符优先分析器
- 组成:总控程序+分析栈+优先函数表
LR分析技术是编译系统中语法分析器实现最常用、最有效的一种分析方法。
- LR->自左向右,最右推导的逆序(规范规约)
- LR分析器结构:
- 组成:总控程序+分析栈+LR分析表
- 实例
活前缀:规范句型的不含句柄之后任何符号的前缀,称为该句型的活前缀
LR(0)项目:在文法G的每个产生式的右部(候选式)的任何位置上添加一个圆点,这样构成的每个产生式称为LR(0)项目。
圆点的位置标记相应的候选式已被匹配(放入栈中)了多少
项目分类:
- 规约项目
- 接受项目
- 移进项目
- 待约项目
构造识别文法G的所有活前缀的非确定有限自动机NFA+识别文法G的所有活前缀的DFA
文法G的LR(0)项目集规范族:识别文法G的活前缀的DFA,其状态中包含的LR(0)项目集的全体
- 构造方法一:
- 构造文法G的LR(0)项目;
- 基于LR(0)项目,构造识别文法 G所有活前缀的NFA
- NFA确定化为DFA,该DFA的各个状态所包含的项目集的集合,即构成了G的LR(0)项目集规范族。
- 构造方法二:(closure(项目集闭包)函数+GO(项目集转移)函数)
- 拓广文法。设G是一文法,S是它的开始符 号,则将产生式S′→S加入到G中构成新的文 法G′,S′为 G′的开始符号,G′称为G的拓广文 法(使文法开始符号的侯选式惟一)
- 构造文法G的LR(0)项目集规范族。
- 构造方法一:
项目集闭包
构造方法:
- I中的每一个项目皆属于closure(I);
- 若形如A→ α ·Bβ(B∈VN) 的项目属于I, 则对G中的任何产生式 B → γ 的第一个 LR(0)项目(B→· γ )也属于closure(I);
- 重复上述步骤,直至不再有新的项目加入 closure(I)为止;
项目集转换函数GO( I , X)
若 I 是文法G的一个项目集,X为G 的 符号,则GO(I , X)=closure(J)。 其中 J={形如A→αX·β的项目|∃A→ α ·Xβ∈I}。(注意 · 的位置)
LR(0)文法:若一个文法G的识别活前缀的DFA的每一个 状态(项目集规范族中的的每一个LR(0)项目集) 中不存在 ① 即含移进项目又含归约项目; 和 ② 含有多个归约项目; 则每个项目集的项目相容,称G是一个 LR(0)文法。
构造LR(0)分析表
算法一(根据DFA)
- 若f (K,a)=j(a∈ V T),则置 action(K , a)=Sj;
- 若f (k ,A)=j (A∈ V N),则置 GOTO(K,A)=j ;
- 若A→ α ·∈k,则对所有终结符a和结束符“#”, 置action(K , a)=rj和 action(K , #)=rj。 (其中假设产生式A→ α ·是文法第 j 个产生式)
- 若S ′→ S · ∈k,则置action(K , #)=acc
- 表中空白置出错标志
算法二(根据GO函数以及项目集规范族)
- 若GO (Ik ,a)=Ij(a∈ V T),则置 action(K , a)=Sj
- 若GO (Ik ,A)=Ij(A∈ V N),则置 GOTO(K,A)=j ;
- 若A→ α ·∈Ik,则对所有终结符a和结束符 “#”,置action(K , a)=rj和 action(K , #)=rj。 (其中假设产生式A→ α ·是文法第 j 个产生式)
- 若S ′→S · ∈Ik,则置action(K , #)=acc;
- 表中空白置出错标志
项目集存在归约-归约冲突
在识别活前缀的DFA某一状态(项目集规 范族的某一项目集)中,若既含有圆点不在 最后的移进项目,又含有圆点在最后的归约项 目,则称该项目集存在移进-归约冲突。若含 有两个或两个以上圆点在最后的归约项目,则 称该项目集存在归约-归约冲突
构造SLR(1)分析表 (上面第3步时先判断输入符号是否属于某个follow集)
算法:
- 若GO (Ik ,a)=Ij(a∈ V T),则置 action(K , a)=Sj
- 若GO (Ik ,A)=Ij(A∈ V N),则置 GOTO(K,A)=j ;
- 若A→ α ·∈Ik,则对所有a∈FOLLOW(A), 置action(K , a)=rj。 (其中假设产生式A→ α ·是文法第 j 个产生式)
- 若S ′→S · ∈Ik,则置action(K , #)=acc;
- 表中空白置出错标志
按照SLR(1)方法构造的文法G的LR分析 表,如果每个入口不含多重定义,则称它为G 的SLR(1)分析表。具有SLR(1)分析表的文法G 称为SLR(1)文法。使用SLR(1)分析表的语法分 析器称作SLR(1)分析器
SLR(1)分析表构造= SLR(1)方法+ LR(0)分析表构造
SLR(1)方法 =有归约项目的状态中归约动作的设置。
LR(k)项目:文法G的一个LR(k)项目是 [A→ α ·β,a1a2 … ak ]其中: A→α ·β是一个LR( 0 )项目; ai∈ VT∪{#} ; a1 a2 … ak:搜索符串
LR(1)有效项目
若文法G的一个LR(1)项目[A→α ·β,a]对活前缀 γ 是有效的,当且仅当存在规范推导 S=(*)> δ Aω=(*)> δ α β ω 其中:ω∈VT*, γ = δ α ,a∈FIRST( ω )或 a为’#’(当 ω = ε ),称a为搜索符
六、语义分析与中间代码生成
- 语法制导翻译:为文法的每一个产生式配一个相应的语义子程序(或语义规则描述的语义动作),并在语法分析的同时调用它。
- 属性翻译文法:把语义引入文法,给产生式中的文法符号附加“属性”,构成涉及语义的翻译文法
- 综合属性 :分析树中,如果一个结点的属性值是通过 子结点的属性值计算得到则称为综合属性。
- 继承属性 :分析树中,如果一个结点的属性值是由该 结点的父结点和(或)兄弟结点的属性定义的 称为继承属性
- 中间语言:
- 逆波兰式
- N元式
- 三元式(三元式表)
- 间接三元式(间接码表+三元式表)
- 四元式 NO. ( OP, ARG1 , ARG2 ,Result)
- 图(树)
- 一个三元式 <–> 一棵子树
- OP <–> 子树根
- ARG1 <–> 子树左叶节点
- ARG2 <–> 子树右叶节点
- 符号表->整个编译过程中动态地采集、记录、变更、引用
- 定义:存放源程序中有关标识符的属性信息的 数据结构。
- 结构:名称域+属性信息域
- 作用:收集标识符属性信息;语义检查依据; 代码生成时地址分配依据
- 标识符类的主要属性和作用
- 标识符名。作用:查重(考虑作用域和可视性前提)
- 类型。作用:存储空间分配;可施加运算的检查等
- 存储类别。作用:提供语义处理、检查、存储 分配的依据。
- 作用域、可视性。作用:动态活动环境支持,提 供量所在层次;
- 语句标号表LT
- 构成:标号名 + 定义否(flag) + addr(1表示定义性出现,0表示使用性出现)
- 拉链反填技术:处理标号先引用后定义的情况,适用于一边扫描的编译器
八、代码优化
- 基本块
- 特点1:唯一入口和唯一出口
- 特点2:没有转进转出,分叉会合
- 基本块划分
- 确定每个基本块的入口语句。
- 根据确定的基本块的入口语句,构造 其所属的基本块
- 凡是未包含在基本块中的语句,都是程序 的控制流不可到达的语句,直接从程序中删除。
- 程序的控制流图
- DAG 无环路的有向图 ->确认的式基本块内各四元式间的关系
- 循环
- 强连通性
- 入口唯一
- 必经节点:ni DOM nj -> 到达nj的任意通路都经过ni
- 必经节点集:D(n)
- 回边:a→b是流图G中一条有向边,如果b DOM a, 则称a→b是流图G中的一条回边。记作