编译原理实验LL1文法的判断及转换.docx
- 文档编号:8274671
- 上传时间:2023-01-30
- 格式:DOCX
- 页数:12
- 大小:66.33KB
编译原理实验LL1文法的判断及转换.docx
《编译原理实验LL1文法的判断及转换.docx》由会员分享,可在线阅读,更多相关《编译原理实验LL1文法的判断及转换.docx(12页珍藏版)》请在冰豆网上搜索。
编译原理实验LL1文法的判断及转换
2016.11.30
LL
(1)文法的判断及转换
一、实验名称
LL
(1)文法的判断及转换
二、实验目的
输入:
任意一个文法
输出:
(1)是否为LL
(1)文法
(2)若是,给出每条产生式的select集
(3)若不是,看看是否含有左公共因子或者含有左递归,并用相应的方法将非LL
(1)文法变成LL
(1)文法,并输出新文法中每条产生式的select集。
三、实验原理
1、First集定义
令X为一个文法符号(终止符或非终止符)或ε,则集合First(X)有终止符组成,此外可能还有ε,它的定义如下:
1. 若X是终止符或ε,则First(X)= {X}。
2. 若X是非终结符,则对于每个产生式X—>X1X2…Xn,First(X)包含了First(X1)-{ε}。
若对于某个i < n,所有的集合First(X1),... ,First(Xi)都包含了ε,则First(X)也包 括了First(Xi+1)- {ε}。
若所有集合First(X1),...,First(Xn)都包括了ε,则First(X)也包括了ε。
2、Follow集定义
给出一个非终结符A,那么集合Follow(A)则是由终结符组成,此外可能还含有#(#是题目约定的字符串结束符)。
集合Follow(A)的定义如下:
1.若A是开始符号,则#在Follow(A)中。
2.若存在产生式B—>αAγ,则First(γ)-{ε}在Follow(A)中。
3.若存在产生式B—>αAγ,且ε在First(γ)中,则Follow(A)包括Follow(B)。
3、Select集定义
对于产生式A—>α。
集合select(A—>α)定义如下:
1.若α不能推出ε,则select(A—>α)=first(α)。
2.若α能推出ε,则select(A—>α)=first(α)∪follow(A)。
4、含左递归文法
一个文法G,若存在P经过一次或多次推导得到Pa(即能推导出以P开头的式子),则称G是左递归的。
左递归分为直接左递归和间接左递归。
直接左递归经过一次推导就可以看出文法存在左递归,如P→Pa|b。
间接左递归侧需多次推导才可以看出文法存在左递归,如文法:
S→Qc|c,Q→Rb|b,R→Sa|a有S=>Qc=>Rbc=>Sabc
四、实验思路
本次实验采用python完成。
1、求非终结符是否能导出空
a.第一轮扫描。
当前的产生式还没被删除,非终结符lp可以导出空,将以该非终结符为左部的产生式标记为要删除的。
产生式右部分解,若该产生式右部包含终结符,删除该产生式因为由它不会导出空。
判断没有被删除的产生式中是否还有以该非终结符为左部的产生式。
b.第二轮扫描。
逐一扫描每一条产生右部的每一个符号,循化直至每个非终结符的状态都确定下来。
2、求First集算法
存储每一个非终结符对应的First集,扫描每一条产生式,记录每一轮扫描是每个非终结符First集是否增大过。
全部初始化为没有增大的状态,对于课本的五种类型依次求解,每次将结果加入对应的集合中,若一次扫描First集没有增大,则说明循环结束。
3、求Follow集算法
存储每一个非终结符对应的Follow集,将'#'加入文法的开始符号的Follow集合中,记录每一轮扫描是每个非终结符Follow集合是否增大过,全部初始化为没有增大的状态,扫描每一条产生式的右部,扫描到非终结符,判断在该非终结符之后的子串能否推导空,若该符号串可以推导出空,还要将Follow(lp)加入到里面。
4、求Select集算法
初始化每条产生式对应的Select集合为空,若产生式右部不能推导出空,则将右部的First集加入Select集,如果可以推出空,则需要同时将左部的Follow集合右部的First集去掉空的部分加入Select集。
五、实验小结
通过本次实验,知道了如何判断一个文法是不是LL
(1)文法,同时对于First、Follow以及Select集的求解原理变得更加熟悉,并且知道了如何用计算机语言求解First,Follow以及Select集。
不足之处是,没有完成判断文法是否为左递归文法以及左递归文法的转换部分。
六、附件
1、源代码
classGw:
def__init__(self):
withopen('Gw.txt')asf:
content=f.readlines()
content=[line.strip()forlineincontent]
self.Vn=content[0].split('')
self.Vt=content[1].split('')
self.start=content[2]
self.produce=[]
self.left=[]
self.right=[]
foriinrange(3,len(content)):
self.produce.append(content[i])
self.left.append(content[i].split('->')[0])
self.right.append(content[i].split('->')[1])
defshowGw(self):
print('非终结符:
',self.Vn)
print('终结符:
',self.Vt)
print('开始符号:
',self.start)
print('产生式如下:
')
forl,rinzip(self.left,self.right):
print(l+'->'+r)
defcanEmpty(self):
self.isEmpty=dict()
foriinrange(len(self.Vn)):
self.isEmpty[self.Vn[i]]=-1
print(self.isEmpty)
temp=self.produce[:
:
]
deleteIndex=[]
pointer=0
whilepointer ifpointernotindeleteIndex: lp=temp[pointer].split('->')[0] rp=temp[pointer].split('->')[1] ifrp=='! ': self.isEmpty[lp]=1 foriinrange(len(temp)): iftemp[i].split('->')[0]==lpandinotindeleteIndex: deleteIndex.append(i) l=list(rp) isContainVt=[iinself.Vtforiinl] ifTrueinisContainVt: deleteIndex.append(pointer) forkinrange(len(temp)): ifknotindeleteIndex: iftemp[k].split('->')[0]==lp: break else: self.isEmpty[lp]=0 pointer=pointer+1 while-1inself.isEmpty.values(): foriinrange(len(temp)): ifinotindeleteIndex: lp=temp[i].split('->')[0] rp=temp[i].split('->')[1] rlsit=list(rp) forjinrange(len(rlsit)): ifself.isEmpty[rlsit[j]]==1: ifj==len(rlsit)-1: self.isEmpty[lp]=1 elifself.isEmpty[rlsit[j]]==0: deleteIndex.append(i) forkinrange(len(temp)): ifknotindeleteIndex: iftemp[k].split('->')[0]==lp: break else: self.isEmpty[lp]=0 else: continue defshow(self): print('非终结符能否推导出空的信息: ') forvinself.Vn: ifself.isEmpty[v]==1: yon='是' else: yon='否' print('%s: %s'%(v,yon)) defgetFirst(self): self.First=dict() foriinself.Vn: self.First[i]=list() isChange=dict() whileTrue: forkinself.Vn: isChange[k]=0 foriinrange(len(self.produce)): lp=self.produce[i].split('->')[0] rp=self.produce[i].split('->')[1] rlist=list(rp) ifrlist[0]=='! 'orrlist[0]inself.Vt: ifrlist[0]notinself.First[lp]: self.First[lp].append(rlist[0]) isChange[lp]=1 else: forjinrlist: ifjinself.Vn: ifself.isEmpty[j]==1: oldsize=len(self.First[lp]) templist=self.First[j][: : ] if'! 'intemplist: templist.remove('! ') forxintemplist: ifxnotinself.First[lp]: self.First[lp].append(x) ifrp.endswith(j)and'! 'notinself.First[lp]: self.First[lp].append('! ') newsize=len(self.First[lp]) ifoldsize! =newsize: isChange[lp]=1 else: oldsize=len(self.First[lp]) ifjinself.Vn: templist=self.First[j][: : ] forxintemplist: ifxnotinself.First[lp]: self.First[lp].append(x) else: ifjnotinself.First[lp]: self.First[lp].append(x) newsize=len(self.First[lp]) ifoldsize! =newsize: isChange[lp]=1 break if1notinisChange.values(): print('First集合不在增大! ') break else: print('First集合有增大! ') pass defshowFirst(self): print('First集合信息: ') forvinself.Vn: print(v,self.First[v]) defcanCauseEmpty(self,plist): first=list() iflen(plist)==0: first.append('! ') else: foriinplist: ifiinself.Vn: ifself.isEmpty[i]==1: t=self.First[i][: : ] if'! 'int: t.remove('! ') forkint: ifknotinfirst: first.append(k) if''.join(plist).endswith(i)and'! 'notinfirst: first.append('! ') else: forkinself.First[i]: ifknotinfirst: first.append(k) break else: ifinotinfirst: first.append(i) break returnfirst defgetFollow(self): self.Follow=dict() foriinself.Vn: self.Follow[i]=list() self.Follow[self.start].append('#') isChange=dict() whileTrue: forkinself.Vn: isChange[k]=0 foriinrange(len(self.produce)): lp=self.produce[i].split('->')[0] rp=self.produce[i].split('->')[1] rlist=list(rp) forjinrange(len(rlist)): ifrlist[j]inself.Vn: reslist=self.canCauseEmpty(rlist[j+1: : ]) if'! 'inreslist: oldsize=len(self.Follow[rlist[j]]) foryinself.Follow[lp]: ifynotinself.Follow[rlist[j]]: self.Follow[rlist[j]].append(y) newsize=len(self.Follow[rlist[j]]) ifoldsize! =newsize: isChange[rlist[j]]=1 else: pass oldsize=len(self.Follow[rlist[j]]) forxinreslist: ifx! ='! 'andxnotinself.Follow[rlist[j]]: self.Follow[rlist[j]].append(x) newsize=len(self.Follow[rlist[j]]) ifoldsize! =newsize: isChange[rlist[j]]=1 if1notinisChange.values(): break defshowFollow(self): print('Follow集合信息: ') forkeyinself.Vn: print(key,self.Follow[key]) defgetSelect(self): self.Select=dict() foriinself.produce: self.Select[i]=list() foriinrange(len(self.produce)): lp=self.produce[i].split('->')[0] rp=self.produce[i].split('->')[1] rlist=list(rp) ifrlist[0]=='! ': forvinself.Follow[lp]: ifvnotinself.Select[self.produce[i]]: self.Select[self.produce[i]].append(v) elifrlist[0]inself.Vt: self.Select[self.produce[i]].append(rlist[0]) else: res=self.canCauseEmpty(rlist) if'! 'notinres: forvinres: ifvnotinself.Select[self.produce[i]]: self.Select[self.produce[i]].append(v) else: forvinres: ifvnotinself.Select[self.produce[i]]andv! ='! ': self.Select[self.produce[i]].append(v) forvinself.Follow[lp]: ifvnotinself.Select[self.produce[i]]: self.Select[self.produce[i]].append(v) defshowSelect(self): print('Select集合信息: ') forkeyinself.produce: print(key,self.Select[key]) defisLLone(self): isright=[] forkinself.Vn: tset=set() tset.add('#') tset=tset|set(self.Vt) forl,rinzip(self.left,self.right): ifk==l: p=l+'->'+r tset=tset&set(self.Select[p]) iflen(tset)==0: isright.append (1) else: isright.append(0) if0inisright: print('不是LL (1)文法! ') self.isll1=False else: print('是LL (1)文法! ') self.isll1=True print(isright) if__name__=='__main__': w=Gw() w.showGw() w.canEmpty() w.show() w.getFirst() w.showFirst() w.getFollow() #res=w.canCauseEmpty(['A','D']) #print('res=',res) w.showFollow() w.getSelect() w.showSelect() w.isLLone() 2、运行结果截图
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 实验 LL1 文法 判断 转换