编程学习-编译原理
本语法分析是编译程序的核心功能之一。语法分析的作用是识别由词法分析给出的单词符号串是否是给定问法的正确句子(程序)。语法分析常用的方法可分为自顶向下分析和自底向上分析两大类。
确定的自顶向下分析思想
对于一个上下文无关文法,在推导过程中完全可以根据当前的输入符号决定选择哪个产生式往下推导,因此分析过程是唯一确定的。
- 比如有以下文法
- G[S]:
- S→pA | qB
- A→cAd | a
- B→dB | b
若输入串W=pccadd,自顶向下的推导过程为S⇒pA⇒pcAd⇒pccAdd⇒pccadd。在这个过程中,即使每个非终结符都对应了两个产生式,你也可以明确的知道使用那个产生式进行推导。
假如把上述S→pA | qB产生式换成S→pA | pB,在你一开始推导时,因为S的两个产生式首个字符都为p,你将不知道选择哪一个进行推导。
1、FIRST(α)开始符号集或首符集
定义:设G=设G=(VN,VT,P,S)是上下文无关文法 。
FIRST(α)={a | α 经任意次推导⇒aβ,a∈VT,α,β∈V*}
- VN:非终结符的集合,用大写字母表示
- VT:终结符的集合,用小写字母表示
- P:为规则(α→β)的集合,即产生式的集合
- S:称作识别符或开始符,它是一个非终结符
求法:
(1)若α=a···,则a∈FIRST(α)
(2)若α=Xα’,(x∈VN),则FIRST(x)-{ɛ}⊆FIRST(α)
(3)若α=X1X2X3X4···Xn (X1,X2,X3,X4,···Xn∈VN),且X1,X2,X3···Xk经过至少1次推导可以推导出ɛ,则FIRST(Xk+1 ···Xn)⊆FIRST(α)
(4)若α任意次⇒ɛ,则ɛ∈FIRST(α)
(5)若α=β1 | β2 | β3 | ··· | βn,则FIRST(α)=FIRST(β1)U FIRST(β2)U ··· U FIRST(βn)
用文字表达来说就是:
(1)当产生式第1个字符就是终结符,这个终结符就属于FIRST(α)集合中的1个元素
(2)当产生式第1个字符为非终结符,这个非终结符的FIRST集合是FIRST(α)的一个子集
(3)当产生式的前一部分可以推导出空ɛ,则后一部分的FIRST集合是FIRST(α)的一个子集
(4)当产生式经过推导可以推导出空ɛ,则ɛ为FIRST(α)集合中的1个元素
(5)当同一个非终结符对应了多个产生式时,则每个产生式的FIRST集合的并集组成FIRST(α)
2、FOLLOW(A)随符集
定义:设G=设G=(VN,VT,P,S)是上下文无关文法 。
FOLLOW(A)={a | S 经任意次推导⇒···Aa···,a∈VT,A∈VN}
求法:
(1)若A是一个开始符号,则#∈FOLLOW(A)
(2)若B→αAaβ,则a∈FOLLOW(A)
(3)若B→αA 或 B→αAβ,但β可以推导出空ɛ,则FOLLOW(B)是FOLLOW(A)的子集
(4)若B→αAXβ,则FIRST(Xβ)是FOLLOW(A)的子集
3、SELECT(A→α)选符集
α:为终结符VT和非终结符VN的并集
求法:
(1)当α怎么也推导不出空ɛ时,SELECT(A→α)=FIRST(α)
(2)当α=ɛ时,SELECT(A→α)=FOLLOW(A)
(3)当α经过至少一次推导才为空ɛ时,SELECT(A→α)=(FIRST(α)-{ɛ})U FOLLOW(A)
LL(1)文法
解释:L从左到右,最左推导,向前看一个符号决定如何推导。
1、LL(1)文法的判别
①上下文无关文法是LL(1)文法的充要条件
②文法中出现的每一个非终结符A,如果A有两个不同的产生式,那么这两个产生式所对应的SELECT集合的交集为空。
2、LL(1)文法的特征
①不含二义性
②不含左递归
3、非LL(1)转化LL(1)
①提取公共因子
②消除左递归
举例:求下述文法的三个集合、分析表、栈表,判断aaabd是否为该文法的一个句子。
G[S]:
S→aH
H→aMd | d
M→Ab | ɛ
A→ aM | e
FIRST(α) | FOLLOW(A) | SELECT(A→α) |
---|---|---|
FIRST(S)={a} | FOLLOW(S)={#} | SELECT(S→aH)={a} |
FIRST(H)={a,d} | FOLLOW(H)={#} | SELECT(H→aMd )={b} |
FIRST(M)={ɛ,a,e} | FOLLOW(M)={d,b} | SELECT(H→d )={d} |
FIRST(A)={a,e} | FOLLOW(A)={b} | SELECT(M→Ab)={a,e} |
———— | ———— | SELECT(M→ɛ)={d,b} |
———— | ———— | SELECT(A→ aM )={a} |
———— | ———— | SELECT(A→e)={e} |
根据SELECT集合写分析表:
a | b | d | e | # | |
---|---|---|---|---|---|
S | aH | ||||
H | aMd | d | |||
M | Ad | Ad | |||
A | aM | e |
栈表:逆序进栈,查分析表
1. #S aaabd#
2. #Ha aaabd#
3. #H aabd#
4. #dMa aabd#
5. #dM abd#
6. #dbA abd#
7. #dbMa abd#
8. #dbM bd#
9. #db bd#
10. #d d#
11. # #
总结:FIRST(α)求的是第1个遇到的终结符的集合,FOLLOW(A)求的是非终结符后面所跟着的终结符的集合,SELECT(A→α)求的是产生式的集合。