一、實驗目的
利用C語言編制遞歸下降分析程序,並對簡單語言進行語法分析。
編制一個遞歸下降分析程序,實現對詞法分析程序所提供的單詞序列的語法檢查和結構分析。
二、實驗原理
每個非終結符都對應一個子程序。
該子程序根據下一個輸入符號(SELECT集)來確定按照哪一個產生式進行處理,再根據該產生式的右端:
- 每遇到一個終結符,則判斷當前讀入的單詞是否與該終結符相匹配,若匹配,再讀取下一個單詞繼續分析;不匹配,則進行出錯處理
- 每遇到一個非終結符,則調用相應的子程序
三、實驗要求說明
輸入單詞串,以“#”結束,如果是文法正確的句子,則輸出成功信息,打印“success”,否則輸出“error”,並指出語法錯誤的類型及位置。
例如:
輸入begin a:=9;b:=2;c:=a+b;b:=a+c end #
輸出success
輸入a:=9;b:=2;c:=a+b;b:=a+c end #
輸出‘end' error
四、實驗步驟
1.待分析的語言的語法(參考P90)
2.將其改為文法表示,至少包含
–語句
–條件
–表達式
E -> E+T | T T -> T*F | F F -> (E) | i
3. 消除其左遞歸
E -> TE' E' -> +TE' | ε T -> FT' T' -> *FT' | ε F -> (E) | i
4. 提取公共左因子
5. SELECT集計算
SELECT(E->TE) =FIRST(TE')=FIRSI(T)-FIRST(F)U{*}={(, i, *} SELECT(E'->+TE')=FIRST(+TE')={+} SELECT(E'->ε)=follow(E')=follow(E)={#, )} SELECT(T -> FT')=FRIST(FT')=FIRST(F)={(, i} SELECT(T'->*FT')=FRIST(*FT')={*} SELECT(T'->ε)=follow(T')=follow(T)={#, ), +} SELECT(F->(E))=FRIST((E)) ={(} SELECT(F->i)=FRIST(i) ={i}
6. LL(1)文法判斷
其中SELECT(E'->+TE')與SELECT(E'->ε)互不相交,SELECT(T'->*FT')與SELECT(T'->ε)互不相交,SELECT(F->(E))與SELECT(F->i)互不相交,故原文法為LL(1)文法。
7. 遞歸下降分析程序
1 ''' 2 by Rakers 3 ''' 4 5 import re 6 7 types = {'begin':1, 8 'if':2, 9 'then':3, 10 'while':4, 11 'do':5, 12 'end':6, 13 'l(l|d)*':10, 14 'dd*':11, 15 '+':13, 16 '-':14, 17 '*':15, 18 '/':16, 19 ':':17, 20 ':=':18, 21 '<':20, 22 '<=':21, 23 '<>':22, 24 '>':23, 25 '>=':24, 26 '=':25, 27 ';':26, 28 '(':27, 29 ')':28, 30 '#':0, 31 'i':-1 32 } 33 34 # 當前讀到的字符 35 syn = '' 36 synIndex = 0 37 38 # 所有字符 39 syns = [] 40 41 kk = 0 42 43 # 語法分析方法 44 def syntaxAnalysis(strs): 45 strs += ' ' # 補位 46 syns = [] 47 index = 0 48 while index < len(strs): 49 for key in types.keys(): 50 if index+len(key) < len(strs): 51 if strs[index:index+len(key)] == key: 52 53 if re.match('^[<>:]$', strs[index]) and strs[index+1] == '=': 54 key = strs[index:index+2] 55 ss = strs[index:index+len(key)] 56 # print((ss, types.get(ss))) 57 syns.append({ss:types.get(ss)}) 58 index += len(key)-1 59 break 60 elif re.match('^[a-zA-Z0-9_]+', strs[index:]): 61 ss = re.match('^([a-zA-Z0-9_]+)', strs[index:]).group() 62 if not types.get(ss): 63 if re.match('[a-zA-Z]+', ss): 64 # print((ss, 10)) 65 syns.append({ss: 10}) 66 elif re.match('\\d+', ss): 67 # print((ss, 11)) 68 syns.append({ss: 11}) 69 else: 70 print((ss, '其他')) 71 else: 72 # print((ss, types.get(ss))) 73 syns.append({ss:types.get(ss)}) 74 index += len(ss) 75 # index += len(strs[index:strs.find(ss, index)]) 76 index += 1 77 return syns 78 79 80 def scaner(): 81 global syn, synIndex 82 syn = syns[synIndex][list(syns[synIndex].keys())[0]] 83 synIndex += 1 84 85 86 def lrparser(): 87 global kk 88 if syn == types['begin']: 89 scaner() 90 yucu() 91 92 if syn == types['end']: 93 scaner() 94 if syn == types['#'] and kk == 0: 95 print("語句語法正確!!!") 96 else: 97 if kk != 1: 98 print("發生錯誤! 缺少end") 99 kk = 1 100 else: 101 print("發生錯誤! 缺少begin") 102 kk = 1 103 return 104 105 106 def yucu(): 107 statement() 108 while syn == types[';']: 109 scaner() 110 statement() 111 return 112 113 114 def statement(): 115 global kk 116 if syn == types['l(l|d)*']: 117 scaner() 118 if syn == types[':=']: 119 scaner() 120 expression() 121 else: 122 print(":=error!") 123 kk = 1 124 else: 125 print("l(l|d)*error!") 126 kk = 1 127 return 128 129 130 def expression(): 131 term() 132 while syn == types['+'] or syn == types['-']: 133 scaner() 134 term() 135 return 136 137 138 def term(): 139 factor() 140 while syn == types['*'] or syn == types['/']: 141 scaner() 142 factor() 143 return 144 145 146 def factor(): 147 global kk 148 if syn == types['l(l|d)*'] or syn == types['dd*']: 149 scaner() 150 elif syn == types['(']: 151 scaner() 152 expression() 153 if syn == types[')']: 154 scaner() 155 else: 156 print("語法錯誤, 缺少')'") 157 kk = 1 158 else: 159 print("表達式錯誤") 160 kk = 1 161 return 162 163 164 if __name__ == '__main__': 165 print('-'*30, 'Rakers語法分析程序', '-'*30) 166 strs = input('請輸入待分析語句:') 167 syns = syntaxAnalysis(strs) 168 scaner() 169 lrparser()
Rakers 版權所有,侵權必告