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

最近要交實驗報告了,不然這個LL1文法的博客可能還要好久才能想起來補全這個下篇。
前面實現了LL(1)文法的求first集和follow集,也求出來了預測分析表。現在我們的任務就是進行左右一項——利用預測分析表對文法進行預測。
在這裏插入圖片描述
《編譯原理(第3版)》(陳意雲等編著)這本書裏把用預測分析表進行預測的方法用僞代碼寫了出來,我寫在下方。
ip是一個標記輸入讀入的指針,a是ip所指的那個輸入的字符。

讓ip指向w $的第一個符號
令X等於棧頂符號
while(X != $) { /*棧非空*/
	if(X是a) 把X從棧頂彈出並把ip推進到指向的下一個符號
	else if(X是終結符) error()
	else if(M[X,a]是出錯入口) error()
	else if(M[X,a] = X -> Y1 Y2 …… Yk){
		輸出產生式X -> Y1 Y2 …… Yk
		從棧中彈出X
		把Yk Yk-1 …… Y1 依次壓入棧,Y1在棧頂
	}
	令X等於棧頂符號
}

來看一下預測分析器接受輸入爲id * id + id的動作吧,這地方我只給了前面的一部分分析過程,後半部分看明白了這個結構就能直接推了。
在這裏插入圖片描述
按照上面的僞代碼我們就可以用python實現了。
這裏需要使用到棧數據結構,先手動寫一個Stack類吧。(這地方不寫註釋了,也很好看明白)

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)

實現LL(1)文法

def getRes(lang):
    V = lang.split(' ')
    V.append('$')
    l = len(V)
    i = 0
    # 生成初始棧
    sta = Stack()
    sta.push('$')
    sta.push('E')

    X = sta.top()
    while X != '$':
        print('輸入',''.join(V))
        a = V[i]
        if X == a:
            sta.pop()
            i = i+1
            print('匹配',a)
        elif X in vt:
            raise Exception('Errof:the first sign is vt', X)
        elif M[a][X] is []:
            raise Exception('Errof:not found in analysis list', X)
        elif M[a][X][0] in productions:
            prod = M[a][X][0]
            print('輸出',prod)
            sta.pop()
            ll = len(prod)
            for ii in range(ll-1):
                if prod[ll-ii-1] != 'epsilon':
                    sta.push(prod[ll-ii-1])
        X = sta.top()
        print('棧',sta.show())
        print()

查看輸出結果

sentence = "id * id + id"
getRes(sentence)
輸入 id*id+id$
輸出 ['E', 'T', "E'"]
棧 $E'T

輸入 id*id+id$
輸出 ['T', 'F', "T'"]
棧 $E'T'F

輸入 id*id+id$
輸出 ['F', 'id']
棧 $E'T'id

輸入 id*id+id$
匹配 id
棧 $E'T'

輸入 id*id+id$
輸出 ["T'", '*', 'F', "T'"]
棧 $E'T'F*

輸入 id*id+id$
匹配 *
棧 $E'T'F

輸入 id*id+id$
輸出 ['F', 'id']
棧 $E'T'id

輸入 id*id+id$
匹配 id
棧 $E'T'

輸入 id*id+id$
輸出 ["T'", 'epsilon']
棧 $E'

輸入 id*id+id$
輸出 ["E'", '+', 'T', "E'"]
棧 $E'T+

輸入 id*id+id$
匹配 +
棧 $E'T

輸入 id*id+id$
輸出 ['T', 'F', "T'"]
棧 $E'T'F

輸入 id*id+id$
輸出 ['F', 'id']
棧 $E'T'id

輸入 id*id+id$
匹配 id
棧 $E'T'

輸入 id*id+id$
輸出 ["T'", 'epsilon']
棧 $E'

輸入 id*id+id$
輸出 ["E'", 'epsilon']
棧 $

結果和上面的表格展示的一樣,就完成了整個LL(1)文法。

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