廢話不多說直接開干!
對文法G的句子進行確定的自頂向下語法分析的充分必要條件是,G的任意兩個具有相同左部的
產生式A—>α|β 滿足下列條件:
(1)如果α、β均不能推導出ε,則 FIRST(α) ∩ FIRST(β) = ∅。
(2)α 和 β 至多有一個能推導出 ε。
(3)如果 β *═> ε,則 FIRST(α) ∩ FOLLOW(A) = ∅。
將滿足上述條件的文法稱為LL(1)文法。
概要
第一個L代表從左向右掃描輸入符號串,第二個L代表產生最左推導,1代表在分析過程中執行每一步推導都要向前查看一個輸入符號——當前正在處理的輸入符號。
LL(1)文法既不是二義性的,也不含左遞歸,對LL(1)文法的所有句子均可進行確定的自頂向下語法分析。
需要注意的是,並不是所有的語言都可以用LL(1)文法來描述,而且不存在判定某語言是否是LL(1)文法的算法。也就是說,確定的自頂向下分析只能實現一部分上下文無關語言的分析,這就是LL(1)文法所產生的語言。另外,在上述LL(1)文法的條件中,要求:ε ∈ FIRST(α1),ε ∈ FIRST(α2),…ε ∈ FIRST(αn) 中至多有一個成立。——————來自百度百科
直接代碼開搞,首先舉個栗子!
處理好之后的文法:
然后經過各種推到最后得到

上面那個分析表
萬事具備,開始制造東風
直接來個代碼
1 import copy 2 3 strs = ['#', 'E'] # 當做棧來使用,棧是先進后出那我就從-1開始 4 list1 = [['E->TE\'', '', '', '', '', 'E->TE\'', '', ''], 5 ['', 'E\'->ATE\'', 'E\'->ATE\'', '', '', '', 'E\'->ε', 'E\'->ε'], 6 ['T->FT\'', '', '', '', '', 'T->FT\'', '', ''], 7 ['', 'T\'->ε', 'T\'->ε', 'T\'->MFT\'', 'T\'->MFT\'', '', 'T\'->ε', 'T\'->ε'], 8 ['F->i', '', '', '', '', 'F->(E)', '', ''], 9 ['', 'A->+', 'A->-', '', '', '', '', ''], 10 ['', '', '', 'M->*', 'M->/', '', '', ''] 11 ] 12 list2 = ['E', 'E\'', 'T', 'T\'', 'F', 'A', 'M'] 13 list3 = ['i', '+', '-', '*', '/', '(', ')', '#'] 14 s1 = '' # 全局變量s1 15 16 17 def out1(): 18 print("分析棧\t\t余留輸入串\t\t分析表中產生式") 19 20 21 def out2(str1, str2, str3, str4): 22 print("%s\t\t%s\t\t%s %s" % (str1, str2, str3, str4)) 23 24 25 str1 = [] 26 str2 = [] 27 str3 = '' 28 str4 = '' 29 s1 = input("請輸入要分析的字符串:") 30 s1 += '#' 31 for i in s1: 32 str2.append(i) 33 out1() 34 35 for i in s1: 36 37 while True: 38 str1 = copy.copy(strs) 39 40 sout = strs.pop() # 取出最后一個元素 41 42 str3 = 'M[' + sout + ',' + i + ']' 43 try: 44 45 num1 = list2.index(sout) 46 num2 = list3.index(i) 47 if list1[num1][num2] != '': 48 schan = list1[num1][num2] 49 if schan[-1] == 'ε': 50 # strs.pop() 51 strs.append(sout) 52 str1 = copy.copy(strs) 53 num1 = list2.index(strs[-1]) 54 num2 = list3.index(i) 55 schan = list1[num1][num2] 56 str4 = schan 57 stop1 = 1 58 sums = '' 59 for j in schan[::-1]: 60 if j == '>': 61 break 62 elif j == '\'': 63 sums += j 64 stop1 = 2 65 else: 66 if stop1 == 1: 67 strs.append(j) 68 else: 69 sums = j + '\'' 70 strs.append(sums) 71 sums = '' 72 stop1 = 1 73 else: 74 str4 = schan 75 stop1 = 1 76 sums = '' 77 for j in schan[::-1]: 78 if j == '>': 79 break 80 elif j == '\'': 81 sums += j 82 stop1 = 2 83 else: 84 if stop1 == 1: 85 strs.append(j) 86 else: 87 sums = j + '\'' 88 89 strs.append(sums) 90 sums = '' 91 stop1 = 1 92 except: 93 if False: 94 str3 = '' 95 str4 = '成功' 96 out2(str1, str2, str3, str4) 97 break 98 else: 99 str3 = 'Pop' 100 str4 = 'Nextsym' 101 strs.pop() 102 if str1[-1] != 'ε': 103 out2(str1, str2, str3, str4) 104 str1.pop() 105 strs = copy.copy(str1) 106 107 break 108 else: 109 str1.pop() 110 str1.pop() 111 strs = copy.copy(str1) 112 if str2[-1] == '#': 113 if str1[-1] == '#': 114 str3 = '' 115 str4 = '成功' 116 out2(str1, str2, str3, str4) 117 break 118 elif str1[-1] != '#': 119 str3 = '' 120 str4 = '失敗' 121 out2(str1, str2, str3, str4) 122 break 123 else: 124 str3 = '' 125 if str4 != 'Nextsym': 126 out2(str1, str2, str3, str4) 127 else: 128 out2(str1, str2, str3, str4) 129 130 str2.pop(0) # 移除第一個元素
運行結果:

輸出格式有需要的朋友可以自行修改一下!
里面使用了淺拷貝,為什么要使用淺拷貝呢?原因就是我使用深拷貝錯了,關於python的深拷貝和淺拷貝,首先來個官方的介紹:

反正我看的不咋明白,來個實例解釋一下吧!開干!!!!
import copy a = ['a','b','c','d'] # 首先我們定義了一個我們用於操作的數組 b = a # 此時進行深拷貝 print("這是a的地址" + str(id(a))) print("這是b的地址" + str(id(b))) print("a的地址是否和b一樣呢?" + str(id(a) == id(b))) c = copy.copy(a) #此時進行淺拷貝 print("這是a的地址" + str(id(a))) print("這是c的地址" + str(id(c))) print("a的地址是否和c一樣呢?" + str(id(a) == id(c))) #然並軟貌似看不出啥東西來,你以為這就結束了?醒醒快開學了 #下面來個我的驗證方法,網上有好多將這個深拷貝和淺拷貝的但是我沒看懂 #進入正題 a.pop()#現在我移除一下a中的最后一個元素 print("a中的元素:"+str(a)) print("深拷貝b中的元素:"+str(b)) print("淺拷貝c中的元素:"+str(c))
運行結果:

網上有些資料說copy方式復制的是淺拷貝,我也沒有去看官方的文檔,所以我從定奪,有資料的小伙伴可以發給我一下。
