python | 編譯原理,語法分析——LR(1)文法實現

LR(1)文法的意思是從左向右掃描,最右推導,往前多看一個字符。
LR(1)文法也需要構造要給預測分析表,但是LR(1)的的預測分析表有兩部分,分別是action表和goto表。

action表的橫座標是不同的狀態標號,縱座標是不同的終結符,goto表的橫座標也是不同狀態標號,縱座標是不同的非終結符。
action表中有si、rj、acc和空白,其中si表示推進至狀態i,將當前輸入符號和狀態i入棧,rj按第j個產生式進行規約,棧首彈出,利用產生式生成,入棧,轉移狀態也同時入棧。acc表示接受,即算法結束。空白表示出錯。
goto表中表示從某個狀態規約後,遇到產生式左邊某個非終結符後轉移到的狀態。
我們以下面這個預測分析表爲例:
(這裏是部分預測分析表)
在這裏插入圖片描述
《編譯原理(第3版)》(陳意雲等編著)這本書裏把用預測分析表進行預測的方法用僞代碼寫了出來,我寫在下方。

令a是w$的第一個符號
while(1){
	令s是棧頂的狀態
	if(action[s,a] == 移進t){
		把a和t依次壓入棧
		令a是下一個輸入符號
	}else if(action[s,a] == 規約 A -> beta){
		棧頂退掉2 *|beta|個符號
		令t是現在的棧頂狀態
		把A和goto[t,A]壓入棧
		輸出產生式A -> beta
	}else if(action[s,a] == 接受)	break;
	else	調用錯誤恢復例程
}

給大家一個表作爲演示。
在這裏插入圖片描述
這裏我是手動生成的預測分析表:

vt = ['id','+','*','(',')','$']
vn = ['E','T','F']

actionData = [['' for i in range(len(vt))] for j in range(12)]
Action = pd.DataFrame(data = actionData,index=range(12),columns=vt)
gotoData = [[-1 for i in range(len(vn))] for j in range(12)] 
Goto = pd.DataFrame(data = gotoData,index=range(12),columns=vn)

Action.loc[0]['id'] = 's 5'
Action.loc[0]['('] = 's 4'
Action.loc[1]['+'] = 's 6'
Action.loc[1]['$'] = 'acc'
Action.loc[2]['+'] = 'r 2'
Action.loc[2]['*'] = 's 7'
Action.loc[2][')'] = 'r 2'
Action.loc[2]['$'] = 'r 2'
Action.loc[3]['+'] = 'r 4'
Action.loc[3]['*'] = 'r 4'
Action.loc[3][')'] = 'r 4'
Action.loc[3]['$'] = 'r 4'
Action.loc[4]['id'] = 's 5'
Action.loc[4]['('] = 's 4'
Action.loc[5]['+'] = 'r 6'
Action.loc[5]['*'] = 'r 6'
Action.loc[5][')'] = 'r 6'
Action.loc[5]['$'] = 'r 6'
Action.loc[6]['id'] = 's 5'
Action.loc[6]['('] = 's 4'
Action.loc[7]['id'] = 's 5'
Action.loc[7]['('] = 's 4'
Action.loc[8]['+'] = 's 6'
Action.loc[8][')'] = 's 11'
Action.loc[9]['+'] = 'r 1'
Action.loc[9]['*'] = 's 7'
Action.loc[9][')'] = 'r 1'
Action.loc[9]['$'] = 'r 1'
Action.loc[10]['+'] = 'r 3'
Action.loc[10]['*'] = 'r 3'
Action.loc[10][')'] = 'r 3'
Action.loc[10]['$'] = 'r 3'
Action.loc[11]['+'] = 'r 5'
Action.loc[11]['*'] = 'r 5'
Action.loc[11][')'] = 'r 5'
Action.loc[11]['$'] = 'r 5'


Goto.loc[0]['E'] = 1
Goto.loc[0]['T'] = 2
Goto.loc[0]['F'] = 3
Goto.loc[4]['E'] = 8
Goto.loc[4]['T'] = 2
Goto.loc[4]['F'] = 3
Goto.loc[6]['T'] = 9
Goto.loc[6]['F'] = 3
Goto.loc[7]['F'] = 10

print(Action)
print(Goto)

在這裏插入圖片描述
LR(1)預測

def getRes(lang):
    V = lang.split(' ')
    V.append('$')
    print('V is ',V)
    sta = Stack()
    sta.push('0')
    i = 0
    a = V[0]
    while True:
        s = int(sta.top())
        curAct = Action[a][s].split(' ')
        if curAct[0] == 's':
            sta.push(a)
            sta.push(str(curAct[1]))
            i = i+1
            a = V[i]
            print('移進')
        elif curAct[0] == 'r':
            curProd = productions[int(curAct[1])-1]
            for j in range(2*(len(curProd)-1)):
                sta.pop()
            t = sta.top()
            A = curProd[0]
            sta.push(A)
            sta.push(str(Goto[A][int(t)]))
            print('輸出 ', ' '.join(curProd),' 規約')
        elif curAct[0] == 'acc':
            print('分析完成')
            break
        else:
            raise error()
        print('棧中爲 ',sta.show())
        print('輸入爲 ',' '.join(V[i:]))
        print()

運行結果爲:

V is  ['id', '*', 'id', '+', 'id', '$']
移進
輸入爲  * id + id $
棧中爲  0 id 5

輸出  F id  規約
輸入爲  * id + id $
棧中爲  0 F 3

輸出  T F  規約
輸入爲  * id + id $
棧中爲  0 T 2

移進
輸入爲  id + id $
棧中爲  0 T 2 * 7

移進
輸入爲  + id $
棧中爲  0 T 2 * 7 id 5

輸出  F id  規約
輸入爲  + id $
棧中爲  0 T 2 * 7 F 10

輸出  T T * F  規約
輸入爲  + id $
棧中爲  0 T 2

輸出  E T  規約
輸入爲  + id $
棧中爲  0 E 1

移進
輸入爲  id $
棧中爲  0 E 1 + 6

移進
輸入爲  $
棧中爲  0 E 1 + 6 id 5

輸出  F id  規約
輸入爲  $
棧中爲  0 E 1 + 6 F 3

輸出  T F  規約
輸入爲  $
棧中爲  0 E 1 + 6 T 9

輸出  E E + T  規約
輸入爲  $
棧中爲  0 E 1

分析完成

完整代碼:

import pandas as pd
sentence = "id * id + id"
# 讀入文法
gramma = open("5_gramma1.txt",'r')

# 把文法中A->B|C 切分爲A->B和A->C
def splitOr(gramma):
    stack = []
    for i in gramma:
        i = i.split(' ')
        ss = i[0]
        j = 1
        while j<len(i):
            if i[j] == "->":
                break
            j+=1
        j+=1
        while j<len(i):
            if i[j][-1] == '\n':
                i[j] = i[j][0:-1]
            if i[j] != '|':
                ss+=" "+i[j]
            else:
                stack.append(ss.split(' '))
                ss = i[0]
            j+=1
        stack.append(ss.split(' '))
    return stack
productions = splitOr(gramma)
print(productions)

vt = ['id','+','*','(',')','$']
vn = ['E','T','F']

actionData = [['' for i in range(len(vt))] for j in range(12)]
Action = pd.DataFrame(data = actionData,index=range(12),columns=vt)
gotoData = [[-1 for i in range(len(vn))] for j in range(12)] 
Goto = pd.DataFrame(data = gotoData,index=range(12),columns=vn)

Action.loc[0]['id'] = 's 5'
Action.loc[0]['('] = 's 4'
Action.loc[1]['+'] = 's 6'
Action.loc[1]['$'] = 'acc'
Action.loc[2]['+'] = 'r 2'
Action.loc[2]['*'] = 's 7'
Action.loc[2][')'] = 'r 2'
Action.loc[2]['$'] = 'r 2'
Action.loc[3]['+'] = 'r 4'
Action.loc[3]['*'] = 'r 4'
Action.loc[3][')'] = 'r 4'
Action.loc[3]['$'] = 'r 4'
Action.loc[4]['id'] = 's 5'
Action.loc[4]['('] = 's 4'
Action.loc[5]['+'] = 'r 6'
Action.loc[5]['*'] = 'r 6'
Action.loc[5][')'] = 'r 6'
Action.loc[5]['$'] = 'r 6'
Action.loc[6]['id'] = 's 5'
Action.loc[6]['('] = 's 4'
Action.loc[7]['id'] = 's 5'
Action.loc[7]['('] = 's 4'
Action.loc[8]['+'] = 's 6'
Action.loc[8][')'] = 's 11'
Action.loc[9]['+'] = 'r 1'
Action.loc[9]['*'] = 's 7'
Action.loc[9][')'] = 'r 1'
Action.loc[9]['$'] = 'r 1'
Action.loc[10]['+'] = 'r 3'
Action.loc[10]['*'] = 'r 3'
Action.loc[10][')'] = 'r 3'
Action.loc[10]['$'] = 'r 3'
Action.loc[11]['+'] = 'r 5'
Action.loc[11]['*'] = 'r 5'
Action.loc[11][')'] = 'r 5'
Action.loc[11]['$'] = 'r 5'


Goto.loc[0]['E'] = 1
Goto.loc[0]['T'] = 2
Goto.loc[0]['F'] = 3
Goto.loc[4]['E'] = 8
Goto.loc[4]['T'] = 2
Goto.loc[4]['F'] = 3
Goto.loc[6]['T'] = 9
Goto.loc[6]['F'] = 3
Goto.loc[7]['F'] = 10

print(Action)
print(Goto)

class Stack(object):
    def __init__(self):
        self.__list = []
    
    def push(self,item):
        self.__list.append(item)

    def pop(self):
        return self.__list.pop()

    def top(self):
        if self.__list:
            return self.__list[-1]
        return None

    def is_empty(self):
        return self.__list == []

    def size(self):
        return len(self.__list)

    def show(self):
        return ' '.join(self.__list)

def getRes(lang):
    V = lang.split(' ')
    V.append('$')
    print('V is ',V)
    sta = Stack()
    sta.push('0')
    i = 0
    a = V[0]
    while True:
        s = int(sta.top())
        curAct = Action[a][s].split(' ')
        if curAct[0] == 's':
            sta.push(a)
            sta.push(str(curAct[1]))
            i = i+1
            a = V[i]
            print('移進')
        elif curAct[0] == 'r':
            curProd = productions[int(curAct[1])-1]
            for j in range(2*(len(curProd)-1)):
                sta.pop()
            t = sta.top()
            A = curProd[0]
            sta.push(A)
            sta.push(str(Goto[A][int(t)]))
            print('輸出 ', ' '.join(curProd),' 規約')
        elif curAct[0] == 'acc':
            print('分析完成')
            break
        else:
            raise error()
        print('棧中爲 ',sta.show())
        print('輸入爲 ',' '.join(V[i:]))
        print()

getRes(sentence)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章