语法制导的定义:为每一个产生式编制一个语义子程序。当一个产生式获得匹配时,调用相应的语义子程序实现语义检查和翻译。
可以类比递归下降的预测分析
要求:实现简易计算器
其实只需要在LR分析器的基础上作适当修改
#语义分析,计算器
import pandas as pd
data={'id':['s5',' ',' ',' ','s5',' ','s5','s5','s5','s5',' ',' ',' ',' ',' ',' '],
'+':[' ','s6','r3','r6',' ','r8',' ',' ',' ',' ','s6','r1','r2','r4','r5','r7'],
'-':[' ','s7','r3','r6',' ','r8',' ',' ',' ',' ','s7','r1','r2','r4','r5','r7'],
'*':[' ',' ','s8','r6',' ','r8',' ',' ',' ',' ',' ','s8','s8','r4','r5','r7'],
'/':[' ',' ','s9','r6',' ','r8',' ',' ',' ',' ',' ','s9','s9','r4','r5','r7'],
'(':['s4',' ',' ',' ','s4',' ','s4','s4','s4','s4',' ',' ',' ',' ',' ',' '],
')':[' ',' ','r3','r6',' ','r8',' ',' ',' ',' ','s15','r1','r2','r4','r5','r7'],
'$':[' ','acc','r3','r6',' ','r8',' ',' ',' ',' ',' ','r1','r2','r4','r5','r7'],
'E':['1',' ',' ',' ','10',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '],
'T':['2',' ',' ',' ','2',' ','11','12',' ',' ',' ',' ',' ',' ',' ',' '],
'F':['3',' ',' ',' ','3',' ','3','3','13','14',' ',' ',' ',' ',' ',' ']}
SLR=pd.DataFrame(data,index=['0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15'])#SLR分析表
grammer=[' ','E→E+T','E→E-T','E→T','T→T*F','T→T/F','T→F','F→(E)','F→id']#文法的各个产生式
state=[]#符号栈
val=[]#属性栈
zt=['0']#状态栈
point=-1#栈顶指针
equation=[]#算式,用户输入
def handle(t,head):
global SLR
global state
global val
global point
global equation
global zt
if head not in SLR.columns:
print('重新输入')
return 1
action = SLR[head][t]
if action=='acc':
print(val[point])
return 1
else:
if action[0]=='s':#要移进
state.append(equation[0])
val.append(equation[0])
equation=equation[1:]
point=point+1
zt.append(action[1:])
#print(zt,'\t',state,'\t',val,'\t',equation)
return 0
elif action[0]=='r':#要归约
num=int(action[1:])#根据要归约的产生式序号
subroutine(num)#调用对应的语义子程序
production = grammer[int(action[1:])]
lenth = rightlenth(production)
zt=zt[:-lenth]
zt.append(SLR[state[point]][zt[-1]])
#print(zt, '\t', state, '\t', val, '\t', equation)
else:#出错
print('重新输入')
return 1
return -1
def subroutine(i):#调用语义子程序
if i==1:
Eplus()
elif i==2:
Eminus()
elif i==3:
E()
elif i==4:
Tmul()
elif i==5:
Tdiv()
elif i==6:
T()
elif i==7:
Fk()
else:
F()
def Eplus():#产生式E→E+T的语义子程序
global val
global point
global state
val[point-2]=str(eval(val[point-2])+eval(val[point]))
point=point-2
val=val[:point+1]
state=state[:point+1]
def Eminus():#产生式E→E-T的语义子程序
global val
global point
global state
val[point-2]=str(eval(val[point-2])-eval(val[point]))
point=point-2
val = val[:point + 1]
state = state[:point + 1]
def E():#产生式E→T的语义子程序
global state
global point
state[point]='E'
def Tmul():#产生式T→T*F的语义子程序
global val
global point
global state
val[point-2]=str(eval(val[point-2])*eval(val[point]))
point=point-2
val = val[:point + 1]
state = state[:point + 1]
def Tdiv():#产生式T→T/F的语义子程序
global val
global point
global state
val[point-2]=str(eval(val[point-2])/eval(val[point]))
point=point-2
val = val[:point + 1]
state = state[:point + 1]
def T():#产生式T→F的语义子程序
global state
global point
state[point]='T'
def Fk():#产生式F→(E)的语义子程序
global val
global state
global point
val[point-2]=val[point-1]
state[point-2]='F'
point=point-2
val = val[:point + 1]
state = state[:point + 1]
def F():#产生式F→id的语义子程序
global state
global point
state[point]='F'
def trans(s):#把输入的算式分割成若干个记号,并保存到到一个列表中
s+='$'
lst=[]
i=0
while True:
if s[i].isdigit()==True:
pass
else:
if i!=0:
lst.append(s[:i])
s=s[i:]
else:
lst.append(s[0])
s=s[1:]
i=-1
i+=1
if len(s)<2:
break
lst.append('$')
return lst
def rightlenth(s):#计算产生式→右边的长度
index=s.find('→')
ss=s[index+1:]
if ss=='id':
return 1
else:
return len(ss)
if __name__=='__main__':#【注】输入时不考虑负数,浮点数,科学计数法;不考虑其他未提及的终结符,否则计算错误或报错
print("---------------------------------------")
inputString=input()#输入算式
equation=trans(inputString)#将算式分成若干个记号
print("---------------------------------------")
#print('zt', '\t', 'state', '\t', 'val', '\t', 'equation')
#print(zt, '\t', state, '\t', val, '\t', equation)
while(True):
if equation[0].isdigit()==True:
co='id'
else:
co=equation[0]
if(handle(zt[-1],co)==1):
break
print("---------------------------------------")