-
问题描述:
输入:文法的多个产生式或产生式选项
输出:(1) 产生式中非终结符的First集和Follow集
(2) 判断该文法是否是LL(1)文法
(3) 建立LL(1)文法的分析表
(4) 对输入的符号串进行LL(1)文法分析,并给出分析结果
二、解决思路:
(1)First集的求解:
对G中每个文法符号XÎVT∪VN,构造 FIRST(X)。连续使用下述规则,直至每个FIRST集合不再增大:
a、若XÎ VT,则FIRST(X)={X};
b、若XÎ VN,且有产生式X®a…,则把a加入FIRST(X) ;若X®e也是一条产生式,则把e也加入
c、若X®Y…是一个产生式且YÎ VN,则把FIRST(Y)中的所有非e元素都加入FIRST(X)中;若X®Y1Y2…Yk是一个产生式,Y1,Y2,…,Yi-1都是非终结符,而且,对任意j(1≤j≤i-1),FIRST(Yj)都含有e,则把FIRST(Yi)中的所有非e元素加入FIRST(X)中;特别是,若所有的FIRST(Yj)均含有e,j=1, 2, …,k, 则把e加入FIRST(X)中
(2)Follow集的求解:
对G中每个非终结符A,构造FOLLOW(A)。连续使用下述规则,直至每个FOLLOW不再增大:
a、对文法的开始符号S,置$于FOLLOW(S)中;
b、若A®aBb是一个产生式,则把FIRST(b)\{e}加入FOLLOW(B);
c、若A®aB是一个产生式,或A®aBb是一个产生式而bÞe,则把FOLLOW (A)加入FOLLOW(B)
(3) 构造M[A, a]
a、对文法G的每个产生式A®a,执行第2步和第3步;
b、对每个终结符aÎFIRST(a),把A®a加入M[A, a];
c、若eÎFIRST(a),则对任何bÎFOLLOW(A)把A®a加入M[A,b]中
d、所有无定义的M[A, a]标上“出错标志”。
(4) 文法分析程序的过程:
文法分析表是一个M[A, a]形式的矩阵,A为非终结符,a是终结符或“#” (结束符)。矩阵元素M[A, a]中存放着一条关于A的产生式,指出当A面临输入符号a时所采用的候选,M[A, a]中可能存放着一个“出错标志”,指出A根本不该面临输入符号a。栈STACK存放文法符号,栈底先放一个“#”,然后,放进文法开始符号,同时,假定输入串之后也总有一个“#”,标志输入串的结束。文法分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输入符号a行事的。对于任何(X,a),总控程序每次都执行下面三中可能的动作之一:
a、若X=a=‘#’,则分析成功,并停止分析过程
b、若X=a¹‘#’,则把X从STACK栈顶逐出,让a指向下一个输入符号
c、若X是一个非终结符,则查表M。若M[A,a]中存在产生式,则逐出X,然后把产生式右部符号串反序入栈,同时应做这个产生式相应的语义动作。若M[A,a]中存放出错标志,则调用ERROR。
三、算法的设计与实现
#!/usr/bin/env python
# -*- coding:GBK -*-
NonTermSet = set() #非终结符集合
TermSet = set() #终结符集合
First = dict() #First集
FirstA = dict() #First[a]集
Follow = dict() #Follow集
GramaDict = dict() #处理过的产生式
AnalysisList = dict() #分析表
StartSym = "" #开始符号
Epsilon = "~" #由于没有epsilon符号用“~”代替
EndSym = '#' 结束符号为“#“
#获取First集
def getFirst():
global NonTermSet,TermSet, First, Follow, FirstA
for A in NonTermSet:First[A] = set() #初始化非终结符First集为空
for A in TermSet:First[A] = set(A)#初始化终结符First集为自己
Change = True
while Change: #当First集没有更新则算法结束
Change = False
for A inNonTermSet:
for X inGramaDict[A]:
k = 0
FirstA[X]= set()
Continue= True
whileContinue and k < len(X): #FirstA[X] = FirstA[a]
FirstA[X] |= First[X[k]] - set(Epsilon)
ifnot First[X[k]] - set(Epsilon) <= First[A]:
First[A] |= First[X[k]] - set(Epsilon)
Change = True
ifEpsilon not in First[X[k]]: Continue = False
k +=1
ifContinue == True:
First[A] |= set(Epsilon)
FirstA[X] |= set(Epsilon)
#构造Follow集
def getFollow():
global NonTermSet,TermSet, First, Follow, StartSym
for A in NonTermSet:Follow[A] = set()
Follow[StartSym].add(EndSym) #将结束符号加入Follow[开始符号]中
Change = True
while Change: #当Follow集没有更新算法结束
Change = False
for A inNonTermSet:
for X inGramaDict[A]:
for i inxrange(len(X)):
ifX[i] in TermSet:continue
Flag= True
for jin xrange(i+1, len(X)):
if not First[X[j]] - set(Epsilon) <= Follow[X[i]]:
Follow[X[i]] |= First[X[j]] - set(Epsilon)
Change = True
if Epsilon not in First[X[j]]: Flag = False
ifFlag == True:
if not Follow[A] <= Follow[X[i]]:
Follow[X[i]] |= Follow[A]
Change = True
def columnarDisplay(list, colwidth=17) :
for item in list:
print item + ''*(colwidth - len(item)),
print ''
#构造分析表
def getAnalysisList():
#global NonTermSet,TermSet, First, Follow, StartSym, AnalysisList
for nt in NonTermSet:
AnalysisList[nt]= dict()
row =AnalysisList[nt]
flag = True
for X inGramaDict[nt]:
for a inFirstA[X]:
ifrow.has_key(a):
print'error'
exit(0)
row[a] ="%s"%(X)
if Epsilon inFirstA[X] and flag:
flag =False
for a inFollow[nt]:
ifrow.has_key(a):
print 'error'
exit(0)
row[a] = "%s"%(X)
#分析表达式过程
def Analysis():
#global AnalysisList
sta = []
sta.append(EndSym)
sta.append(StartSym)
ss = raw_input("输入表达式:\n")
head =["Stack","StackTop","Input","Action"]
columnarDisplay(head)
idx = 0
sta_top = sta.pop()
while sta_top !=EndSym and idx < len:
if sta_top ==Epsilon:
sta_top =sta.pop()
elif sta_top inTermSet and ss[idx] == sta_top:
disp =[''.join(sta),sta_top,ss[idx:],"Accept "+sta_top]
columnarDisplay(disp)
idx += 1
sta_top =sta.pop()
elif sta_top inNonTermSet and ss[idx] in TermSet and AnalysisList[sta_top].has_key(ss[idx]):
disp =[''.join(sta),sta_top,ss[idx:],sta_top+"->"+AnalysisList[sta_top][ss[idx]]]
columnarDisplay(disp)
for Xi inAnalysisList[sta_top][ss[idx]][::-1]:
sta.append(Xi)
sta_top =sta.pop()
else:
break
if sta_top == EndSymand ss[idx] == EndSym:
print'Accept'
else:
print 'AnalysisError'
#测试驱动
def preCode():
global NonTermSet,TermSet, First, Follow, StartSym, AnalysisList
n = raw_input("输入规则个数:\n")
n = int(n)
print '输入规则\n'
for i in xrange(n):
A, X =raw_input().split('->')
NonTermSet.add(A)
X = X.split('|')
for Xi in X:TermSet |= set(Xi)
if not GramaDict.has_key(A):
GramaDict[A]= set()
GramaDict[A] |=set(X)
TermSet -= NonTermSet
print 'Nonterminalset:', NonTermSet
print 'Terminalset:', TermSet - set(Epsilon)
StartSym =raw_input("输入开始符号:\n")
getFirst()
getFollow()
print "FIRSTSET"
for k in NonTermSet:
print k, ': ',First[k]
print ''
print "FOLLOWSET"
for k, v inFollow.items():
print k, ': ', v
print ''
getAnalysisList()
TermSet -=set(Epsilon)
TermSet |=set(EndSym)
columnarDisplay(['']+list(TermSet), 10)
for A in NonTermSet:
disp = []
disp.append(A)
for a in TermSet:
ifAnalysisList[A].has_key(a):
disp.append(A+'->'+AnalysisList[A][a])
else :disp.append(" ")
columnarDisplay(disp, 10)
print ''
Analysis()
preCode()