-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.py
executable file
·222 lines (178 loc) · 6.29 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
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
from ply import yacc
from lexer import Lexer
class Parser:
tokens = Lexer().tokens
precedence = (
# Braces
('left', "LCB", "RCB"),
('left', "LSB", "RSB"),
('left', "LRB", "RRB"),
# Statements
# ('left', "WHILE", "FOR", "ON"),
# ('left', "IN"),
('left', "ELSEIF", "ELSE"),
('left', "IF"),
# ('left', "WHERE"),
# ('left', "PRINT"),
# ('left', "RETURN"),
# High-level Boolean Operators
('left', "OR"),
('left', "AND"),
('left', "NOT"),
# Low-level Boolean Operators & Assignment
('left', "GT", "LT", "NE", "EQ", "LE", "GE"),
# Numeric Operators
('left', "MOD"),
('left', "SUM", "SUB"),
('left', "MUL", "DIV"),
# Atoms
('left', "INTEGERNUMBER"),
('left', "FLOATNUMBER"),
('left', "TRUE", "FALSE"),
# Type Identifiers
# ('left', "INTEGER"),
# ('left', "FLOAT"),
# ('left', "BOOLEAN"),
# Identifier
('left', "ID"),
('right', "ASSIGN"),
# ('left', "FUNCTION"),
# ('left', "MAIN"),
# Low-level Misc
# ("left", "SEMICOLON", "COLON"),
# Error
("left", "ERROR")
)
def __init__(self):
pass
def p_program(self, p):
"""program : declist MAIN LRB RRB block
| MAIN LRB RRB block"""
print("declist MAIN LRB RRB block| MAIN LRB RRB block")
def p_declist(self, p):
"""declist : dec
| declist dec"""
print("dec| declist dec")
def p_dec(self, p):
"""dec : vardec
| funcdec"""
print("vardec| funcdec")
def p_type(self, p):
"""type : INTEGER
| FLOAT
| BOOLEAN"""
print("INTEGER| FLOAT| BOOLEAN")
def p_iddec(self, p):
"""iddec : lvalue
| lvalue ASSIGN exp"""
print("ID| ID LSB exp RSB| ID ASSIGN exp")
def p_idlist(self, p):
"""idlist : iddec
| idlist COMMA iddec"""
print("iddec| idlist COMMA iddec")
def p_vardec(self, p):
"""vardec : idlist COLON type SEMICOLON"""
print("idlist COLON type SEMICOLON")
def p_funcdec(self, p):
"""funcdec : FUNCTION ID LRB paramdecs RRB COLON type block
| FUNCTION ID LRB paramdecs RRB block"""
print("FUNCTION ID LRB paramdecs RRB COLON type block| FUNCTION ID LRB paramdecs RRB block")
def p_paramdecs(self, p):
"""paramdecs : paramdecslist
| empty"""
print("paramdecslist| empty")
def p_paramdecslist(self, p):
"""paramdecslist : paramdec
| paramdecslist COMMA paramdec"""
print("paramdec| paramdecslist COMMA paramdec")
def p_paramdec(self, p):
""" paramdec : ID COLON type
| ID LSB RSB COLON type"""
print("ID COLON type| ID LSB RSB COLON type")
def p_block(self, p):
"""block : LCB stmtlist RCB"""
print("LCB stmtlist RCB")
def p_stmtlist(self, p):
"""stmtlist : stmtlist stmt
| empty"""
print("stmtlist stmt| empty")
def p_lvalue(self, p):
"""lvalue : ID
| ID LSB exp RSB"""
print("ID| ID LSB exp RSB")
def p_case(self, p):
"""case : WHERE const COLON stmtlist"""
print("WHERE const COLON stmtlist")
def p_cases(self, p):
"""cases : cases case
| empty"""
print("cases case| empty")
def p_stmt(self, p):
"""stmt : RETURN exp SEMICOLON
| exp SEMICOLON
| block
| vardec
| WHILE LRB exp RRB stmt
| ON LRB exp RRB LCB cases RCB SEMICOLON
| FOR LRB exp SEMICOLON exp SEMICOLON exp RRB stmt
| FOR LRB ID IN ID RRB stmt
| IF LRB exp RRB stmt elseiflist
| IF LRB exp RRB stmt elseiflist ELSE stmt
| PRINT LRB ID RRB SEMICOLON"""
print(
"RETURN exp SEMICOLON| exp SEMICOLON| block| vardec| WHILE LRB exp RRB stmt| ON LRB exp RRB LCB cases RCB SEMICOLON| FOR LRB exp SEMICOLON exp SEMICOLON exp RRB stmt| FOR LRB ID IN ID RRB stmt| IF LRB exp RRB stmt elseiflist| IF LRB exp RRB stmt elseiflist ELSE stmt| PRINT LRB ID RRB")
def p_elseiflist(self, p):
"""elseiflist : elseiflist ELSEIF LRB exp RRB stmt
| empty"""
print("elseiflist ELSEIF LRB exp RRB stmt| empty")
def p_exp(self, p):
"""exp : lvalue ASSIGN exp
| exp GT exp
| exp LT exp
| exp NE exp
| exp EQ exp
| exp LE exp
| exp GE exp
| exp AND exp
| exp OR exp
| exp SUM exp
| exp SUB exp
| exp MUL exp
| exp DIV exp
| exp MOD exp
| const
| lvalue
| lvalue LRB explist RRB
| LRB exp RRB
| lvalue LRB RRB
| SUB exp
| NOT exp"""
print(
"lvalue ASSIGN exp| exp GT exp| exp LT exp| exp NE exp| exp EQ exp| exp LE exp| exp GE exp| exp AND exp| exp OR exp| exp SUM exp| exp SUB exp| exp MUL exp| exp DIV exp| exp MOD exp| const| lvalue| ID LRB explist RRB| LRB exp RRB| ID LRB RRB| SUB exp| NOT exp")
def p_const(self, p):
"""const : INTEGERNUMBER
| FLOATNUMBER
| TRUE
| FALSE"""
print("INTEGERNUMBER| FLOATNUMBER| TRUE| FALSE")
def p_explist(self, p):
"""explist : exp
| explist COMMA exp"""
print("exp| explist COMMA exp")
def p_empty(self, p):
"""empty :"""
print("empty")
pass
def p_error(self, p):
print("Error", p.type, p.lexpos)
# raise Exception('ParsingError: invalid grammar at ', p)
def build(self, **kwargs):
self.parser = yacc.yacc(module=self, **kwargs)
return self.parser
lexer = Lexer().build()
file = open('test3.txt')
text_input = file.read()
file.close()
lexer.input(text_input)
parser = Parser()
parser.build().parse(text_input, lexer, False)