若用算法来描述,则预测分析程序的总控程序的算法如下:
BEGIN
首先把‘#’然后把文法开始符号推进STACK栈;
把第一个输入符号读进a;
FLAG:=TRUE;
WHILE FLAG DO
BEGIN
把STACK栈顶符号上托出去并放在X中;
IF X(-Vt THEN
IF X=a THEN把下一个输入符号读进a
ELSE ERROR
ELSE IF X=‘#’ THEN
IF X=a THEN FLAG:=FALSE ELSE ERROR
ELSE IF M[A,a]={X->X1X2…Xk}THEN
把Xk,Xk_1,…,X1一一推进STACK栈
ELSE
ERROR
END OF WHILE;
STOP
END
预测分析表的构造
从前面的讨论中可以看出,预测分析法的实现关键在于预测分析表。预测分析表是指分析栈中的文法符号与输入串中的符号的一种匹配关系记为M[A,a]其中A为分析栈中的符号,a为输入符号。
构造预测分析表算法的基本思想并不复杂。例如,设A->α是一个产生式,a(-FIRST(α)。那么,当A呈现于分析栈栈顶,且a是当前的输入符号时,α应当是A唯一合适的侯选式。因此,M[A,a]中应放进产生式A->α。若α=>ε,而当前面临的输入符号a属于FOLLOW(A),那么,A->α就认为已自动得到匹配,因而,应把A->α放在M[A,a]中。根据这个基本思想,对于给定的LL(1)文法,在求出其各个产生式的可选集之后,可以按照如下的方法构造预测分析表,其构造算法是:
<1>对文法G的每个产生式A->α执行第2步和第3步;
<2>对每个终结符a(-FIRST(α),把A->α加至M[A,a]中;
<3>若ε(-FIRST(α),则对任何b(-FOLLOW(A)把A->α加至M[A,a]中;
<4>把所有无定义的,M[A,a]均填上“出错标志”。
上述算法可用于任何文法G以构造它的分析表M。但对于某些文法,有些M[A,a]中可能有若干个产生式,或者说有些M[A,a]可能是多重定义的。如果G是左递归的或回溯的,那么M至少含有一个多重定义人口。因此,消除左递归和提取公共左因子将有助于获得无多重定义的分析表M。
预测分析方法举例
把上述算法应用于下列文法,可以为该文法构造预测分析表,并且对该文法利用预测分析法进行语法分析。
文法G7[E]:E->E+T|T
T->T*F|F
F->i|(E)
用预测分析法分析的步骤如下:
(1) 判断文法是否为LL(1)文法
由于上述文法中含有左递归,所以必须先消除左递,使文法改写为:
E->TEˊ
Eˊ->+T Eˊ|ε
T->FTˊ
Tˊ->*F Tˊ|ε
F->i|(E)
各非终结符的FIRST集如下:
FIRST(E)={(,i)}
FIRST(Eˊ)={+}
FIRST(T)={(,i}
FIRST(Tˊ)={*}
FIRST(F)={(,i}
各非终结符的FOLLOW集为:
FOLLOW(E)={#,)}
FOLLOW(Eˊ)={#,)}
FOLLOW(T)={+,),#}
FOLLOW(Tˊ)={+,),#}
FOLLOW(F)={*,+,),#}
(2) 根据可选集构造预测分析表
根据构造预测分析表的算法,可得上述文法的预测分析表如图所示:
i
+
*
(
)
#
E
E->T Eˊ
E->T Eˊ
Eˊ
Eˊ->+ T Eˊ
Eˊ->ε
Eˊ->ε
T
T-> FTˊ
T-> FTˊ
Tˊ
Tˊ->ε
Tˊ->*F Tˊ
Tˊ->ε
Tˊ->ε
F
F->i
F->(E)
下面用预测分析法的总控程序、分析栈和预测分析表对输入串i+i*i进行分析,给出输入串T的分析过程如图所示:
步骤
分析栈
(栈顶符号,当前输入符)
剩余输入串
所用产生式
1
#E
(E,i) 查表
i+i*i#
E->TEˊ
2
#EˊT
(T,i) 查表
i+i*i#
T->FTˊ
3
#EˊTˊF
(F,i) 查表
i+i*i#
F->i
4
#EˊTˊi
(i,i) i匹配
i+i*i#
5
#EˊTˊ
(Tˊ,+) 查表
+i*i#
Tˊ->ε
6
#Eˊ
(Eˊ,+) 查表
+i*i#
Eˊ->+T Eˊ
7
# EˊT+
(+,+)+匹配
+i*i#
8
# EˊT
(T,i) 查表
i*i#
T->FTˊ
9
#EˊTˊF
(F,i) 查表
i*i#
F->i
10
#EˊTˊi
(i,i) i匹配
i*i#
11
#EˊTˊ
(Tˊ,*) 查表
*i#
Tˊ->*F Tˊ
12
#EˊTˊF*
(*,*) *匹配
*i#
13
#EˊTˊF
(F,i) 查表
i#
F->i
14
#EˊTˊi
(i,i) i匹配
i#
15
#EˊTˊ
(Tˊ,#) 查表
#
Tˊ->ε