文法如下
0 S' -> S
1 S -> G
2 S -> A
3 G -> D;
4 D -> int id
5 D -> float id
6 D -> char id
7 D -> D, id
8 A -> id=E;
9 E -> E + T
10 E ->E - T
11 E -> T
12 T -> T * F
13 T -> T / F
14 T -> T % F
15 T -> F
16 F -> (E)
17 F -> id
[code=Python]
#!/usr/bin/env python
VN = ('s', 'S', 'G', 'A', 'D', 'E', 'T', 'F')VT = (',', ';', 'int', 'float', 'char', 'id', '=', '+', '-', '*', '/' ,'%', '(', ')', '#')
generators = (
('s', 'S', 2),('S', 'G', 2), ('S', 'A', 2), ('G', 'D', ';', 3),
('D', 'int', 'id', 3), ('D', 'float', 'id', 3), ('D', 'char', 'id', 3), ('D', 'D', ',', 'id', 4),
('A', 'id', '=', 'E', ';', 5), ('E', 'E', '+', 'T', 4), ('E', 'E', '-', 'T', 4), ('E', 'T', 2), ('T', 'T', '*', 'F', 4),
('T', 'T', '/', 'F', 4), ('T', 'T', '%', 'F', 4), ('T', 'F', 2), ('F','(', 'E', ')', 4), ('F', 'id', 2))
'''
如何生成FIRST,FOLLOW SET
'''
first = { vn:set() for vn in VN}
follow = { vn:set() for vn in VN}
[first[i].add(j[1]) for i in VN for j in generators if j[0] == i and j[1] not in VN]
#print(follow)
'''
first set, the dict, which VN, the VN list
'''
#构造FIRST SET
#print(first)
#第一步获取只有终结符的产生式的符号
NOVT = []
for i in first:
if len(first[i]) == 0:
continue
for j in VN:
if j in first[i]:
break
else :
NOVT.append([i])
#print(NOVT)
#第二步填充NOVT
for j in NOVT:
for k in j:
for i in generators:
if i[1] == k and i[0] not in j:
j.append(i[0])
#print(NOVT)
for i in NOVT:
for j in range(1, len(i)):
first[i[j]] |= first[i[j-1]]
#print(first)
[follow[j[k]].add(j[k+1]) for j in generators for k in range(1, len(j)-1) if j[k] in VN and j[k+1] in VT]
follow['s'].add('#')
for i in generators :
for j in range(1,len(i) - 2):
if i[j] in VN and i[j+1] in VN:
follow[i[j]] |= first[i[j + 1]]
#构造FOLLOW SET
#第一步获取关系表
relation = {i[0]:set() for i in generators if i[-2] in VN}
for i in generators:
if i[-2] in VN:
relation[i[0]].add(i[-2])
#print(relation)
#第二步生成FOLLOWSET
for i in relation:
for j in relation[i]:
follow[j] |= follow[i]
#print(follow)
#(a, b) means a how many chars has passed , and b means generators[b][a]
analyze_table = [[[],(1, 0)]]
for i in analyze_table:
d = {}
for j in i:
if j is i[0]:
continue
if j[0] >= generators[j[1]][-1] :
continue
tmp = generators[j[1]]
for k in generators:
if k[0] == tmp[j[0]] and k is not tmp and (1, generators.index(k)) not in i :
#print('k =', k, 'tmp', tmp)
i.append((1, generators.index(k)))
#else :
#because all the same VN are all negolate each other
#break
if generators[j[1]][j[0]] not in d:
tmp1 = [n[1] for n in analyze_table]
tmp2 = (j[0] + 1, j[1])
tmp3 = [[],tmp2]
if tmp2 not in tmp1:
analyze_table.append(tmp3)
tmp1 = [n[1] for n in analyze_table]
i[0].append(tmp1.index(tmp2))
else :
i[0].append(tmp1.index(tmp2))
d[generators[j[1]][j[0]]] = tmp1.index(tmp2)
elif generators[j[1]][-1] > j[0]:
tmp2 = (j[0] + 1, j[1])
if tmp2 not in analyze_table[d[generators[j[1]][j[0]]]]:
analyze_table[d[generators[j[1]][j[0]]]].append(tmp2)
i[0].append(d[generators[j[1]][j[0]]])
action = {i:[ 0 for j in range(0, len(analyze_table))] for i in VT}
goto = {i:[-1 for j in range(0, len(analyze_table))] for i in VN}
for i in range(0, len(analyze_table)) :
map = analyze_table[i][0]
for j in analyze_table[i][1:]:
#可归约项目
if j[0] == generators[j[1]][-1] :
#对任何终结符或'#'用产生式进行归约
if j[1] == 0 and j[0] == generators[0][-1] :
action['#'][i] = 'acc'
else :
for key in action:
if key in follow[generators[j[1]][0]]:
action[key][i] = -1 * j[1];
elif generators[j[1]][j[0]] in VT:
#移进项目
action[generators[j[1]][j[0]]][i] = map[0]
map = map[1:]
else :
goto[generators[j[1]][j[0]]][i] = map[0]
map = map[1:]
print(' ',end='')
[print('%5s' % i, end=' ') for i in VT]
print()
for i in range(len(analyze_table)) :
print('%2s' % i, end='')
for j in VT:
print('%5s' % action[j][i], end = ' ')
print()
//生成Qt下的定义语句
f = open("action.txt", "w")
f.write('QStringList ')
for i in range(0, len(analyze_table)):
f.write('a' + str(i) + ',')
f.write(';\n')
for i in range(0, len(analyze_table)) :
f.write('a' + str(i) + '<<')
for key in VT[:-1] :
f.write('"' + str(action[key][i]) + '"<<')
f.write('"' + str(action[VT[-1]][i]) + '";\n')
for i in range(0, len(analyze_table)) :
f.write('analyze_table->append(a' + str(i) + ');\n')
f.close()
f = open('goto.txt','w')
f.write('QStringList ')
for i in range(0, len(analyze_table)) :
f.write('g' + str(i) + ',')
f.write(';\n')
for i in range(0, len(analyze_table)) :
f.write('g' + str(i) + '<<')
for key in VN[:-1] :
f.write('"' + str(goto[key][i]) + '"<<')
f.write('"' + str(goto[VN[-1]][i]) + '";\n')
for i in range(0, len(analyze_table)) :
f.write('goto_table->append(g' + str(i) + ');\n')
f.close()
f = open("syntax.txt",'w')
f.write('QStringList ')
for i in range(0, len(generators)):
f.write('s' + str(i) + ',')
f.write(';')
for i in range(len(generators)):
f.write('s' + str(i) + '<<');
for j in generators[i][:-2]:
f.write('"' + j + '"<<')
f.write('"' + generators[i][-2] + '";\n')
for i in range(len(generators)) :
f.write('syntax->append(s' + str(i) + ');\n')
f.close()
[/code]
这个也只是生成了一个初步的分析表,错误处理没有用程序实现,而是手工实现,分析后的结果如下
e0 -- empty def
e1 -- extra
e2 -- missing this line
e3 -- missing ;
e4 -- missing ,
e5 -- missing
e6 -- missing id
e7 -- redefine
e8 -- not define sentence, replace int or float or char to id
e9 -- illageal end of define replace , with ;
e10 -- missing operator or ; must look back two chars
e11 -- illeageal operator change * / % to + -
e12 --missing operator
, ; int float char id = + - * / % ( ) #
0 e1 e1 6 7 8 5 e1 e1 e1 e1 e1 e1 e1 e1 e0
1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 acc
2 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 -1
3 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 -2
4 10 9 e3 e3 e3 e4 e1 e1 e1 e1 e1 e1 e1 e1 e3
5 e5 e1 e1 e1 e1 e1 11 e1 e1 e1 e1 e1 e1 e1 e0
6 e6 e6 e7 e7 e7 12 e8 e1 e1 e1 e1 e1 e1 e1 e0
7 e6 e6 e7 e7 e7 13 e8 e1 e1 e1 e1 e1 e1 e1 e0
8 e6 e6 e7 e7 e7 14 e8 e1 e1 e1 e1 e1 e1 e1 e0
9 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 -3
10 e1 e1 e1 e1 e1 15 e1 e1 e1 e1 e1 e1 e1 e1 e9
11 e1 e6 e1 e1 e1 20 e1 e6 e6 e6 e6 e6 19 e1 e6
12 -4 -4 e3 e3 e3 e4 e1 e1 e1 e1 e1 e1 e1 e1 e3
13 -5 -5 e3 e3 e3 e4 e1 e1 e1 e1 e1 e1 e1 e1 e3
14 -6 -6 e3 e3 e3 e4 e1 e1 e1 e1 e1 e1 e1 e1 e3
15 -7 -7 e3 e3 e3 e4 e1 e1 e1 e1 e1 e1 e1 e1 e3
16 e1 21 e1 e1 e1 e10 e1 22 23 e11 e11 e11 e1 e1 e3
17 e1 -11 e1 e1 e1 e3 e1 -11 -11 24 25 26 e1 -11 e3
18 e1 -15 e1 e1 e1 e3 e1 -15 -15 -15 -15 -15 e1 -15 e3
19 e1 e6 e1 e1 e1 20 e1 e6 e6 e6 e6 e6 19 e1 e6
20 e1 -17 e1 e1 e1 e1 e1 -17 -17 -17 -17 -17 e1 -17 e6
21 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 -8
22 e1 e6 e1 e1 e1 20 e1 e6 e6 e6 e6 e6 19 e1 e6
23 e1 e6 e1 e1 e1 20 e1 e6 e6 e6 e6 e6 19 e1 e6
24 e1 e6 e1 e1 e1 20 e1 e6 e6 e6 e6 e6 19 e1 e6
25 e1 e6 e1 e1 e1 20 e1 e6 e6 e6 e6 e6 19 e1 e6
26 e1 e6 e1 e1 e1 20 e1 e6 e6 e6 e6 e6 19 e1 e6
27 e1 e12 e1 e1 e1 e12 e1 22 23 e11 e11 e11 e12 33 e12
28 e1 -9 e1 e1 e1 e12 e1 -9 -9 24 25 26 e12 -9 e12
29 e1 -10 e1 e1 e1 e12 e1 -10 -10 24 25 26 e12 -10 e12
30 e1 -12 e1 e1 e1 e6 e1 -12 -12 -12 -12 -12 e12 -12 e6
31 e1 -13 e1 e1 e1 e6 e1 -13 -13 -13 -13 -13 e12 -13 e6
32 e1 -14 e1 e1 e1 e6 e1 -14 -14 -14 -14 -14 e12 -14 e6
33 e1 -16 e1 e1 e1 e6 e1 -16 -16 -16 -16 -16 e12 -16 e6
较好的地方:
这个程序分三块:First集Follow集构造部分,项目集合生成部分,分析表构造部分
项目集合生成和分析表构造部分比较成功,多次修改文法最终生成的分析表都正确
需要改进的地方:
1、First集Follow集的构造还有待改进
2、错误处理还有待改进,有些错误处理可以合并,有些错误可能拆分之后更好
3、程序的结构不好,