编译原理:语义分析之语法制导的定义的简单实现

语法制导的定义:为每一个产生式编制一个语义子程序。当一个产生式获得匹配时,调用相应的语义子程序实现语义检查和翻译。

  • 可以类比递归下降的预测分析

  • 要求:实现简易计算器

  • 其实只需要在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("---------------------------------------")

输入输出

编译原理:语义分析之语法制导的定义的简单实现_第1张图片
编译原理:语义分析之语法制导的定义的简单实现_第2张图片

  • 实现计算器的另一种方法:用Yacc实现简易计算器

你可能感兴趣的:(编译技术)