文章目录
语法分析器
- 语法分析的任务:对任⼀给定 w ∈ VT*,判断 w ∈ L(G)?
- 语法分析器:按照产生式规则,做识别w的工作
语法分析方法
- 自上(顶)而下分析
- LL(1)分析法
- 递归下降分析法
- 预测分析法
- 自下(底)而上分析
- 算符优先分析法
- LR分析法
自上而下分析
- 从文法的开始符号出发,向下推导,推出句子
- 对任何的输入串(单词符号),试图用⼀切可能的办法, 从文法的开始符号出发,自上而下地为输入串建立⼀棵语法树,即为输入串寻找⼀个最左推导
LL(1)分析法
- 从左(Left)到右扫描输入串;构造最左(Leftmost)推导;分析时每步向前看⼀个(1)字符。
- 目的:构造不带回溯的自上而下分析算法
- 左递归的消除
- 消除回溯,提左因子
- FIRST集合,FOLLOW集合
- LL(1)分析条件
- LL(1)分析方法
左递归文法
- ⼀个文法含有下列形式的产生式时,
a)直接递归
A->A β \beta β A ∈ \in ∈VN, β \beta β ∈ \in ∈V*
b)间接递归
A->B β \beta β
B->Aa A,B ∈ \in ∈VN, a,b ∈ \in ∈ V*
称为左递归文法。 - 如果⼀个文法是左递归时,则不能采用自顶向下分析法。
- 例1. 文法S -> Sa, S -> b 是直接左递归
语言是:L={ ban | n≥0} - 例2. 文法 A -> aB, A->Bb, B->Ac, B->d 是间接左递归
消除直接左递归
- P -> Pα│β(α≠ε,β不以P开头)
↓ \downarrow ↓
P -> βP’
P’ -> αP’ │ε - 例. 文法
E→E+T│T
T→T*F│F
F→(E)│i
↓ \downarrow ↓
E→TE’
E’ → +TE’ │ε
T→FT’
T’ → *FT’ │ε
F→(E)│i - 有很多个
α
\alpha
α
β
\beta
β:
⼀般地, 假定P关于的产生式是
P→Pα1│Pα2 │… │Pαm │β1 │β2 │… │βn
其中:αi≠ε,βi不以P开头,则改写为:
P→ β1 P’ │β2 P’ │…│βn P’
P’ →α1 P’ │ α2 P’ │… │αm P’ │ε
消除左递归算法
(1)排序 (2)改写并消除左递归 (3)化简删除永不使用的产生式
- 例1.文法G(S) R→Sa|a, Q→Rb|b, S →Qc|c
有推导:S ⇒ Qc ⇒ Rbc ⇒ Sabc, 存在左递归。- 按R(1)、Q(2)、S(3)排序
- 执行算法
按照排序顺序带入
Q->Sab|ab|b
S->Sabc|abc|bc|c
消除左递归
α \alpha α=abc, β \beta β=abc|bc|c
S->abcS’|bcS’|cS’
S’->abcS’| ϵ \epsilon ϵ - 消除无用产生式
- 结果:
S->abcS’|bcS’|cS’
S’->abcS’| ϵ \epsilon ϵ
- 例2. 消去下面文法的左递归
T → T,S|S
S → a|+|(T)- 过程:
α
\alpha
α=,S,
β
\beta
β=S
T->ST’,T’->,ST’| ϵ \epsilon ϵ - 结果:
T->ST’
T’->,ST’| ϵ \epsilon ϵ
S->a|+|(T)
- 过程:
α
\alpha
α=,S,
β
\beta
β=S
回溯解决方法
提取公共左因⼦,将文法改造成任何非终结符的所有候选首符集两两不相交。
- 例1. 文法G:S→aSb|aS|ε
- 解:提取: S →aS(b|ε)
S→ε - 引入新符: S →aSA
A→ b|ε
S→ε
- 解:提取: S →aS(b|ε)
- 例2. 文法G:S→abc|abd|ae
- 解:提取: S →a(bc|bd|e)
- 引入新符: S →aA
A→ bc|bd|e - 引入新符:B->c|d
- 结果:
S->aA
A->bB|e
B->c|d
FIRST(X)
- 终结符是终结符
- 非终结符
- 推出空字,空字
- 推出非终结符,FIRST(非终结符)
- 例1.
G: E → TE’
E’→ +TE’ │ε
T →FT’
T’ → *FT’ │ε
F →(E)│i
求每个非终结符号的FIRST集合
解:FIRST (E) = FIRST (T)= FIRST (F)= { (, i }
FIRST (E’ ) = { +, ε }
FIRST (T’ ) = { *, ε} - 例2.
文法规则 | FIRST(X) |
---|---|
E → E A T | T | {(,n} |
A → + | - | {+,-} |
T → T M F | F | {(,n} |
M → * | {*} |
F → (E) | n | {(,n} |
FOLLOW(X)
对于文法G的每个非终结符,构造FOLLOW(A)的方法是:
(1)若A为文法开始符号,置#于FOLLOW(A)中;
(2)若有产生式B→αAβ,则将FIRST(β) - {ε}加到FOLLOW (A)中;
(解释:忽略空字)
(3)若有B→αA或B →αAβ, 且β =*=> ε,则将FOLLOW(B)加到FOLLOW(A)中;
(解释:右侧非终结符后面没有字符或能推出空字,加左侧非终结符的FOLLOW到后继符集。特别注意:如果遇到 B->
α
\alpha
αAC 这种,而C能推出空字,则加入FOLLOW(B);如果遇到 B->
α
\alpha
αAC |
ϵ
\epsilon
ϵ 这种,C推不出空字,但因为后面有空字,所以既加入FIRST( C )又加入FOLLOW(B)!)
(4)反复使用以上规则, 直至 FOLLOW(A)不再增大为止。
- 例1.
G: E → TE’
E’ → +TE’ │ε
T →FT’
T’ → *FT’ │ε
F →(E)│i
求每个非终结符号的FOLLOW集合
FOLLOW(E)={),#} 起始符加#!
FOLLOW(E’)={),#}
FOLLOW(T)={+,),#}
FOLLOW(T’)={+,),#}
FOLLOW(F)={*,+,),#} - 例2.
文法规则 | FOLLOW(X) |
---|---|
E → E A T | T | {),+,-,#} |
A → + | - | {(,n} |
T → T M F | F | {*,),+,-,#} |
M → * | {(,n} |
F → (E) | n | {*,),+,-,#} |
LL(1)文法
- LL(1)文法需要满足的条件是?
- 文法每一个非终结符A的任何两个不同产生式 A -> α| β,有FIRST(α)∩ FIRST(β) = Φ
- 文法不含左递归
- 文法每一个非终结符A,若A=*=>ε则 FIRST(A)∩ FOLLOW(A) =Φ
- LL(1)分析方法
- 对⼀个LL(1)文法,可以对某个输入串进行有效的无回溯的自上而下分析。
- 设面临的输入符号为a,要用非终结符A进行匹配,且A→α1│α2│… │αn,则可如下分析:
- 若a∈FIRST (αi) ,则指派αi执行匹配任务;
- 否则
- 若ε∈FIRST(A),且a∈FOLLOW (A),则让A与ε自动匹配;
- 否则,a的出现是⼀种语法错误。
递归下降分析程序
- 程序形式
(1)对每⼀个非终结符A,编写⼀个相应的子程序P(A);
(2)对于规则A→α1│α2│…│αn 相应的子程序P(A)构造如下:
IF ch IN FIRST(α1) THEN P(α1)
ELSE IF ch IN FIRST(α2) THEN P(α2)
ELSE ……
ELSE IF ch IN FIRST(αn) THEN P(αn)
ELSE IF (ε∈FIRST(A) )AND (ch IN FOLLOW(A) )
THEN RETURN
ELSE ERROR
例. E→TE’; E’→+TE’ |
ϵ
\epsilon
ϵ ; T→FT’ ; T’ →*FT’ |
ϵ
\epsilon
ϵ ; F→(E)|i
能推出空字的算一下FOLLOW
FOLLOW(E’)={),#}
FOLLOW(T’)={+,),#}
对于E→TE’
P(E)
BEGIN
P(T);P(E');
END;
对于E’→+TE’ | ϵ \epsilon ϵ
P(E');
IF ch="+" THEN
BEGIN
read(ch);P(T);P(E');
END;
ELSE IF (ch=") OR ch="#") THEN
return;
ELSE ERROR;
对于F→(E)|i
P(F);
IF ch="i" THEN read(ch);
ELSE IF ch="(" THEN
BEGIN
read(ch);P(E);
IF ch=")" THEN read(ch);
ELSE ERROR;
END;
ELSE ERROR;
LL(1)分析表
- 若文法有m个非终结符n个终结符,则LL(1)分析表是⼀个(m+1)*(n+2)的矩阵M
- 行标题为文法非终结符
- 列标题为终结符号和输入结束符#
- M[A, a]为⼀条关于A的产生式,指出当A面临a时,应使用的产生式或空格(出错标志)
- 例.
E→TE’; E’→+TE’ | ϵ \epsilon ϵ ; T→FT’ ; T’ →*FT’ | ϵ \epsilon ϵ ;F→(E)|i
首先计算FIRST和FOLLOW
FIRST | FOLLOW | |
---|---|---|
E | {(,i} | {#,)} |
E’ | {+, ϵ \epsilon ϵ} | {#,)} |
T | {(,i} | {+,#,)} |
T’ | {*, ϵ \epsilon ϵ} | {+,#,)} |
F | {(,i} | {*, ϵ \epsilon ϵ} |
i | + | * | ( | ) | # | |
---|---|---|---|---|---|---|
E | E→TE’ | E→TE’ | ||||
E’ | E’→+TE’ | E’→ϵ | E’→ϵ | |||
T | T→FT’ | T→FT’ | ||||
T’ | T’→ϵ | T’ →*FT’ | T’→ϵ | T’→ϵ | ||
F | F→i | F→(E) |
栈
- 栈 STACK存放分析过程中的⽂法符号
- 分析开始时栈底先放⼀个“#”,再压入文法开始符;当分析栈中仅剩“#”且输入串指针指向串尾的“#”时,分析成功。
- 例:
E→TE’; E’→+TE’ | e ;
T→FT’ ; T’ →*FT’ |e ;
F→(E)|i
匹配符号串i + i * i #
栈:
- 结论
- 输出的产生式就是最左推导的产生式。栈中存放产生式右部,等待与a匹配;
- 当栈顶X=a时,分析表指出如何扩充语法树,出错能马上发现。
- 实质:
- 栈:部分句型,句型右部,还未得到推导的符号。
- 表:指出VN按哪⼀条扩充,依赖于VT
分析表构造算法
(1)对每个产生式 A→α,执行(2) 和(3)
(2)若 a∈FIRST(α), 置M[ A, a] =A→α
(3)若ε∈FIRST(A),对b∈FOLLOW(A) 置M[A, b] =A→ε
(4)其余置 M[A, a] =ERROR