语法分析-LR(1)的python实现[已经得到分析表的情况下]

LR(1):从左分析,从右推导,超前查看一个单词

由于研究了半天为懂表是怎么自动建出来的,连方法都没懂,于是同LL1直接手动建立表了,哈哈哈哈我就是这么菜。

分析表分为action表和goto表,同样为二维表

第一个key为状态(int),第二个key为终结字符(action)/非终结字符(goto)

action的表项为ri或si,ri表示按第i个产生式规约,si表示移进,即把输入符号和i入栈

acc表示完成

goto表项为状态(int)

 

对于给定的文法G,输入流w 和表action、goto

先初始化字符指针ip为0 字符为w[0] ,栈的值为"$"和状态0

进行如下循环:

while 1:

 s为栈顶元素

如果 action[s,a]存在:

       如果第一个字符为s[即为si]:

             a和i入栈

             ip指向下一个字符

             a为ip指向的字符

      如果第一个字符为r[即为ri]:

            表示对第i个产生式进行规约

            栈回退第i个产生式右端(->右)长度的二倍

            t为回退后栈顶元素

            第i个产生式左端A(A->)和goto[t,A]入栈

            输出第i个产生式

不存在:调用错误恢复进程

 

# -*- coding: utf-8 -*-
"""
Created on Wed Jan  2 22:10:19 2019

@author: 71405
"""

#使用已经建立好的分析表
from collections import defaultdict
def addtwodimdict(thedict, key_a, key_b, val): 
    if key_a in thedict:
        thedict[key_a].update({key_b: val})
    else:
        thedict.update({key_a:{key_b: val}})
    
action=dict()
goto=dict()

addtwodimdict(action, 0, 'i', 's5')
addtwodimdict(action, 0, '(', 's4')
addtwodimdict(action, 1, '+', 's6')
addtwodimdict(action, 1, '$', 'acc')
addtwodimdict(action, 2, '+', 'r2')
addtwodimdict(action, 2, '*', 's7')
addtwodimdict(action, 2, ')', 'r2')
addtwodimdict(action, 2, '$', 'r2')
addtwodimdict(action, 3, '+', 'r4')
addtwodimdict(action, 3, '*', 'r4')
addtwodimdict(action, 3, ')', 'r4')
addtwodimdict(action, 3, '$', 'r4')
addtwodimdict(action, 4, 'i', 's5')
addtwodimdict(action, 4, '(', 's4')
addtwodimdict(action, 5, '+', 'r6')
addtwodimdict(action, 5, '*', 'r6')
addtwodimdict(action, 5, ')', 'r6')
addtwodimdict(action, 5, '$', 'r6')
addtwodimdict(action, 6, 'i', 's5')
addtwodimdict(action, 6, '(', 's4')
addtwodimdict(action, 7, 'i', 's5')
addtwodimdict(action, 7, '(', 's4')
addtwodimdict(action, 8, '+', 's6')
addtwodimdict(action, 8, ')', 's11')
addtwodimdict(action, 9, '+', 'r1')
addtwodimdict(action, 9, '*', 's7')
addtwodimdict(action, 9, ')', 'r1')
addtwodimdict(action, 9, '$', 'r1')
addtwodimdict(action, 10, '+', 'r3')
addtwodimdict(action, 10, '*', 'r3')
addtwodimdict(action, 10, ')', 'r3')
addtwodimdict(action, 10, '$', 'r3')
addtwodimdict(action, 11, '+', 'r5')
addtwodimdict(action, 11, '*', 'r5')
addtwodimdict(action, 11, ')', 'r5')
addtwodimdict(action, 11, '$', 'r5')

addtwodimdict(goto, 0, 'E', 1)
addtwodimdict(goto, 0, 'T', 2)
addtwodimdict(goto, 0, 'F', 3)
addtwodimdict(goto, 4, 'E', 8)
addtwodimdict(goto, 4, 'T', 2)
addtwodimdict(goto, 4, 'F', 3)
addtwodimdict(goto, 6, 'T', 9)
addtwodimdict(goto, 6, 'F', 3)
addtwodimdict(goto, 7, 'F', 10)

gramma=open('gram2.txt').readlines()
i=0
while i<len(gramma): #去掉'->'符号
    gramma[i]=gramma[i][0:1]+gramma[i][3:len(gramma[i])-1]
    i+=1

sen='i*i+i$'
ip=0#sen的指针
stack=['$',0]
a=sen[ip]
while True:
    print(stack)
    s=stack[len(stack)-1] #s为栈顶状态
    if  a in action[s]:#存在action[s][a]
        if action[s][a]=='acc': #若为acc 则成功,并结束
            print('ana succeess')
            break
        elif action[s][a][0]=='s':#若为 si 则把a和i依次入栈 a指向下一个
            print('移进'+action[s][a])
            t=int(action[s][a][1])
            stack.append(a)
            stack.append(t)
            ip+=1
            a=sen[ip]
        elif action[s][a][0]=='r':#若为ri i为第i个文法(gramma[i-1]) 则栈回退2*gramma[i-1]表达式表达式右端的长度
            print('规约'+gramma[int(action[s][a][1])-1][0:1]+'->'+gramma[int(action[s][a][1])-1][1:])
            size=len(gramma[int(action[s][a][1])-1])-1 #rj 对应的第j个产生式右端的长度
            j=0
            while j<2*size:
                stack.pop()
                j+=1
            t=stack[len(stack)-1]#t为现在栈的状态
            stack.append(gramma[int(action[s][a][1])-1][0])#表达式左端入栈
            stack.append(goto[t][gramma[int(action[s][a][1])-1][0]])#goto[t,表达式左端]入栈
            print(gramma[int(action[s][a][1])-1])#输出产生式
        else:
            #调用错误恢复例程
            print('error')

文法还是那本书上的(P71),

输入字符流i*i+i

结果如下:

 

博主设置当前文章不允许评论。

没有更多推荐了,返回首页