要求
代码
#语法分析,LR分析器
import pandas as pd
data={'id':['s5',' ',' ',' ','s5',' ','s5','s5',' ',' ',' ',' '],
'+':[' ','s6','r2','r4',' ','r6',' ',' ','s6','r1','r3','r5'],
'*':[' ',' ','s7','r4',' ','r6',' ',' ',' ','s7','r3','r5'],
'(':['s4',' ',' ',' ','s4',' ','s4','s4',' ',' ',' ',' ',],
')':[' ',' ','r2','r4',' ','r6',' ',' ','s11','r1','r3','r5'],
'$':[' ','acc','r2','r4',' ','r6',' ',' ',' ','r1','r3','r5'],
'E':['1',' ',' ',' ','8',' ',' ',' ',' ',' ',' ',' '],
'T':['2',' ',' ',' ','2',' ','9',' ',' ',' ',' ',' ',],
'F':['3',' ',' ',' ','3',' ','3','10',' ',' ',' ',' ']}
SLR=pd.DataFrame(data,index=['0','1','2','3','4','5','6','7','8','9','10','11'])#SLR分析表
grammer=[' ','E→E+T','E→T','T→T*F','T→F','F→(E)','F→id']#文法的各个产生式
stk='0'#用字符串模拟栈
sub="" #当前待处理记号被处理后的输入
def nextToken():#获取下一个词法记号
global sub
if(sub[0:2]=="id"):
sub=sub[2:]
return "id"
else:
s=sub[0:1]
sub=sub[1:]
return s
def showNextToken():#查看下一个词法记号
global sub
if (sub[0:2] == "id"):
return "id"
else:
s = sub[0:1]
return s
def top():#获取栈顶元素
global stk
if(stk[-2:]=='10'or stk[-2:]=='id' or stk[-2:]=='11'):
return stk[-2:]
else:
return stk[-1:]
def pop():#弹出栈顶元素
global stk
if(stk[-2:]=='id'or stk[-2:]=='10'or stk[-2:]=='11'):
stk=stk[:-2];
else:
stk=stk[:-1]
def push(s):#产生式→右边的逆序入栈
global stk
stk=stk+s
def rightlenth(s):#计算产生式→右边的长度
index=s.find('→')
ss=s[index+1:]
if ss=='id':
return 1
else:
return len(s[index+1:])
def leftPro(s):#计算产生式→左边的非终结符
index = s.find('→')
return s[:index]
def handle(t,head):#分析程序
global SLR
global stk
action=SLR[head][t]
#print("head=",head,'t=',t,"action=",action,end=" ")
if action=='acc':
print("%-10s"%stk,"%+9s"%sub,' 接受')
return True
else:
if action[0]=='s':#要移进
print("%-10s"%stk,"%+9s"%sub," 移进")
push(nextToken())
push(action[1:])
elif action[0]=='r':#要归约
production=grammer[ord(action[1:])-ord('0')]
print("%-10s"%stk,"%+9s"%sub," 按",production,"归约")
lenth=rightlenth(production)
for i in range(lenth*2):
pop()
t=top()
left=leftPro(production)
push(left)
push(SLR[left][t])
else:#出错
print("%-10s"%stk,"%+9s"%sub,end='')
print(" error",end=', ')
print('多输入了一个',head)
head=nextToken()
return False
if __name__=='__main__':
print("---------------------------------------")
sub=input()
sub+='$'
print("---------------------------------------")
print("%-8s"%"栈","%+8s"%"输入"," 动作")
while(True):
b=handle(top(),showNextToken())
if b==True:
break
print("---------------------------------------")
输入输出
- 有一定的错误处理功能,可以试试输入 idid+id 或者id**id
- 附:用Yacc实现简易计算器