编译原理--复习知识点整理(散装自用)
声明:本博客为自己为复习编译原理整理的一些知识点(虽然完美滴错过了考试重点),引用了多篇博客内容(原文见本人编译原理收藏夹😊)。仅作为学习记录,无意侵权~
文法相关符号
VT:终结符集合 VN 非终结符结合。
S:开始符号。
P:产生式集合。
短语-直接短语-句柄
短语:一个句型的语法树中任一子树叶结点所组成的符号串都是该句型的短语。
直接短语:指的是如果子树中不再包含其他的子树,即A只能推导出b,而b不能再推出其他的式子,则b为此句型的直接短语。
句柄:直接短语中的最左直接短语为该句型的句柄。
NFA-DFA
DFA:确定的有限自动机。
NFA:非确定的有限自动机。
NFA转DFA步骤:
- 确定由ε得到的closure(0),构造状态集闭包;
- 然后确定move( , ),构造closure(move( ,))闭包;
- 简化状态,构造状态转移表;
- 画图。
最小化DFA步骤:
- 去除无关状态,合并等价状态;
- 分割子集法,首次分为终态集与非终态集。然后,对每个子集G,如果面对某个输入符号得到的后继状态不属于同一个子集,则将G进一步划分。
最左推导
自顶向下推导,文法:LL(1)
LL(1)重点在于求FIRST集、FOLLOW集、SELECT集。
(第一个L 表示从左到右扫描输入串 第二个L表示生成的是最左推导 1表示向右看一个输入符号决定选择哪个产生式)
FIRST(A)为A的开始符或者首符号集
- 若X∈VT,则FIRST(X)={X} 简单讲,终结符的FIRST集就是它本身。
- 若X∈VN,且有产生式X→a…,a∈VT, 则 a∈FIRST(X) X→ε,则ε∈FIRST(X) 简单讲,若是非终结符X,能推导出以终结符a开头的串,那么这个终结符a属于FIRST(X),若X能够推导出空符号串ε,那么空符号串ε也属于X的FIRST集。
- X→Y…是一个产生式且Y ∈VN 则把FIRST(Y)中的所有非空符号串ε元素都加入到FIRST(X)中。
- 若X∈VN, Y1,Y2,…,Yi∈VN,且有产生式X→Y1 Y2 … Yn;当Y1 Y2 … Yn-1都能推导出ε时,则FIRST(Y1)、FIRST(Y2)、…、FIRST(Yn-1)的所有非空元素和FIRST(Yn) 包含在FIRST(X)中。即: FIRST(X)=(FIRST(Y1)-{ε} )∪(FIRST(Y2)-{ε} )∪…∪(FIRST(Yn-1)-{ε})∪{FIRST(Yn)}
- 当所有Yi 能够推导出ε,(i=1,2,…n),则FIRST(X)=(FIRST(Y1)-{ε})∪(FIRST(Y2)- {ε}∪…∪(FIRST(Yn) -{ε})∪{ε}
FOLLOW(A)为非终结符A的后跟符号集合
- 设S为文法中开始符号,把{#}加入FOLLOW(S)中(这里“#” 为句子括号)。
- 若A→αBβ是一个产生式,则把FIRST(β)的非空元素加入FOLLOW(B)中。
- 如果β能够推导出ε则把FOLLOW(A)也加入FOLLOW(B)中,反复使用(2)直到每个非终结符的FOLLOW集不再增大。
SELECT集
- 若α不能推导出ε,则SELECT(A→α)=FIRST(α)
- α能推导出ε则:SELECT(A→α)=(FIRST(α) –{ε})∪FOLLOW(A)
注意⚠️:左递归问题 公共左因子 不能用自顶而下分析。
如何消除左递归??
- 直接左递归:A→Aβ|γ ——> A→γA’ (终结符+X’) A'→βA'|ε ( X’+去掉左递归的产生式|空集)
- 间接左递归:将间接左递归式子化为直接左递归,利用1转化。
最右推导
自底而上规约,文法:LR(0)、LR(1)、 SLR(1)、 LALR(1)
重点在于求action-goto表。
action表用于告诉分析引擎:在栈顶状态为k,输入符号是a的时候做什么。
action(k,a)=si // 将状态i移入栈顶
action(k,a)=rj // 按照第j条产生式进行归约
action(k,a)=acc // 分析完成
action(k,a)=err // 发现错误
goto表
goto(i,A)=j告诉引擎,在依照产生归约之后,栈顶状态为i,要将j移进栈顶。
LR(0)文法
- 拓广文法 在产生式前加上·
- 分析接收字符,构造LR(0)自动机
- 构造LR(0)分析表 status action goto 终止项对应action 內填写对应的归约式
判断是否是LR(0)文法
如果文法对应的自动机中不存在移进-归约冲突和归约-归约冲突则为 LR(0)文法。
SLR(1)
拓广文法、写自动机、分析过程表与 LR(0)文法相同
判断是否是SLR(1)文法
用 follow集来处理即出现移进-归约冲突的两条产生式,如果其 follow集相交为空则为 SLR文法,反之不是。
LALR(1)
- 拓广文法一致
- 与 LR(0)自动机,LR(1)自动机多了向前搜索符
- 合并同心集,即合并产生式相同但是向前搜索符不同的项集族.由于合并了同心集,所以 LALR分析表也应该做出相应的改变,例如合并了 I3和 I6,则对应的格中应填 S36 .
判断是否是LALR(1)文法
合并同心集不会产生新的移进-归约冲突。但是会产生新的归约-归约冲突,如果没产生冲突就是 LALR 文法,反之不是。
LR(1)
分析过程与 LALR文法相同。
判断是否是LR(1)文法
因为 LR(1)文法的范围比较大,所以文法几乎都是 LR(1)的。现在知道的只有当合并同心集产生了归约-归约冲突时才只属于LR(1)文法,而不属于其他文法
算符优先文法
如果它的任意产生式的右部都不含两个相继(并列)的非终结符,即不含如下形式的产生式右部:…QR…
那么我们称该文法为算符文法。
LL(1)重点在于求FIRSTVT集、LASTVT集.
FIRSTVT集
- P->a…或者P->Qa…,那么a∈FIRSTVT(P);
- a∈FIRSTVT(Q)且P->Q…,那么a∈FIRSTVT(P)。
LASTVT集
- P->…a或者P->…aQ,那么a∈LASTVT(P);
- a∈LASTVT(Q),P->…Q,那么a∈LASTVT(P)。
文法构造步骤:
- 构造非终结符的FIRSTVT集和LASTVT集;
- 构造优先关系表:
- 首先找的是=关系,就是两个终结符之间夹着一个非终结符的情况,所以这道题中[和]是=关系;
- 然后看的是<关系,找的是终结符+非终结符的形式,就是[E,+E,可以得出[<FirstVT(E),+<FirstVT(E),相比较而言,>关系就是找非终结符+终结符的形式,N[,E,],V+,可以得出LastVT(N)>[,LastVT(E)>],LastVT(V)>+;
- #号的填法,用到FIRSTVT(S)集和LASTVT(S)集。
运用规则:
不断取输入字符串的栈顶和当前符号比较优先级,若是<或者=的关系就是移进的操作,如果是>的关系就是规约的关系。
属性
综合属性: 自下而上 传递信息
继承属性: 自上而下 传递信息
终结符只有综合属性,由词法分析器提供。
非终结符既有综合属性又可以有继承属性。
语法制导定义
两个🌰,看看吧~
写出一个语法制导定义,输出配对括号个数
为S,L引入属性h
S’—>S print(S.h)
S—>(L) S.h=L.h+1
S—>a S.h=0
L—>L1,S L.h=L1.h+S.h
L—>S L.h=S.h
写一个翻译方案,打印每个a的嵌套深度
S’—>S S.d=0
S—>(L) l.d=s.d+1
S—>a print(S.d)
L—>L1,S L1.d=L.d,S.d=l.d
L—>S S.d=l.d
基本块
基本块是指程序中以顺序执行的语句序列,只有一个出口和入口。
如何优化基本块:
- 合并已知量;
- 删除无用赋值;
- 共用公共子表达式。