-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathLR1.py
More file actions
241 lines (221 loc) · 7.01 KB
/
Copy pathLR1.py
File metadata and controls
241 lines (221 loc) · 7.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
'''
自底向上 分析器
'''
import copy
from utils import getFirst, getFirstSet
from extract_word import parseString
def get_FirstSet_full(grammar, first, sigs):
'''
:param first:
:param sigs:
:return:
'''
rr = []
for s in sigs:
if not s[0].isupper():
rr.append(s)
break
fs = getFirstSet(grammar, first, s)[0]
rr += fs
if 'none' not in fs:
break
else:
rr.remove('none')
return list(set(rr))
def closeure(I: list, Gramar: list):
'''
计算制定项目集的闭包
:param I: 给定项目集 [[('X',['E'->'A'], a)], ...]
:param Gramar: 给定文法
:return: 返回项目集闭包
'''
J = I[:] #deep copy
first = getFirst(Gramar)
while True:
fg = False
for l, r, c in J:
idx = list(r).index('.')
if idx < len(r) - 1 and r[idx+1][0].isupper(): # A -> * . B * 形式
for lg, rg in Gramar:
fs = get_FirstSet_full(Gramar, first, r[idx+2:]+[c]) # 求First(后面的* 后接着c)
for b in fs:
if lg == r[idx+1] and (lg, ['.']+rg, b) not in J:
fg = True
J.append((lg, ['.']+rg, b))
if not fg:
break
return J
def moveDot(item: tuple, step = 1):
'''
点往后移动step格, 默认一格
:param item: 项目集的一个元素 Turple
:param step:
:return:
'''
copy_item = copy.deepcopy(item)
l, r, c = copy_item
idx = r.index('.')
if idx < len(r) - step:
r.remove('.')
r.insert(idx+1, '.')
return (l, r, c)
else:
print('不能向后移动{} 格!'.format(step))
def get_full_sig(grammar: list):
'''
获取文法中所有符号
:param grammar: 文法 list
:return: 文法中所有非终结符和终结符
'''
l_sigs = [l for l ,r in grammar] # 文法左侧所有符号
r_sigs = [] # 文法右侧所有符号
for _, rs in grammar:
for rr in rs:
r_sigs.append(rr)
res = list(set(l_sigs + r_sigs))
return res
def goto(I: list, X: str, Grammar: list):
'''
计算项目集I 经过X 的后继闭包
:param I: 给定项目集
:param X: 给定的后继符号
:param Grammar: 给定文法
:return: 返回一个后继项目集闭包
'''
J = []
II = copy.deepcopy(I)
for l, r, c in II:
# print(l,r,c)
idx = r.index('.')
if idx < len(r) - 1 and r[idx+1] == X: # 找到 A —> * . X *
# print('移动原点', l, r)
t = moveDot((l, r, c))
J.append(t)
return closeure(J, Grammar)
def createItems(grammar: list):
'''
构建LR(1) 自动机的状态集族
:param grammar: 注意是增广文法, 开始符只存在一个产生式的左部。
:return:
'''
#获取开始符号
temp_g = copy.deepcopy(grammar[0])
l, r = temp_g
r = ['.'] + r
temp = closeure([(l, r, '#')], grammar)
# temp.append('none')
C = [temp]
Xs = get_full_sig(grammar)
# print(Xs)
while True:
fg = False
# print(len(C))
for item in C:
for l in Xs:
# item_= item[0:-1] # 去除最后一个元素吗最后一个元素代表着
goto_temp = goto(item, l, grammar)
# print(l, goto_temp )
# goto_temp.append(l)
# print(goto_temp)
if goto_temp and goto_temp not in C:
fg = True
C.append(goto_temp)
if not fg:
break
return C
def get_index_of_grammar(grammar: list, v):
'''
根据 v 返回v在grammar中的序号
:param gammar:
:param v:
:return:
'''
# print('GGGGGG', v)
vv = copy.deepcopy(v)
l, r = vv
if '.' in r:
r.remove('.')
if vv in grammar:
return grammar.index(vv)
def createLR_sheeet(items, grammar: list):
'''
构造LR(1)分析表
:param items: LR(1)项集族
:param grammar:
:return:
'''
sheet ={}
Vt = get_full_sig(grammar) # 文法所有终结符
Vt = [v for v in Vt if not v[0].isupper()]
Vt.append('#')
copy_items = copy.deepcopy(items)
for i, item in enumerate(items):
item_ = copy.deepcopy(item)
for l, r, c in item:
for idx in range(len(r) - 1):
if r[idx] == '.':
gt = goto(item_, r[idx + 1], grammar)
if not r[idx+1][0].isupper() and gt in items: # 形如 A—>* .a *
j = items.index(gt)
sheet[str(i)+'->' + r[idx+1]] = 's'+str(j)
elif r[idx+1][0].isupper() and gt in items: # # 形如 A—>* .B *
j = items.index(gt)
sheet[str(i) + '->' + r[idx + 1]] = str(j)
if r[-1] == '.': # 形如 A->* .
if l == 'S_':
sheet[str(i) + '->' + '#'] = 'acc'
else:
# print(l,r)
j = get_index_of_grammar(grammar, (l, r)) # 找到规约式在原文法的位置
# if not j:
# print('yyyy', l,r)
sheet[str(i) + '->' + str(c)] = 'r' + str(j)
return sheet
def LR1_analyse(sheet: dict, grammar, s: str):
'''
:param sheet: 创建好的LR1分析表
:param s: 待分析字符串
:return:
'''
token, errors = parseString(s+'#')
# 如果有词法错误
if errors:
print('词法错误!')
for e in errors:
print(e)
return
# 定义状态栈, 符号栈
State = ['0']
sigs = ['#']
idx = 0 # token 指针
while State and idx < len(token):
current_state = State[-1]
key = current_state+'->'+ token[idx][0]
if key in sheet: #没有错误时
value = sheet[key]
if value[0] == 's':
State.append(value[1:])
idx += 1
elif value[0] == 'r':
# print(value)
l,r = grammar[int(value[1:])]
len_ = len(r)
# len个元素同时出栈
# print(State)
State = State[: -len_]
# print(State)
# l 符号查表 进栈
key = State[-1]+'->'+l
if key in sheet:
value = sheet[key]
State.append(value)
else:
print('出错')
elif value == 'acc':
print('接受成功')
break
else:
print('出错!!')
else:
print('出错!!')
break