-
Notifications
You must be signed in to change notification settings - Fork 0
/
yaccConfig.py
340 lines (278 loc) · 13.2 KB
/
yaccConfig.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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
# This file contains the BNF rules for MAlice.
import ASTNodes
from tokRules import tokens
import grammarExceptions as e
start = 'code_seperator'
precedence = (
('left', 'L_OR'),
('left', 'L_AND'),
('left', 'L_EQUAL', 'L_NOT_EQUAL'),
('left', 'L_LESS_THAN', 'L_LESS_THAN_EQUAL', 'L_GREATER_THAN', 'L_GREATER_THAN_EQUAL'),
('left', 'B_OR'),
('left', 'B_XOR'),
('left', 'B_AND'),
('left', 'PLUS', 'MINUS'),
('left', 'MULTIPLY', 'DIVIDE', 'MOD'),
('right', 'INCREMENT', 'DECREMENT', 'B_NOT', 'UMINUS'),
('left', 'L_PAREN', 'R_PAREN'),
)
################################################################################
# CODE SEPERATOR
################################################################################
def p_code_seperator(p):
'''code_seperator : statement_list function_seperator functions'''
p[0] = ASTNodes.CodeSeparatorNode(p.lineno(1), p.clauseno(1), p[1], p[3])
def p_code_seperator_single(p):
'code_seperator : statement_list'
p[0] = p[1]
################################################################################
# STATEMENT LIST
################################################################################
def p_statement_list_statement(p):
'statement_list : statement seperator'
p[0] = p[1]
def p_statement_list_sep(p):
'''statement_list : statement seperator statement_list'''
p[0] = ASTNodes.StatementListNode(p.lineno(1), p.clauseno(1), [p[1], p[3]])
################################################################################
# SEPERATOR
################################################################################
def p_seperator(p):
'''seperator : SEP_AND
| SEP_BUT
| SEP_THEN
| SEP_COMMA
| SEP_QUESTION
| SEP_PERIOD'''
pass
################################################################################
# STATEMENT
################################################################################
def p_statement_print(p):
'''statement : expression PRINT_SPOKE
| expression PRINT_SAID ALICE'''
p[0] = ASTNodes.SpokeNode(p.lineno(1), p.clauseno(1), p[1])
def p_statement_input(p):
'statement : INPUT_WHAT DEC_WAS expression'
p[0] = ASTNodes.InputNode(p.lineno(1), p.clauseno(1), p[3])
def p_statement_comment(p):
'statement : expression COMMENT_THOUGHT ALICE'
p[0] = ASTNodes.CommentNode(p.lineno(1), p.clauseno(1), p[1])
def p_statement_too(p):
'statement : statement TOO'
p[0] = p[1]
def p_statement_wasa(p):
'statement : ID DEC_WAS DEC_A type'
p[0] = ASTNodes.DeclarationNode(p.lineno(1), p.clauseno(1), p[1], p[4])
def p_statement_became_id(p):
'statement : ID ASSIGNMENT expression'
p[0] = ASTNodes.AssignmentNode(p.lineno(1), p.clauseno(1), p[1], p[3])
def p_statement_became_array_access(p):
'statement : array_access ASSIGNMENT expression'
p[0] = ASTNodes.ArrayAssignmentNode(p.lineno(1), p.clauseno(1), p[1], p[3])
#TODO: SHOULD WE ONLY MATCH ON NUMBERS e.g "a has 'a' number" readable but catch later?
def p_statement_array_has(p):
'statement : ID ARRAY_HAD expression type'
p[0] = ASTNodes.ArrayDeclarationNode(p.lineno(1), p.clauseno(1), p[1], p[4], p[3])
def p_statement_loop(p):
'statement : LOOP_EVENTUALLY L_PAREN expression R_PAREN LOOP_BECAUSE statement_list LOOP_ENOUGH LOOP_TIMES'
p[0] = ASTNodes.LoopNode(p.lineno(2), p.clauseno(2), p[3], p[6])
def p_statement_if_either(p):
'statement : IF_EITHER L_PAREN expression R_PAREN IF_SO statement_list IF_OR statement_list logical_ending'
p[0] = ASTNodes.IfNode(p.lineno(2), p.clauseno(2), p[3], p[6], p[8])
def p_statement_if_perhaps(p):
'statement : IF_PERHAPS L_PAREN expression R_PAREN IF_SO statement_list logical_ending'
p[0] = ASTNodes.IfNode(p.lineno(2), p.clauseno(2), p[3], p[6])
def p_statement_if_perhaps_multiple(p):
'statement : IF_PERHAPS L_PAREN expression R_PAREN IF_SO statement_list logical_clauses logical_ending'
p[0] = ASTNodes.IfNode(p.lineno(2), p.clauseno(2), p[3], p[6], p[7])
def p_statement_return(p):
'statement : ALICE_FOUND expression'
p[0] = ASTNodes.ReturnNode(p.lineno(1), p.clauseno(1), p[2])
def p_statement_expression(p):
'statement : expression'
p[0] = p[1]
################################################################################
# LOGICAL CLAUSES
################################################################################
def p_logical_clauses_many(p):
'logical_clauses : logical_clause logical_clauses'
p[0] = ASTNodes.LogicalClausesNode(p.lineno(1), p.clauseno(1), p[1], p[2])
def p_logical_clauses_single(p):
'logical_clauses : logical_clause'
p[0] = p[1]
def p_logical_ending(p):
'''logical_ending : ALICE DEC_WAS IF_UNSURE
| ALICE DEC_WAS IF_UNSURE IF_WHICH'''
pass
################################################################################
# LOGICAL CLAUSE
################################################################################
def p_logical_clause_elif(p):
'logical_clause : IF_OR IF_MAYBE L_PAREN expression R_PAREN IF_SO statement_list'
p[0] = ASTNodes.ElseIfNode(p.lineno(4), p.clauseno(4), p[4], p[7])
def p_logical_clause_else(p):
'logical_clause : IF_OR statement_list'
p[0] = ASTNodes.ElseNode(p.lineno(2), p.clauseno(2), p[2])
################################################################################
# EXPRESSION
################################################################################
def p_expression_call_function(p):
'expression : ID L_PAREN function_arguments R_PAREN'
p[0] = ASTNodes.FunctionCallNode( p.lineno(1), p.clauseno(1), p[1], p[3])
def p_expression_call_pbr_function(p):
'expression : ID FUNCTION_WENT FUNCTION_THROUGH ID'
factor = ASTNodes.IDNode(p.lineno(1), p.clauseno(1), p[1])
argument = ASTNodes.FunctionArgumentNode( p.lineno(1), p.clauseno(1), factor )
functionCall = ASTNodes.FunctionCallNode( p.lineno(1), p.clauseno(1), p[4], argument)
p[0] = ASTNodes.AssignmentNode(p.lineno(1), p.clauseno(1), p[1], functionCall)
def p_expression_parenthesis(p):
'expression : L_PAREN expression R_PAREN'
p[0] = p[2]
def p_expression_not(p):
'expression : B_NOT expression'
p[0] = ASTNodes.UnaryNode(p.lineno(2), p.clauseno(2), p[1], p[2])
def p_expression_inc_dec(p):
'''expression : ID DECREMENT
| ID INCREMENT'''
idNode = ASTNodes.IDNode(p.lineno(1), p.clauseno(1), p[1])
p[0] = ASTNodes.UnaryNode(p.lineno(2), p.clauseno(2), p[2], idNode)
def p_expression_binary(p):
'''expression : expression B_OR expression
| expression B_XOR expression
| expression B_AND expression
| expression PLUS expression
| expression MINUS expression
| expression MULTIPLY expression
| expression L_EQUAL expression
| expression L_LESS_THAN expression
| expression L_GREATER_THAN expression
| expression L_GREATER_THAN_EQUAL expression
| expression L_LESS_THAN_EQUAL expression
| expression L_NOT_EQUAL expression
| expression L_AND expression
| expression L_OR expression'''
p[0] = ASTNodes.BinaryNode(p.lineno(1), p.clauseno(1), p[2], [p[1],p[3]])
#TODO: MOVE THESE EXPRESSIONS INTO GENERAL BINARY EXPRESSION ABOVE AND MOVE
# DIV/0 CHECK INTO ASTNODE CHECK FUNCTION
def p_expression_divide(p):
'''expression : expression DIVIDE expression
| expression MOD expression'''
if p[3].getValue() == 0:
raise e.DivisionByZeroException(p.lineno(1), p.clauseno(1))
p[0] = ASTNodes.BinaryNode(p.lineno(1), p.clauseno(1), p[2], [p[1],p[3]])
def p_expression_uminus(p):
'expression : MINUS expression %prec UMINUS'
p[0] = ASTNodes.UnaryNode(p.lineno(1), p.clauseno(1), p[1], p[2])
def p_expression_array_access(p):
'expression : array_access'
p[0] = p[1]
def p_expression_factor(p):
'expression : factor'
p[0] = p[1]
################################################################################
# ARRAY ACCESS
################################################################################
def p_array_access(p):
'array_access : ID APOSTROPHE expression ARRAY_PIECE'
factor = ASTNodes.IDNode(p.lineno(1), p.clauseno(1), p[1])
p[0] = ASTNodes.ArrayAccessNode(p.lineno(1), p.clauseno(1), factor, p[2])
################################################################################
# FACTOR
################################################################################
def p_factor_number(p):
'factor : NUMBER'
p[0] = ASTNodes.NumberNode(p.lineno(1), p.clauseno(1), p[1])
def p_factor_letter(p):
'factor : LETTER'
p[0] = ASTNodes.LetterNode(p.lineno(1), p.clauseno(1), p[1])
def p_factor_id(p):
'factor : ID'
p[0] = ASTNodes.IDNode(p.lineno(1), p.clauseno(1), p[1])
def p_factor_sentence(p):
'factor : SENTENCE'
p[0] = ASTNodes.SentenceNode(p.lineno(1), p.clauseno(1), p[1])
################################################################################
# TYPE
################################################################################
def p_type_number(p):
'type : TYPE_NUMBER'
p[0] = ASTNodes.NumberTypeNode(p.lineno(1), p.clauseno(1))
def p_type_letter(p):
'type : TYPE_LETTER'
p[0] = ASTNodes.LetterTypeNode(p.lineno(1), p.clauseno(1))
def p_type_sentence(p):
'type : TYPE_SENTENCE'
p[0] = ASTNodes.SentenceTypeNode(p.lineno(1), p.clauseno(1))
################################################################################
# FUNCTIONS
################################################################################
def p_functions_multiple(p):
'functions : function function_seperator functions'
p[0] = ASTNodes.FunctionsNode( p.lineno(1), p.clauseno(1), p[1], p[3] )
def p_functions_single(p):
'functions : function'
p[0] = p[1]
################################################################################
# FUNCTION SEPERATOR
################################################################################
def p_function_seperator(p):
'''function_seperator : FUNCTION_THE FUNCTION_ROOM
| FUNCTION_THE FUNCTION_LOOKING_GLASS'''
pass
################################################################################
# FUNCTION
################################################################################
def p_function(p):
'function : ID L_PAREN arguments R_PAREN FUNCTION_CONTAINED DEC_A type statement_list'
p[0] = ASTNodes.FunctionDeclarationNode( p.lineno(1), p.clauseno(1), p[1], p[3], p[7], p[8])
# TODO CHANGE THIS TO FUNCTION
def p_function_reference(p):
'function : ID FUNCTION_CHANGED DEC_A type statement_list'
factor = ASTNodes.IDNode(p.lineno(1), p.clauseno(1), 'it')
returnNode = ASTNodes.ReturnNode(p.lineno(1), p.clauseno(1), factor)
lookingGlassNode = ASTNodes.LookingGlassNode( p.lineno(1), p.clauseno(1), p[5], returnNode)
declarationNode = ASTNodes.DeclarationNode(p.lineno(1), p.clauseno(1), 'it', p[4])
argument = ASTNodes.ArgumentNode( p.lineno(4), p.clauseno(4), declarationNode )
p[0] = ASTNodes.FunctionDeclarationNode( p.lineno(1), p.clauseno(1), p[1], argument, p[4], lookingGlassNode )
################################################################################
# ARGUMENTS
################################################################################
def p_arguments_multiple(p):
'arguments : argument SEP_COMMA arguments'
p[0] = ASTNodes.ArgumentsNode( p.lineno(1), p.clauseno(1), p[1], p[3])
def p_arguments_single(p):
'arguments : argument'
p[0] = p[1]
################################################################################
# ARGUMENT
################################################################################
def p_argument(p):
'argument : type ID'
declarationNode = ASTNodes.DeclarationNode(p.lineno(1), p.clauseno(1), p[2], p[1])
p[0] = ASTNodes.ArgumentNode( p.lineno(1), p.clauseno(1), declarationNode )
def p_argument_reference(p):
'argument : FUNCTION_SPIDER type ID'
declarationNode = ASTNodes.DeclarationNode(p.lineno(1), p.clauseno(1), p[3], p[2])
p[0] = ASTNodes.ArgumentNode( p.lineno(1), p.clauseno(1), declarationNode, True)
################################################################################
# FUNCTION ARGUMENTS
################################################################################
def p_function_arguments_multiple(p):
'function_arguments : function_argument seperator function_arguments'
p[0] = ASTNodes.FunctionArgumentsNode( p.lineno(1), p.clauseno(1), p[1], p[3] )
def p_function_arguments_single(p):
'function_arguments : function_argument'
p[0] = p[1]
################################################################################
# FUNCTION ARGUMENT
################################################################################
def p_function_argument(p):
'function_argument : expression'
p[0] = ASTNodes.FunctionArgumentNode( p.lineno(1), p.clauseno(1), p[1] )
def p_error(p):
if p == None:
raise e.NoMatchException()
else:
# print p
raise e.SyntaxException(p.lineno, p.clauseno)