-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.py
139 lines (121 loc) · 3.21 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
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
import ply.yacc as yacc
from lexer import tokens
num_errors = 0
num_lines = 0
precedence = (
('nonassoc', 'AND', 'OR'),
('nonassoc', 'EQUAL', 'NOTEQUAL'),
('nonassoc', 'LESS', 'LESSEQUAL', 'GREATER', 'GREATEREQUAL'),
('left', 'PLUS', 'MINUS'),
('left', 'TIMES', 'DIVIDE'),
('right', 'UMINUS', 'NOT')
)
def p_block(p):
'''block : blocklist'''
p[0] = p[1]
def p_blocklist(p):
'''blocklist : empty
| blocklist command blockterminator'''
if len(p) == 2:
p[0] = p[1]
else:
p[0] = ('blocklist', p[1], p[2])
def p_blockterminator(p):
'''blockterminator : empty
| SEMICOLON'''
pass
def p_command(p):
'''command : ID ASSIGN exp
| functioncall
| vardeclaration
| WHILE exp DO block END
| IF exp THEN block elsestnt END'''
if len(p) == 4:
p[0] = ('assign', p[1], p[3])
elif len(p) == 6:
p[0] = ('while', p[2], p[4], 'endwhile')
elif len(p) == 7:
p[0] = ('if', p[2], p[4], p[5], 'endif')
else:
p[0] = p[1]
def p_elsestnt(p):
'''elsestnt : empty
| ELSE block'''
if len(p) == 2:
p[0] = p[1]
else:
p[0] = ('else', p[2])
def p_exp(p):
'''exp : NUMBER
| ID
| functioncall
| exp PLUS exp
| exp MINUS exp
| exp TIMES exp
| exp DIVIDE exp
| exp LESS exp
| exp LESSEQUAL exp
| exp GREATER exp
| exp GREATEREQUAL exp
| exp EQUAL exp
| exp NOTEQUAL exp
| exp AND exp
| exp OR exp
| NOT exp
| MINUS exp %prec UMINUS
| LPAREN exp RPAREN'''
if len(p) == 4:
if p[1] == '(':
p[0] = p[2]
elif p[1] == 'MINUS' or p[1] == 'NOT':
p[0] = ('unary-operation', p[1], p[2])
else:
p[0] = ('binary-operation', p[1], ('binary-operator', p[2]), p[3])
#elif len(p) == 3:
# p[0] = ('unary-operation', p[1], p[2])
elif len(p) == 3:
p[0] = ('unary-operation', p[1], p[2])
else:
p[0] = p[1]
def p_functioncall(p):
'''functioncall : ID LPAREN explist RPAREN'''
p[0] = ('function-call', p[1], p[3])
def p_vardeclaration(p):
'''vardeclaration : VAR ID expassign'''
p[0] = ('vardeclaration', p[2], p[3])
def p_expassign(p):
'''expassign : empty
| ASSIGN exp'''
if len(p) == 2:
p[0] = p[1]
else:
p[0] = p[2]
def p_explist(p):
'''explist : empty
| lexp exp'''
if len(p) == 2:
p[0] = p[1]
else:
p[0] = ('exp-list', p[1], p[2])
def p_lexp(p):
'''lexp : empty
| lexp exp COMMA'''
if len(p) == 2:
p[0] = p[1]
else:
p[0] = ('exp-seq', p[1], p[2])
#def p_unaryop(p):
# '''unaryop : MINUS %prec UMINUS
# | NOT'''
# p[0] = ('unary-operator', p[1])
def p_empty(p):
'empty : '
pass
def p_error(p):
global num_errors
global num_lines
line = p.lineno - num_lines
print "Syntax error in input at token '%s' at line: %d" % (p.type, line)
num_errors += 1
# Building parser
parser = yacc.yacc(debug=True)