-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser.py
108 lines (91 loc) · 1.56 KB
/
parser.py
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
definitions = {}
import sys
from ply import yacc
from lexer import lex, tokens
precedence = (
('left', 'OR'),
('left', 'NL'),
)
class Definition(object):
def __init__(self):
self.rules = []
self.used = 0
def name(self, prefix):
assert(self.used > 0)
idx = "" if self.used==1 else str(self.used)
return str(prefix) + idx
def p_programB(p):
'''
program : block program
'''
p[0] = p[1]
def p_programE(p):
'''
program :
'''
pass
def p_block(p):
'''
block : BLOCK rules BLOCK
'''
p[0] = p[2]
def p_rules(p):
'''
rules : rule NL rules
| rule NL
| rule
'''
p[0] = p[1]
def p_rule(p):
'''
rule : VARIABLE COLON disj
'''
if p[1] not in definitions:
definitions[p[1]] = Definition()
definitions[p[1]].rules.extend(p[3])
p[0] = p[1]
def p_disjE(p):
'''
disj :
'''
p[0] = [None]
def p_disjB(p):
'''
disj : terms
'''
p[0] = [p[1]]
def p_disjI(p):
'''
disj : terms OR disj
'''
p[0] = [p[1]] + p[3]
def p_termsB(p):
'''
terms : VARIABLE
| TOKEN
'''
p[0] = [p[1]]
def p_termsI(p):
'''
terms : VARIABLE terms
| TOKEN terms
'''
p[0] = [p[1]] + p[2]
def p_error(p):
where = "near line "+str(p.lineno)
print >>sys.stderr, "Syntax error", where+": unexpected", p.type
yacc = yacc.yacc()
if __name__=="__main__":
import sys
inp = sys.stdin.read()
axiom = yacc.parse(inp, debug=("-d" in sys.argv))
if axiom != None:
f = "%-"+str(max([len(x) for x in definitions]))+"s :"
print f % "S'", axiom
for v in definitions:
for r in definitions[v].rules:
print f % v,
if r != None:
for t in r:
print t,
print