owl-basic 0.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. owl_basic/__init__.py +3 -0
  2. owl_basic/algorithms.py +29 -0
  3. owl_basic/ast_utils.py +204 -0
  4. owl_basic/basic_visitor.py +55 -0
  5. owl_basic/cfg_vertex.py +65 -0
  6. owl_basic/codegen/__init__.py +0 -0
  7. owl_basic/codegen/clr/__init__.py +0 -0
  8. owl_basic/codegen/clr/cil_visitor.py +1296 -0
  9. owl_basic/codegen/clr/cts.py +56 -0
  10. owl_basic/codegen/clr/emitters.py +94 -0
  11. owl_basic/codegen/clr/generate.py +539 -0
  12. owl_basic/correlation_visitor.py +119 -0
  13. owl_basic/data_visitor.py +62 -0
  14. owl_basic/decoder.py +339 -0
  15. owl_basic/errors.py +22 -0
  16. owl_basic/flow/__init__.py +17 -0
  17. owl_basic/flow/basic_block.py +34 -0
  18. owl_basic/flow/basic_block_identifier.py +66 -0
  19. owl_basic/flow/basic_block_orderer.py +29 -0
  20. owl_basic/flow/connectors.py +19 -0
  21. owl_basic/flow/convert_sub_visitor.py +28 -0
  22. owl_basic/flow/entry_point_locator.py +55 -0
  23. owl_basic/flow/entry_point_visitor.py +48 -0
  24. owl_basic/flow/flow_analysis.py +56 -0
  25. owl_basic/flow/flow_graph_creator.py +14 -0
  26. owl_basic/flow/flowgraph_visitor.py +178 -0
  27. owl_basic/flow/longjump_converter.py +20 -0
  28. owl_basic/flow/longjump_visitor.py +53 -0
  29. owl_basic/flow/subroutine_converter.py +38 -0
  30. owl_basic/flow/traversal.py +110 -0
  31. owl_basic/gml_visitor.py +151 -0
  32. owl_basic/line_mapper.py +43 -0
  33. owl_basic/line_number_visitor.py +65 -0
  34. owl_basic/main.py +381 -0
  35. owl_basic/node.py +21 -0
  36. owl_basic/options.py +22 -0
  37. owl_basic/owltyping/__init__.py +1 -0
  38. owl_basic/owltyping/function_type_inferer.py +50 -0
  39. owl_basic/owltyping/hindley_milner.py +524 -0
  40. owl_basic/owltyping/set_function_type_visitor.py +25 -0
  41. owl_basic/owltyping/type_system.py +220 -0
  42. owl_basic/owltyping/typecheck.py +60 -0
  43. owl_basic/owltyping/typecheck_visitor.py +471 -0
  44. owl_basic/parent_visitor.py +37 -0
  45. owl_basic/process.py +36 -0
  46. owl_basic/separation_visitor.py +98 -0
  47. owl_basic/sigil.py +30 -0
  48. owl_basic/simplify_visitor.py +204 -0
  49. owl_basic/singleton.py +127 -0
  50. owl_basic/source_debugging.py +124 -0
  51. owl_basic/symbol_table_visitor.py +220 -0
  52. owl_basic/symbol_tables.py +195 -0
  53. owl_basic/syntax/__init__.py +0 -0
  54. owl_basic/syntax/ast.py +1081 -0
  55. owl_basic/syntax/ast_meta.py +228 -0
  56. owl_basic/syntax/grammar.py +1972 -0
  57. owl_basic/syntax/lexer.py +943 -0
  58. owl_basic/syntax/parser.py +77 -0
  59. owl_basic/utility.py +26 -0
  60. owl_basic/visitor.py +43 -0
  61. owl_basic/xml_blocks.py +137 -0
  62. owl_basic/xml_visitor.py +101 -0
  63. owl_basic-0.6.0.dist-info/METADATA +37 -0
  64. owl_basic-0.6.0.dist-info/RECORD +69 -0
  65. owl_basic-0.6.0.dist-info/WHEEL +5 -0
  66. owl_basic-0.6.0.dist-info/entry_points.txt +2 -0
  67. owl_basic-0.6.0.dist-info/licenses/LICENSE +21 -0
  68. owl_basic-0.6.0.dist-info/licenses/THIRD-PARTY-NOTICES.md +57 -0
  69. owl_basic-0.6.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1972 @@
1
+ import logging
2
+
3
+ import ply.yacc as yacc
4
+
5
+ # Get the token map from the lexer. This is required.
6
+ from .lexer import tokens
7
+ from .ast import *
8
+
9
+
10
+ def setDebuggingPositions(p):
11
+ if p is not None and p[0] is not None:
12
+ # If it hasn't already been set by more specialised code
13
+ if p[0].startLine is None:
14
+ #print "Assigning line numbers"
15
+ p[0].startLine, p[0].endLine = p.linespan(1)
16
+ # Note: endPos here will be *before* the last token - it can be refined later
17
+ p[0].startPos, p[0].endPos = p.lexspan(1)
18
+ #print p[0].startLine, p[0].endLine, p[0].startPos, p[0].endPos
19
+
20
+ logger = logging.getLogger('bbc_grammar')
21
+
22
+ # Precedence table for the above operators
23
+ precedence = (
24
+ ('right', 'UEQUAL'),
25
+ ('left', 'EOR', 'OR'),
26
+ ('left', 'AND'),
27
+ ('nonassoc', 'EQ', 'NE', 'LTE', 'GTE', 'LT', 'GT', 'SHIFT_LEFT', 'SHIFT_RIGHT', 'SHIFT_RIGHT_UNSIGNED'),
28
+ ('left', 'PLUS', 'MINUS'),
29
+ ('left', 'TIMES', 'DIVIDE', 'MOD', 'DIV'),
30
+ ('left', 'CARET'),
31
+ ('left', 'PLING', 'QUERY'), # Binary indirection operators
32
+ ('right', 'FUNCTION', 'NOT', 'UPLUS', 'UMINUS', 'UPLING', 'UQUERY', 'UPIPE', 'UDOLLAR', 'UHASH'), # Unary operators
33
+ )
34
+
35
+ def p_program(p):
36
+ 'program : statement_list'
37
+ p[0] = Program(statements = p[1])
38
+
39
+ def p_statement_list(p):
40
+ '''statement_list : compound_statement
41
+ | statement_list compound_statement'''
42
+ if len(p) == 2:
43
+ p[0] = StatementList()
44
+ p[0].extend(p[1])
45
+ elif len(p) == 3:
46
+ p[1].extend(p[2])
47
+ p[0] = p[1]
48
+
49
+ # A single line statement list - use in single-line IF THEN ELSE construct
50
+ def p_compound_statement(p):
51
+ '''compound_statement : lone_stmt_body stmt_terminator
52
+ | multi_statement stmt_terminator'''
53
+ p[0] = p[1]
54
+
55
+ def p_multi_statement(p):
56
+ '''multi_statement : statement statements_tail'''
57
+ p[2].prepend(p[1])
58
+ p[0] = p[2]
59
+
60
+ def p_statements_tail(p):
61
+ '''statements_tail : statement_separator statement statements_tail
62
+ | empty'''
63
+ if len(p) == 4:
64
+ p[3].prepend(p[2])
65
+ p[0] = p[3]
66
+ elif len(p) == 2:
67
+ p[0] = StatementList()
68
+
69
+ def p_statement_separator(p):
70
+ 'statement_separator : COLON'
71
+ p[0] = p[1]
72
+
73
+ def p_stmt_terminator(p):
74
+ 'stmt_terminator : EOL'
75
+ p[0] = p[1]
76
+
77
+ def p_statement(p):
78
+ '''statement : stmt_body
79
+ | empty'''
80
+ p[0] = p[1]
81
+ setDebuggingPositions(p)
82
+
83
+ #=============================================================================#
84
+ # STATEMENTS
85
+
86
+ # TODO: Statements to be implemented
87
+ '''stmt_body : chain_stmt
88
+ | local_stmt
89
+ | on_error_stmt
90
+ | restore_stmt PAGE 69 BBCBASIC.PDF - RESTORE +offset???
91
+ | trace_stmt'''
92
+
93
+ # Statements which must appear alone on
94
+ # their own line
95
+ def p_lone_stmt_body(p):
96
+ '''lone_stmt_body : case_stmt
97
+ | star_command'''
98
+ p[0] = StatementList()
99
+ p[0].append(p[1])
100
+
101
+ def p_star_command(p):
102
+ '''star_command : STAR_FX
103
+ | STAR_CAT'''
104
+ p[0] = StarCommand(command = p[1])
105
+ p[0].lineNum = p.lineno(1) - 1
106
+ setDebuggingPositions(p)
107
+
108
+ # Statements which can appear alone,
109
+ # or in compound statements on one line
110
+ def p_stmt_body(p):
111
+ '''stmt_body : beats_stmt
112
+ | bput_stmt
113
+ | call_stmt
114
+ | circle_stmt
115
+ | clear_stmt
116
+ | clg_stmt
117
+ | cls_stmt
118
+ | close_stmt
119
+ | colour_stmt
120
+ | data_stmt
121
+ | def_stmt
122
+ | dim_stmt
123
+ | draw_stmt
124
+ | ellipse_stmt
125
+ | end_stmt
126
+ | end_fn_stmt
127
+ | endproc_stmt
128
+ | envelope_stmt
129
+ | error_stmt
130
+ | fill_stmt
131
+ | gcol_stmt
132
+ | goto_stmt
133
+ | on_goto_stmt
134
+ | gosub_stmt
135
+ | input_stmt
136
+ | install_stmt
137
+ | if_stmt
138
+ | for_stmt
139
+ | line_stmt
140
+ | library_stmt
141
+ | let_stmt
142
+ | local_stmt
143
+ | mandel_stmt
144
+ | mode_stmt
145
+ | mouse_stmt
146
+ | move_stmt
147
+ | off_stmt
148
+ | on_stmt
149
+ | origin_stmt
150
+ | oscli_stmt
151
+ | next_stmt
152
+ | plot_stmt
153
+ | point_stmt
154
+ | print_stmt
155
+ | private_stmt
156
+ | proc_stmt
157
+ | quit_stmt
158
+ | read_stmt
159
+ | rectangle_stmt
160
+ | rem_stmt
161
+ | repeat_stmt
162
+ | report_stmt
163
+ | restore_stmt
164
+ | return_stmt
165
+ | sound_stmt
166
+ | stop_stmt
167
+ | stereo_stmt
168
+ | swap_stmt
169
+ | sys_stmt
170
+ | tempo_stmt
171
+ | tint_stmt
172
+ | until_stmt
173
+ | vdu_stmt
174
+ | voices_stmt
175
+ | while_stmt
176
+ | width_stmt
177
+ | wait_stmt
178
+ | endwhile_stmt
179
+ | run_stmt'''
180
+ p[0] = p[1]
181
+
182
+ def p_bput_stmt(p):
183
+ '''bput_stmt : BPUT channel COMMA expr
184
+ | BPUT channel COMMA expr SEMICOLON'''
185
+ if len(p) == 5:
186
+ p[0] = Bput(channel = p[2], data = p[4], newline=True)
187
+ elif len(p) == 6:
188
+ p[0] = Bput(channel = p[2], data = p[4], newline=False)
189
+ p[0].lineNum = p.lineno(1) - 1
190
+
191
+ def p_call_stmt(p):
192
+ '''call_stmt : CALL expr
193
+ | CALL expr COMMA writable_list'''
194
+ if len(p) == 3:
195
+ p[0] = Call(address = p[2])
196
+ elif len(p) == 5:
197
+ p[0] = Call(address = p[2], parameters = p[4])
198
+ p[0].lineNum = p.lineno(1) - 1
199
+
200
+ # TODO CASE stmt
201
+ # Not that WHEN clauses which follow the OTHERWISE clause
202
+ # a legal, but cannot be executed.
203
+ # TODO : Put this into a special class of statements which
204
+ # must begin on a new line.
205
+ def p_case_stmt(p):
206
+ '''case_stmt : CASE expr OF stmt_terminator when_clause_list ENDCASE'''
207
+ p[0] = Case(condition = p[2], whenClauses = p[5])
208
+ p[0].lineNum = p.lineno(1) - 1
209
+ setDebuggingPositions(p)
210
+
211
+ def p_when_clause_list(p):
212
+ '''when_clause_list : when_clause
213
+ | when_clause_list when_clause'''
214
+ if len(p) == 2:
215
+ p[0] = WhenClauseList()
216
+ p[0].append(p[1])
217
+ elif len(p) == 3:
218
+ p[1].append(p[2])
219
+ p[0] = p[1]
220
+
221
+ def p_when_clause(p):
222
+ '''when_clause : WHEN expr_list COLON statement_list
223
+ | OTHERWISE statement_list'''
224
+ if len(p) == 5:
225
+ p[0] = WhenClause(matches = p[2], statements = p[4])
226
+ elif len(p) == 3:
227
+ p[0] = OtherwiseClause(statements = p[2])
228
+ p[0].lineNum = p.lineno(1) - 1
229
+
230
+ def p_beats_stmt(p):
231
+ '''beats_stmt : BEATS expr'''
232
+ p[0] = Beats(counter = p[2])
233
+ p[0].lineNum = p.lineno(1) - 1
234
+
235
+ def p_circle_stmt(p):
236
+ '''circle_stmt : CIRCLE expr COMMA expr COMMA expr
237
+ | CIRCLE FILL expr COMMA expr COMMA expr'''
238
+ if len(p) == 7:
239
+ p[0] = Circle(xCoord = p[2], yCoord = p[4], radius = p[6])
240
+ elif len(p) == 8:
241
+ p[0] = Circle(xCoord = p[3], yCoord = p[5], radius = p[7], fill=True)
242
+ p[0].lineNum = p.lineno(1) - 1
243
+
244
+ def p_clear_stmt(p):
245
+ 'clear_stmt : CLEAR'
246
+ p[0] = Clear()
247
+ p[0].lineNum = p.lineno(1) - 1
248
+
249
+ def p_close_stmt(p):
250
+ 'close_stmt : CLOSE channel'
251
+ p[0] = Close(channel = p[2])
252
+ p[0].lineNum = p.lineno(1) - 1
253
+
254
+ def p_clg_stmt(p):
255
+ 'clg_stmt : CLG'
256
+ p[0] = Clg()
257
+ p[0].lineNum = p.lineno(1) - 1
258
+
259
+ def p_cls_stmt(p):
260
+ 'cls_stmt : CLS'
261
+ p[0] = Cls()
262
+ p[0].lineNum = p.lineno(1) - 1
263
+
264
+ def p_colour_stmt(p):
265
+ '''colour_stmt : COLOUR expr
266
+ | COLOUR expr COMMA expr
267
+ | COLOUR expr TINT expr
268
+ | COLOUR expr COMMA expr COMMA expr COMMA expr'''
269
+ if len(p) == 3:
270
+ p[0] = Colour(colour = p[2])
271
+ elif len(p) == 5:
272
+ if p[3] == "TINT":
273
+ p[0] = Colour(colour = p[2], tint = p[4])
274
+ else:
275
+ p[0] = Palette(logicalColour = p[2], physicalColour = p[4])
276
+ elif len(p) == 9:
277
+ p[0] = Palette(logicalColour = p[2], red = p[4], green = p[6], blue = p[8])
278
+ p[0].lineNum = p.lineno(1) - 1
279
+
280
+
281
+ # DATA
282
+ def p_data_statement(p):
283
+ 'data_stmt : DATA'
284
+ p[0] = Data(data = p[1])
285
+ p[0].lineNum = p.lineno(1) - 1
286
+
287
+ # REM
288
+ def p_rem_statement(p):
289
+ 'rem_stmt : COMMENT'
290
+ p[0] = Rem(data = p[1])
291
+ p[0].lineNum = p.lineno(1) - 1
292
+
293
+ def p_def_stmt(p):
294
+ '''def_stmt : def_fn_stmt
295
+ | def_proc_stmt'''
296
+ p[0] = p[1]
297
+
298
+ # The statement list needs to be modified so there can be more
299
+ # than one point of return form functions
300
+ def p_def_fn_stmt(p):
301
+ '''def_fn_stmt : DEF FN_ID statement
302
+ | DEF FN_ID LPAREN formal_arg_list RPAREN statement'''
303
+
304
+ if len(p) == 4:
305
+ p[0] = DefineFunction(name = p[2], followingStatement = p[3])
306
+ end_pos = p.lexpos(2)
307
+ elif len(p) == 7:
308
+ p[0] = DefineFunction(name = p[2], formalParameters = p[4], followingStatement = p[6])
309
+ end_pos = p.lexpos(5)
310
+
311
+ #print "Assigning DEF PROC line numbers"
312
+ p[0].lineNum = p.lineno(1) - 1
313
+ p[0].startLine = p.lineno(1)
314
+ p[0].endLine = p.lineno(1)
315
+ p[0].startPos = p.lexpos(1)
316
+ assert end_pos is not None
317
+ p[0].endPos = end_pos
318
+
319
+ def p_end_fn_stmt(p):
320
+ '''end_fn_stmt : EQ expr %prec UEQUAL'''
321
+ p[0] = ReturnFromFunction(returnValue = p[2])
322
+ p[0].lineNum = p.lineno(1) - 1
323
+
324
+ def p_def_proc_stmt(p):
325
+ '''def_proc_stmt : DEF PROC_ID statement
326
+ | DEF PROC_ID LPAREN formal_arg_list RPAREN statement'''
327
+ if len(p) == 4:
328
+ p[0] = DefineProcedure(name = p[2], followingStatement = p[3])
329
+ end_pos = p.lexpos(2)
330
+ elif len(p) == 7:
331
+ p[0] = DefineProcedure(name = p[2], formalParameters = p[4], followingStatement = p[6])
332
+ end_pos = p.lexpos(5)
333
+
334
+ #print "Assigning DEF PROC line numbers"
335
+ p[0].lineNum = p.lineno(1) - 1
336
+ p[0].startLine = p.lineno(1)
337
+ p[0].endLine = p.lineno(1)
338
+ p[0].startPos = p.lexpos(1)
339
+ assert end_pos is not None
340
+ p[0].endPos = end_pos
341
+
342
+ def p_endproc_stmt(p):
343
+ '''endproc_stmt : ENDPROC'''
344
+ p[0] = ReturnFromProcedure()
345
+ p[0].lineNum = p.lineno(1) - 1
346
+
347
+ def p_proc_stmt(p):
348
+ '''proc_stmt : PROC_ID
349
+ | PROC_ID LPAREN actual_arg_list RPAREN'''
350
+ if len(p) == 2:
351
+ p[0] = CallProcedure(name = p[1], actualParameters = ActualArgList())
352
+ elif len(p) == 5:
353
+ p[0] = CallProcedure(name = p[1], actualParameters = p[3])
354
+ p[0].lineNum = p.lineno(1) - 1
355
+
356
+ def p_dim_statement(p):
357
+ '''dim_stmt : DIM dim_list'''
358
+ p[0] = Dim(items = p[2])
359
+ p[0].lineNum = p.lineno(1) - 1
360
+
361
+ def p_dim_list(p):
362
+ '''dim_list : dim_item
363
+ | dim_list COMMA dim_item'''
364
+ if len(p) == 2:
365
+ p[0] = DimList()
366
+ p[0].append(p[1])
367
+ elif len(p) == 4:
368
+ p[1].append(p[3])
369
+ p[0] = p[1]
370
+
371
+ def p_dim_item(p):
372
+ # TODO: BB4W structures would be added here
373
+ '''dim_item : indexer
374
+ | variable expr'''
375
+ if len(p) == 2:
376
+ p[0] = AllocateArray(identifier = p[1].identifier, dimensions = p[1].indices)
377
+ elif len(p) == 3:
378
+ p[0] = AllocateBlock(identifier = p[1], size = p[2])
379
+
380
+
381
+ def p_draw_stmt(p):
382
+ '''draw_stmt : DRAW expr COMMA expr
383
+ | DRAW BY expr COMMA expr'''
384
+ if len(p) == 5:
385
+ p[0] = Draw(xCoord = p[2], yCoord = p[4])
386
+ elif len(p) == 6:
387
+ p[0] = Draw(xCoord = p[3], yCoord = p[5], relative=True)
388
+ p[0].lineNum = p.lineno(1) - 1
389
+
390
+ def p_end_stmt(p):
391
+ '''end_stmt : END'''
392
+ p[0] = End()
393
+ p[0].lineNum = p.lineno(1) - 1
394
+
395
+ def p_ellipse_stmt(p): # BBC BASIC V also supports rotation of an ellipse
396
+ '''ellipse_stmt : ELLIPSE expr COMMA expr COMMA expr COMMA expr
397
+ | ELLIPSE FILL expr COMMA expr COMMA expr COMMA expr
398
+ | ELLIPSE expr COMMA expr COMMA expr COMMA expr COMMA expr
399
+ | ELLIPSE FILL expr COMMA expr COMMA expr COMMA expr COMMA expr'''
400
+
401
+ if len(p) == 9:
402
+ p[0] = Ellipse(xCoord = p[2], yCoord = p[4], semiMajor = p[6], semiMinor = p[8])
403
+ elif len(p) == 10:
404
+ p[0] = Ellipse(xCoord = p[3], yCoord = p[5], semiMajor = p[7], semiMinor = p[9], fill=True)
405
+ elif len(p) == 11:
406
+ p[0] = Ellipse(xCoord = p[2], yCoord = p[4], semiMajor = p[6], semiMinor = p[8], radians = p[10])
407
+ elif len(p) == 12:
408
+ p[0] = Ellipse(xCoord = p[3], yCoord = p[5], semiMajor = p[7], semiMinor = p[9], radians = p[11], fill=True)
409
+ p[0].lineNum = p.lineno(1) - 1
410
+
411
+
412
+ def p_error_stmt(p):
413
+ '''error_stmt : ERROR expr COMMA expr
414
+ | ERROR EXT expr COMMA expr'''
415
+ # TODO: Needs to handle the EXT keyword for returning an external error code
416
+ # ERROR EXT ERR, REPORT$ : REM pass on the error
417
+ if len(p) == 5:
418
+ p[0] = GenerateError(number = p[2], description = p[4])
419
+ elif len(p) == 6:
420
+ p[0] = ReturnError(number = p[2], description = p[4])
421
+ p[0].lineNum = p.lineno(1) - 1
422
+
423
+ def p_envelope_stmt(p):
424
+ '''envelope_stmt : ENVELOPE expr COMMA expr COMMA expr COMMA expr COMMA expr COMMA expr COMMA expr COMMA expr COMMA expr COMMA expr COMMA expr COMMA expr COMMA expr COMMA expr'''
425
+ p[0] = Envelope(n = p[2], t = p[4], pitch1 = p[6], pitch2 = p[8], pitch3 = p[10],
426
+ numSteps1 = p[12], numSteps2 = p[14], numSteps3 = p[16],
427
+ amplitudeAttack = p[18], amplitudeDecay = p[20], amplitudeSustain = p[22],
428
+ amplitudeRelease = p[24], targetAttack = p[26], targetDecay = p[28] )
429
+ p[0].lineNum = p.lineno(1) - 1
430
+
431
+ def p_fill_stmt(p):
432
+ '''fill_stmt : FILL expr COMMA expr
433
+ | FILL BY expr COMMA expr'''
434
+ if len(p) == 5:
435
+ p[0] = Fill(xCoord = p[2], yCoord = p[4])
436
+ elif len(p) == 6:
437
+ p[0] = Fill(xCoord = p[3], yCoord = p[5], relative=True)
438
+ p[0].lineNum = p.lineno(1) - 1
439
+
440
+ def p_gcol_stmt(p):
441
+ '''gcol_stmt : GCOL expr
442
+ | GCOL expr COMMA expr
443
+ | GCOL expr TINT expr
444
+ | GCOL expr COMMA expr TINT expr'''
445
+ if len(p) == 3:
446
+ p[0] = Gcol(mode = LiteralInteger(value = 0), logicalColour = p[2])
447
+ elif len(p) == 5:
448
+ if p[3] == 'TINT':
449
+ p[0] = Gcol(mode = LiteralInteger(value = 0), logicalColour = p[2], tint = p[4])
450
+ else:
451
+ p[0] = Gcol(mode = p[2], logicalColour = p[4])
452
+ elif len(p) == 7:
453
+ p[0] = Gcol(mode = p[2], logicalColour = p[4], tint = p[6])
454
+ p[0].lineNum = p.lineno(1) - 1
455
+
456
+ def p_input_stmt(p):
457
+ '''input_stmt : INPUT
458
+ | INPUT input_list
459
+ | LINE INPUT
460
+ | LINE INPUT input_list
461
+ | INPUT LINE
462
+ | INPUT LINE input_list
463
+ | INPUT channel COMMA variable_list'''
464
+ # TODO: All other syntax of input to replace the second line above - see PRINT
465
+ if len(p) == 2:
466
+ #INPUT
467
+ p[0] = Input()
468
+ elif len(p) == 3:
469
+ if p[1] == "LINE":
470
+ #LINE INPUT
471
+ p[0] = Input(inputLine = True)
472
+ elif p[2] == "LINE":
473
+ #INPUT LINE
474
+ p[0] = Input(inputLine = True)
475
+ else:
476
+ #INPUT input_list
477
+ p[0] = Input(inputList = p[2])
478
+ elif len(p) == 4:
479
+ if p[1] == "LINE":
480
+ #LINE INPUT input_list
481
+ p[0] = Input(inputLine = True, inputList = p[3])
482
+ elif p[2] == "LINE":
483
+ #INPUT LINE input_list
484
+ p[0] = Input(inputLine = True, inputList = p[3])
485
+ elif len(p) == 5:
486
+ p[0] = InputFile(channel = p[2], items = p[4])
487
+ p[0].lineNum = p.lineno(1) - 1
488
+
489
+ def p_input_list(p):
490
+ '''input_list : input_item
491
+ | input_list input_item'''
492
+ if len(p) == 2:
493
+ p[0] = InputList()
494
+ p[0].append(p[1])
495
+ elif len(p) == 3:
496
+ p[1].append(p[2])
497
+ p[0] = p[1]
498
+
499
+ def p_input_item(p):
500
+ '''input_item : literal_string
501
+ | tab
502
+ | spc
503
+ | input_manipulator
504
+ | writable'''
505
+ p[0] = InputItem(item = p[1])
506
+
507
+ def p_input_manipulator(p):
508
+ '''input_manipulator : APOSTROPHE
509
+ | COMMA
510
+ | SEMICOLON'''
511
+ p[0] = InputManipulator(manipulator = p[1])
512
+ p[0].lineNum = p.lineno(1) - 1
513
+
514
+
515
+
516
+
517
+
518
+ def p_install_stmt(p):
519
+ '''install_stmt : INSTALL expr'''
520
+ if len(p) == 3:
521
+ p[0] = Install(filename = p[2])
522
+ p[0].lineNum = p.lineno(1) - 1
523
+
524
+ # GOTO statement
525
+ def p_goto_stmt(p):
526
+ '''goto_stmt : GOTO factor'''
527
+ p[0] = Goto(targetLogicalLine = p[2])
528
+ p[0].lineNum = p.lineno(1) - 1
529
+
530
+ def p_on_goto_stmt(p):
531
+ '''on_goto_stmt : ON expr GOTO expr_list
532
+ | ON expr GOTO expr_list ELSE multi_statement'''
533
+ # TODO ELSE clause
534
+ if len(p) == 5:
535
+ p[0] = OnGoto(switch = p[2], targetLogicalLines = p[4])
536
+ elif len(p) == 7:
537
+ p[0] = OnGoto(switch = p[2], targetLogicalLines = p[4], outOfRangeClause = p[6])
538
+ p[0].lineNum = p.lineno(1) - 1
539
+
540
+ # GOSUB statement
541
+ def p_gosub(p):
542
+ '''gosub_stmt : GOSUB factor'''
543
+ p[0] = Gosub(targetLogicalLine = p[2])
544
+ p[0].lineNum = p.lineno(1) - 1
545
+
546
+ def p_return_stmt(p):
547
+ '''return_stmt : RETURN'''
548
+ p[0] = Return()
549
+ p[0].lineNum = p.lineno(1) - 1
550
+
551
+ def p_if_stmt(p):
552
+ #'''if_stmt : if_single_stmt'''
553
+ '''if_stmt : if_single_stmt
554
+ | if_multi_stmt'''
555
+ p[0] = p[1]
556
+
557
+ def p_if_single_stmt(p):
558
+ '''if_single_stmt : IF expr clause
559
+ | IF expr THEN clause
560
+ | IF expr clause ELSE clause
561
+ | IF expr THEN clause ELSE clause'''
562
+
563
+ # Specialised debugging lexer positions set in here
564
+ if len(p) == 4:
565
+ p[0] = If(condition = p[2], trueClause = p[3])
566
+ end_pos = p.lexpos(3)
567
+ elif len(p) == 5:
568
+ p[0] = If(condition = p[2], trueClause = p[4])
569
+ end_pos = p.lexpos(4)
570
+ elif len(p) == 6:
571
+ p[0] = If(condition = p[2], trueClause = p[3], falseClause = p[5])
572
+ end_pos = p.lexpos(3)
573
+ elif len(p) == 7:
574
+ p[0] = If(condition = p[2], trueClause = p[4], falseClause = p[6])
575
+ end_pos = p.lexpos(4)
576
+
577
+ #print "Assigning IF line numbers"
578
+ p[0].lineNum = p.lineno(1) - 1
579
+ p[0].startLine = p.lineno(1)
580
+ p[0].endLine = p.lineno(1)
581
+ p[0].startPos = p.lexpos(1)
582
+ assert end_pos is not None
583
+ p[0].endPos = end_pos
584
+
585
+ # The clause is only used with IF statements and
586
+ # possible ON statements when the result of an expression
587
+ # is interpreted as a line number to GOTO
588
+ def p_clause(p):
589
+ '''clause : multi_statement
590
+ | implicit_goto'''
591
+ p[0] = p[1]
592
+
593
+ def p_implicit_goto(p):
594
+ '''implicit_goto : factor'''
595
+ stmt_list = StatementList()
596
+ goto = Goto(targetLogicalLine = p[1])
597
+ goto.lineNum = p.lineno(1) - 1
598
+ goto.startLine = p.lineno(1)
599
+ goto.endLine = p.lineno(1)
600
+ goto.startPos = p.lexpos(1)
601
+ goto.endPos = p.lexpos(1)
602
+ stmt_list.append(goto)
603
+ p[0] = stmt_list
604
+
605
+ def p_if_multi_stmt(p):
606
+ '''if_multi_stmt : IF expr THEN statement_list ENDIF
607
+ | IF expr THEN statement_list ELSE statement_list ENDIF'''
608
+ if len(p) == 6:
609
+ p[0] = If(condition = p[2], trueClause = p[4])
610
+ elif len(p) == 8:
611
+ p[0] = If(condition = p[2], trueClause = p[4], falseClause = p[6])
612
+ p[0].lineNum = p.lineno(1) - 1
613
+
614
+ # The syntax rules for FOR..NEXT loops are not implemented by the
615
+ # grammar owing to the fact that NEXT is treated as a statement,
616
+ # rather than as a loop terminator. A later analysis of the parse
617
+ # tree will attempt to match each NEXT with its corresponding FOR
618
+ def p_for_stmt(p):
619
+ '''for_stmt : FOR writable EQ expr TO expr
620
+ | FOR writable EQ expr TO expr STEP expr'''
621
+ if len(p) == 7:
622
+ p[0] = ForToStep(identifier = p[2], first = p[4], last = p[6], step = LiteralInteger(value = 1))
623
+ elif len(p) == 9:
624
+ p[0] = ForToStep(identifier = p[2], first = p[4], last = p[6], step = p[8])
625
+ p[0].lineNum = p.lineno(1) - 1
626
+
627
+ # Rule for dealing with unmatched NEXT statements
628
+ def p_next_stmt(p):
629
+ '''next_stmt : NEXT nullable_variable_list'''
630
+ p[0] = Next(identifiers = p[2])
631
+ p[0].lineNum = p.lineno(1) - 1
632
+
633
+ def p_library_stmt(p):
634
+ '''library_stmt : LIBRARY expr'''
635
+ p[0] = LoadLibrary(filename = p[2])
636
+ p[0].lineNum = p.lineno(1) - 1
637
+
638
+ def p_line_stmt(p):
639
+ '''line_stmt : LINE expr COMMA expr COMMA expr COMMA expr'''
640
+
641
+ # TODO: Sort this lot out!
642
+ p[0] = Line(x1Coord = p[2], y1Coord = p[4], x2Coord = p[6], y2Coord = p[8])
643
+ p[0].lineNum = p.lineno(1) - 1
644
+
645
+ def p_let_stmt(p):
646
+ '''let_stmt : let_assignment
647
+ | increment
648
+ | decrement'''
649
+ p[0] = p[1]
650
+
651
+ def p_let_assignment(p):
652
+ '''let_assignment : LET assignment
653
+ | assignment'''
654
+ if len(p) == 3:
655
+ p[0] = p[2]
656
+ elif len(p) == 2:
657
+ p[0] = p[1]
658
+
659
+ def p_assignment(p):
660
+ '''assignment : scalar_assignment
661
+ | array_assignment'''
662
+ p[0] = p[1]
663
+
664
+ def p_scalar_assignment(p):
665
+ '''scalar_assignment : lvalue EQ expr'''
666
+ p[0] = ScalarAssignment(lValue = p[1], rValue = p[3])
667
+ p[0].lineNum = p.lineno(2) - 1
668
+
669
+ def p_array_assignment(p):
670
+ '''array_assignment : array EQ expr_list'''
671
+ p[0] = ArrayAssignment(lValue = p[1], rValue = p[3])
672
+ p[0].lineNum = p.lineno(2) - 1
673
+
674
+ def p_increment(p):
675
+ '''increment : lvalue PLUS_ASSIGN expr
676
+ | array PLUS_ASSIGN expr'''
677
+ if len(p) == 4:
678
+ p[0] = Increment(lValue = p[1], rValue = p[3])
679
+ p[0].lineNum = p.lineno(2) - 1
680
+
681
+ def p_decrement(p):
682
+ '''decrement : lvalue MINUS_ASSIGN expr
683
+ | array MINUS_ASSIGN expr'''
684
+ if len(p) == 4:
685
+ p[0] = Decrement(lValue = p[1], rValue = p[3])
686
+ p[0].lineNum = p.lineno(2) - 1
687
+
688
+ # LOCAL statement
689
+ def p_local_stmt(p):
690
+ '''local_stmt : LOCAL variable_list'''
691
+ p[0] = Local(variables = p[2])
692
+ p[0].lineNum = p.lineno(1) - 1
693
+
694
+ # MANDEL statement
695
+ def p_mandel_stmt(p):
696
+ '''mandel_stmt : MANDEL expr COMMA expr'''
697
+ p[0] = Mandel(iCoord = p[2], jCoord = p[4])
698
+ p[0].lineNum = p.lineno(1) - 1
699
+
700
+ # MOVE statement
701
+ def p_move_stmt(p):
702
+ '''move_stmt : MOVE expr COMMA expr
703
+ | MOVE BY expr COMMA expr'''
704
+ if len(p) == 5:
705
+ p[0] = Move(xCoord = p[2], yCoord = p[4])
706
+ elif len(p) == 6:
707
+ p[0] = Move(xCoord = p[3], yCoord = p[5], relative=True)
708
+ p[0].lineNum = p.lineno(1) - 1
709
+
710
+ def p_mode_stmt(p):
711
+ '''mode_stmt : MODE expr
712
+ | MODE expr COMMA expr COMMA expr
713
+ | MODE expr COMMA expr COMMA expr COMMA expr'''
714
+ if len(p) == 3:
715
+ p[0] = Mode(number = p[2])
716
+ elif len(p) == 7:
717
+ p[0] = Mode(width = p[2], height = p[4], bitsPerPixel = p[6])
718
+ elif len(p) == 9:
719
+ p[0] = Mode(width = p[2], height = p[4], bitsPerPixel = p[6], frameRate = p[8])
720
+ p[0].lineNum = p.lineno(1) - 1
721
+
722
+
723
+ def p_mouse_stmt(p):
724
+ '''mouse_stmt : MOUSE writable COMMA writable COMMA writable
725
+ | MOUSE writable COMMA writable COMMA writable COMMA writable
726
+ | MOUSE ON
727
+ | MOUSE ON expr
728
+ | MOUSE OFF
729
+ | MOUSE TO expr COMMA expr
730
+ | MOUSE RECTANGLE expr COMMA expr COMMA expr COMMA expr
731
+ | MOUSE RECTANGLE OFF
732
+ | MOUSE STEP expr
733
+ | MOUSE STEP expr COMMA expr
734
+ | MOUSE COLOUR expr COMMA expr COMMA expr COMMA expr'''
735
+ #nested IF is to see that the p[2] contains
736
+ if str(p[2]) == 'ON':
737
+ if len(p) == 3:
738
+ #MOUSE ON
739
+ p[0] = MousePointer(shape =LiteralInteger(value = 0))
740
+ elif len(p) == 4:
741
+ #MOUSE ON expr
742
+ p[0] = MousePointer(shape =p[3])
743
+ elif str(p[2]) == 'OFF':
744
+ #MOUSE OFF
745
+ p[0] = MousePointer(shape =None)
746
+ elif str(p[2]) == 'TO':
747
+ #MOUSE TO
748
+ p[0] = MousePosition(xCoord = p[3], yCoord = p[5])
749
+ elif str(p[2]) == 'RECTANGLE':
750
+ if len(p) == 10:
751
+ #MOUSE RECTANGLE
752
+ p[0] = MouseRectangleOn(left = p[3], bottom = p[5], right = p[7], top = p[9])
753
+ elif len(p) == 4:
754
+ #MOUSE RECTANGLE OFF
755
+ p[0] = MouseRectangleOff()
756
+ elif str(p[2]) == 'STEP':
757
+ if len(p) == 4:
758
+ #MOUSE STEP expr
759
+ p[0] = MouseStep(xCoeff = p[3])
760
+ if len(p) == 6:
761
+ #MOUSE STEP expr COMMA expr
762
+ p[0] = MouseStep(xCoeff = p[3], yCoeff = p[5])
763
+ elif str(p[2]) == 'COLOUR': #Not sure if i need to check for COLOR
764
+ #MOUSE COLOUR expr COMMA expr COMMA expr COMMA expr
765
+ p[0] = MouseColour(logicalColour = p[3], red = p[5], green = p[7], blue = p[9])
766
+ else:
767
+ if len(p) == 7:
768
+ #MOUSE variable COMMA variable COMMA variable
769
+ p[0] = Mouse(xCoord = p[2], yCoord = p[4], buttons = p[6])
770
+ elif len(p) == 9:
771
+ #MOUSE variable COMMA variable COMMA variable COMMA variable
772
+ p[0] = Mouse(xCoord = p[2], yCoord = p[4], buttons = p[6], time = p[8])
773
+ p[0].lineNum = p.lineno(1) - 1
774
+
775
+
776
+ def p_on_stmt(p):
777
+ '''on_stmt : ON'''
778
+ p[0] = On()
779
+ p[0].lineNum = p.lineno(1) - 1
780
+
781
+ def p_off_stmt(p):
782
+ '''off_stmt : OFF'''
783
+ p[0] = Off()
784
+ p[0].lineNum = p.lineno(1) - 1
785
+
786
+ def p_origin_stmt(p):
787
+ '''origin_stmt : ORIGIN expr COMMA expr'''
788
+ p[0] = Origin(xCoord = p[2], yCoord = p[4])
789
+ p[0].lineNum = p.lineno(1) - 1
790
+
791
+ def p_oscli_stmt(p):
792
+ '''oscli_stmt : OSCLI expr'''
793
+ p[0] = Oscli(command = p[2])
794
+ p[0].lineNum = p.lineno(1) - 1
795
+
796
+ def p_plot_stmt(p):
797
+ '''plot_stmt : PLOT expr COMMA expr
798
+ | PLOT expr COMMA expr COMMA expr
799
+ | PLOT BY expr COMMA expr'''
800
+ if len(p) == 5:
801
+ p[0] = Plot(mode = LiteralInteger(value=65), xCoord = p[2], yCoord = p[4])
802
+ elif len(p) == 6:
803
+ p[0] = Plot(mode = LiteralInteger(value=65), xCoord = p[3], yCoord = p[5], relative=True)
804
+ elif len(p) == 7:
805
+ p[0] = Plot(mode = p[4], xCoord = p[6], yCoord = p[2])
806
+ p[0].lineNum = p.lineno(1) - 1
807
+
808
+ def p_point_stmt(p):
809
+ '''point_stmt : POINT expr COMMA expr
810
+ | POINT BY expr COMMA expr
811
+ | POINT TO expr COMMA expr'''
812
+ if len(p) == 5:
813
+ p[0] = Point(xCoord = p[2], yCoord = p[4])
814
+ elif len(p) == 6:
815
+ if str(p[2]) == 'BY':
816
+ p[0] = Point(xCoord = p[3], yCoord = p[5], relative=True)
817
+ else:
818
+ p[0] = MousePosition(xCoord = p[3], yCoord = p[5], moveMouse=False, movePointer = True)
819
+ p[0].lineNum = p.lineno(1) - 1
820
+
821
+ def p_print_stmt(p):
822
+ '''print_stmt : PRINT
823
+ | PRINT print_list
824
+ | PRINT channel COMMA actual_arg_list'''
825
+ if len(p) == 2:
826
+ p[0] = Print()
827
+ elif len(p) == 3:
828
+ p[0] = Print(printList = p[2])
829
+ elif len(p) == 4:
830
+ p[0] = PrintFile(channel = p[2], items = p[3])
831
+ p[0].lineNum = p.lineno(1) - 1
832
+
833
+ def p_print_list(p):
834
+ '''print_list : print_item
835
+ | print_list print_item'''
836
+ if len(p) == 2:
837
+ p[0] = PrintList()
838
+ p[0].append(p[1])
839
+ elif len(p) == 3:
840
+ p[1].append(p[2])
841
+ p[0] = p[1]
842
+
843
+ def p_print_item(p):
844
+ '''print_item : expr
845
+ | tab
846
+ | spc
847
+ | format_manipulator'''
848
+ p[0] = PrintItem(item = p[1])
849
+
850
+ def p_format_manipulator(p):
851
+ '''format_manipulator : TILDE
852
+ | APOSTROPHE
853
+ | COMMA
854
+ | SEMICOLON'''
855
+ p[0] = FormatManipulator(manipulator = p[1])
856
+ p[0].lineNum = p.lineno(1) - 1
857
+
858
+ # PRIVATE statement
859
+ def p_private_stmt(p):
860
+ '''private_stmt : PRIVATE variable_list'''
861
+ p[0] = Private(variables = p[2])
862
+ p[0].lineNum = p.lineno(1) - 1
863
+
864
+ def p_quit_stmt(p):
865
+ # TODO: BBC BASIC on the Iyonix supports a parameter to QUIT
866
+ '''quit_stmt : QUIT'''
867
+ p[0] = Quit()
868
+ p[0].lineNum = p.lineno(1) - 1
869
+
870
+ def p_read(p):
871
+ '''read_stmt : READ
872
+ | READ writable_list'''
873
+ if len(p) == 2:
874
+ p[0] = Read()
875
+ elif len(p) == 3:
876
+ p[0] = Read(writables = p[2])
877
+ p[0].lineNum = p.lineno(1) - 1
878
+
879
+ def p_rectangle_stmt(p):
880
+ '''rectangle_stmt : RECTANGLE expr COMMA expr COMMA expr
881
+ | RECTANGLE expr COMMA expr COMMA expr COMMA expr
882
+ | RECTANGLE expr COMMA expr COMMA expr TO expr COMMA expr
883
+ | RECTANGLE expr COMMA expr COMMA expr COMMA expr TO expr COMMA expr
884
+ | RECTANGLE FILL expr COMMA expr COMMA expr
885
+ | RECTANGLE FILL expr COMMA expr COMMA expr COMMA expr
886
+ | RECTANGLE FILL expr COMMA expr COMMA expr TO expr COMMA expr
887
+ | RECTANGLE FILL expr COMMA expr COMMA expr COMMA expr TO expr COMMA expr
888
+ | RECTANGLE SWAP expr COMMA expr COMMA expr TO expr COMMA expr
889
+ | RECTANGLE SWAP expr COMMA expr COMMA expr COMMA expr TO expr COMMA expr'''
890
+
891
+ # TODO: Sort this lot out!
892
+ if len(p) == 7:
893
+ # RECTANGLE expr COMMA expr COMMA expr
894
+ p[0] = Rectangle(xCoord = p[2], yCoord = p[4], width = p[6])
895
+ elif len(p) == 9:
896
+ # RECTANGLE expr COMMA expr COMMA expr COMMA expr
897
+ p[0] = Rectangle(xCoord = p[2], yCoord = p[4], width = p[6], height = p[8])
898
+ elif len(p) == 11:
899
+ # RECTANGLE expr COMMA expr COMMA expr TO expr COMMA expr
900
+ p[0] = CopyRectangle(xCoordSource = p[2], yCoordSource = p[4], width = p[6], xCoordTarget = p[8], yCoordTarget = p[10])
901
+ elif len(p) == 13:
902
+ # RECTANGLE expr COMMA expr COMMA expr COMMA expr TO expr COMMA expr
903
+ p[0] = CopyRectangle(xCoordSource = p[2], yCoordSource = p[4], width = p[6], height = p[8], xCoordTarget = p[10], yCoordTarget = p[12])
904
+ elif len(p) == 8:
905
+ # RECTANGLE FILL expr COMMA expr COMMA expr
906
+ p[0] = Rectangle(xCoord = p[3], yCoord = p[5], width = p[7], fill=True)
907
+ elif len(p) == 10:
908
+ # RECTANGLE FILL expr COMMA expr COMMA expr COMMA expr
909
+ p[0] = Rectangle(xCoord = p[3], yCoord = p[5], width = p[7], height = p[9], fill=True)
910
+ elif len(p) == 12:
911
+ if str(p[2]) == "FILL":
912
+ # RECTANGLE FILL expr COMMA expr COMMA expr TO expr COMMA expr
913
+ p[0] = MoveRectangle(xCoordSource = p[3], yCoordSource = p[5], width = p[7], xCoordTarget = p[9], yCoordTarget = p[11])
914
+ elif str(p[2]) == "SWAP":
915
+ # RECTANGLE SWAP expr COMMA expr COMMA expr TO expr COMMA expr
916
+ p[0] = SwapRectangle(xCoordSource = p[3], yCoordSource = p[5], width = p[7], xCoordTarget = p[9], yCoordTarget = p[11])
917
+ elif len(p) == 14:
918
+ if str(p[2]) == "FILL":
919
+ # RECTANGLE FILL expr COMMA expr COMMA expr COMMA expr TO expr COMMA expr
920
+ p[0] = MoveRectangle(xCoordSource = p[3], yCoordSource = p[5], width = p[7], height = p[9], xCoordTarget = p[11], yCoordTarget = p[13])
921
+ elif str(p[2]) == "SWAP":
922
+ # RECTANGLE SWAP expr COMMA expr COMMA expr COMMA expr TO expr COMMA expr
923
+ p[0] = SwapRectangle(xCoordSource = p[3], yCoordSource = p[5], width = p[7], height = p[9], xCoordTarget = p[11], yCoordTarget = p[13])
924
+ p[0].lineNum = p.lineno(1) - 1
925
+
926
+ def p_report_stmt(p):
927
+ '''report_stmt : REPORT'''
928
+ p[0] = Report()
929
+ p[0].lineNum = p.lineno(1) - 1
930
+
931
+ def p_repeat_stmt(p):
932
+ '''repeat_stmt : REPEAT statement'''
933
+ p[0] = Repeat(followingStatement = p[2])
934
+ p[0].lineNum = p.lineno(1) - 1
935
+
936
+ def p_restore_stmt(p):
937
+ '''restore_stmt : RESTORE
938
+ | RESTORE expr'''
939
+ # TODO restore data
940
+ # TODO restore + expr
941
+ if len(p) == 2:
942
+ p[0] = Restore()
943
+ elif len(p) == 3:
944
+ p[0] = Restore(targetLogicalLine = p[2])
945
+ p[0].lineNum = p.lineno(1) - 1
946
+
947
+
948
+ def p_sound_stmt(p):
949
+ '''sound_stmt : SOUND expr COMMA expr COMMA expr COMMA expr
950
+ | SOUND ON
951
+ | SOUND OFF'''
952
+ if len(p) == 9:
953
+ p[0] = Sound(channel = p[2], amplitude = p[4], pitch = p[6], duration = p[8])
954
+ elif len(p) == 3:
955
+ if str(p[2]) == 'OFF':
956
+ p[0] = Mute(mute=True)
957
+ else:
958
+ p[0] = Mute(mute=False)
959
+ p[0].lineNum = p.lineno(1) - 1
960
+
961
+ def p_stereo_stmt(p):
962
+ '''stereo_stmt : STEREO expr COMMA expr'''
963
+ p[0] = Stereo(channel = p[2], position = p[4])
964
+ p[0].lineNum = p.lineno(1) - 1
965
+
966
+ def p_swap_stmt(p):
967
+ '''swap_stmt : SWAP writable COMMA writable
968
+ | SWAP array COMMA array'''
969
+ #SWAP var1 COMMA var2
970
+ #SWAP array1 COMMA array2
971
+ p[0] = Swap(identifier1 = p[2], identifier2 = p[4])
972
+ p[0].lineNum = p.lineno(1) - 1
973
+
974
+ def p_sys_stmt(p):
975
+ '''sys_stmt : SYS expr
976
+ | SYS expr SEMICOLON writable
977
+ | SYS expr TO nullable_writable_list
978
+ | SYS expr COMMA nullable_expr_list
979
+ | SYS expr TO nullable_writable_list SEMICOLON writable
980
+ | SYS expr COMMA nullable_expr_list SEMICOLON writable
981
+ | SYS expr COMMA nullable_expr_list TO nullable_writable_list
982
+ | SYS expr COMMA nullable_expr_list TO nullable_writable_list SEMICOLON writable'''
983
+ if len(p) == 3:
984
+ p[0] = Sys(routine = p[2])
985
+ elif len(p) == 5:
986
+ if str(p[3]) == ';': # TODO D.R.Y. Get this from the token somehow
987
+ p[0] = Sys(routine = p[2], flags = p[4])
988
+ elif str(p[3]) == "TO":
989
+ p[0] = Sys(routine = p[2], returnValues = p[4])
990
+ elif str(p[3]) == ',':
991
+ p[0] = Sys(routine = p[2], actualParameters = p[4])
992
+ elif len(p) == 7:
993
+ if str(p[3]) == "TO":
994
+ p[0] = Sys(routine = p[2], returnValues = p[4], flags = p[6])
995
+ elif str(p[3]) == ',':
996
+ if str(p[5]) == ';':
997
+ p[0] = Sys(routine = p[2], actualParameters = p[4], flags = p[6])
998
+ elif str(p[5]) == "TO":
999
+ p[0] = Sys(routine = p[2], actualParameters = p[4], returnValues = p[6])
1000
+ elif len(p) == 9:
1001
+ p[0] = Sys(routine = p[2], actualParameters = p[4], returnValues = p[6], flags = p[8])
1002
+ p[0].lineNum = p.lineno(1) - 1
1003
+
1004
+ def p_tab(p):
1005
+ '''tab : TAB_LPAREN expr RPAREN
1006
+ | TAB_LPAREN expr COMMA expr RPAREN'''
1007
+ if len(p) == 4:
1008
+ p[0] = TabH(xCoord = p[2])
1009
+ elif len(p) == 6:
1010
+ p[0] = TabXY(xCoord = p[2], yCoord = p[4])
1011
+ p[0].lineNum = p.lineno(1) - 1
1012
+
1013
+ def p_tempo_stmt(p):
1014
+ '''tempo_stmt : TEMPO expr'''
1015
+ if len(p) == 3:
1016
+ #TEMPO expression
1017
+ p[0] = Tempo(rate = p[2])
1018
+ p[0].lineNum = p.lineno(1) - 1
1019
+
1020
+ def p_tint_stmt(p):
1021
+ '''tint_stmt : TINT expr COMMA expr'''
1022
+ p[0] = Tint(option = p[3], tint = p[5])
1023
+ p[0].lineNum = p.lineno(1) - 1
1024
+
1025
+ def p_stop_stmt(p):
1026
+ '''stop_stmt : STOP'''
1027
+ p[0] = Stop()
1028
+ p[0].lineNum = p.lineno(1) - 1
1029
+
1030
+ def p_spc(p):
1031
+ '''spc : SPC expr'''
1032
+ p[0] = Spc(spaces = p[2])
1033
+ p[0].lineNum = p.lineno(1) - 1
1034
+
1035
+ def p_until_stmt(p):
1036
+ '''until_stmt : UNTIL expr'''
1037
+ p[0] = Until(condition = p[2])
1038
+ p[0].lineNum = p.lineno(1) - 1
1039
+
1040
+ # VDU
1041
+ def p_vdu_stmt(p):
1042
+ '''vdu_stmt : VDU
1043
+ | VDU vdu_list'''
1044
+ if len(p) == 2:
1045
+ p[0] = Vdu()
1046
+ elif len(p) == 3:
1047
+ p[0] = Vdu(bytes = p[2])
1048
+ p[0].lineNum = p.lineno(1) - 1
1049
+
1050
+ def p_vdu_list(p):
1051
+ '''vdu_list : vdu_item
1052
+ | vdu_list vdu_item'''
1053
+ if len(p) == 2:
1054
+ p[0] = VduList()
1055
+ p[0].append(p[1])
1056
+ elif len(p) == 3:
1057
+ p[1].append(p[2])
1058
+ p[0] = p[1]
1059
+
1060
+ def p_vdu_item(p):
1061
+ '''vdu_item : expr vdu_separator
1062
+ | expr'''
1063
+ if len(p) == 2:
1064
+ p[0] = VduItem(item = p[1])
1065
+ elif len(p) == 3:
1066
+ p[0] = VduItem(item = p[1], length = p[2])
1067
+
1068
+ def p_vdu_separator(p):
1069
+ '''vdu_separator : COMMA
1070
+ | SEMICOLON
1071
+ | PIPE'''
1072
+ if p[1] == ',':
1073
+ p[0] = 1
1074
+ elif p[1] == ';':
1075
+ p[0] = 2
1076
+ elif p[1] == '|':
1077
+ p[0] = 9
1078
+
1079
+ def p_voices_stmt(p):
1080
+ '''voices_stmt : VOICES expr'''
1081
+ #VOICES expression
1082
+ p[0] = Voices(numberOfVoices = p[2])
1083
+ p[0].lineNum = p.lineno(1) - 1
1084
+
1085
+ def p_while_stmt(p):
1086
+ '''while_stmt : WHILE expr'''
1087
+ p[0] = While(condition = p[2])
1088
+ p[0].lineNum = p.lineno(1) - 1
1089
+
1090
+ def p_endwhile_stmt(p):
1091
+ '''endwhile_stmt : ENDWHILE'''
1092
+ p[0] = Endwhile()
1093
+ p[0].lineNum = p.lineno(1) - 1
1094
+
1095
+ def p_width_stmt(p):
1096
+ '''width_stmt : WIDTH expr'''
1097
+ p[0] = Width(lineWidth = p[2])
1098
+ p[0].lineNum = p.lineno(1) - 1
1099
+
1100
+ def p_wait_stmt(p):
1101
+ '''wait_stmt : WAIT
1102
+ | WAIT expr'''
1103
+ if len(p) == 2:
1104
+ #WAIT
1105
+ p[0] = Wait()
1106
+ elif len(p) == 3:
1107
+ #WAIT expr
1108
+ p[0] = Wait(centiseconds = p[2])
1109
+ p[0].lineNum = p.lineno(1) - 1
1110
+
1111
+ def p_run_stmt(p):
1112
+ '''run_stmt : RUN'''
1113
+ p[0] = Run()
1114
+ p[0].lineNum = p.lineno(1) - 1
1115
+
1116
+ #=============================================================================#
1117
+ # ARGUMENTS
1118
+ #
1119
+
1120
+ def p_actual_arg_list(p):
1121
+ '''actual_arg_list : actual_arg
1122
+ | actual_arg_list COMMA actual_arg'''
1123
+ if len(p) == 2:
1124
+ p[0] = ActualArgList()
1125
+ p[0].append(p[1])
1126
+ if len(p) == 4:
1127
+ p[1].append(p[3])
1128
+ p[0] = p[1]
1129
+ p[0].lineNum = p.lineno(2) - 1
1130
+
1131
+ def p_actual_arg(p):
1132
+ '''actual_arg : expr'''
1133
+ p[0] = p[1]
1134
+
1135
+ def p_formal_arg_list(p):
1136
+ '''formal_arg_list : formal_arg
1137
+ | formal_arg_list COMMA formal_arg'''
1138
+ if len(p) == 2:
1139
+ p[0] = FormalArgList()
1140
+ p[0].append(p[1])
1141
+ if len(p) == 4:
1142
+ p[1].append(p[3])
1143
+ p[0] = p[1]
1144
+
1145
+ def p_formal_arg(p):
1146
+ '''formal_arg : variable
1147
+ | array
1148
+ | RETURN variable
1149
+ | RETURN array'''
1150
+ if len(p) == 2:
1151
+ p[0] = FormalArgument(argument = p[1])
1152
+ elif len(p) == 3:
1153
+ p[0] = FormalReferenceArgument(argument = p[2])
1154
+ p[0].lineNum = p.lineno(1) - 1
1155
+
1156
+ #=============================================================================#
1157
+ # FACTORS and EXPRESSIONS
1158
+ #
1159
+
1160
+ # TODO: Removed indexer from factor temporarily
1161
+ def p_factor(p):
1162
+ '''factor : literal
1163
+ | variable
1164
+ | pseudovariable
1165
+ | array
1166
+ | expr_group
1167
+ | expr_function
1168
+ | indexer
1169
+ | PLUS factor %prec UPLUS
1170
+ | MINUS factor %prec UMINUS'''
1171
+ if len(p) == 2:
1172
+ p[0] = p[1]
1173
+ elif len(p) == 3:
1174
+ if p[1] == '+':
1175
+ p[0] = UnaryPlus(factor = p[2])
1176
+ elif p[1] == '-':
1177
+ p[0] = UnaryMinus(factor = p[2])
1178
+ p[0].lineNum = p.lineno(1) - 1
1179
+
1180
+ def p_unary_indirection(p):
1181
+ '''unary_indirection : QUERY factor %prec UQUERY
1182
+ | PLING factor %prec UPLING
1183
+ | PIPE factor %prec UPIPE
1184
+ | DOLLAR factor %prec UDOLLAR'''
1185
+ if p[1] == '?':
1186
+ p[0] = UnaryByteIndirection(expression = p[2])
1187
+ elif p[1] == '!':
1188
+ p[0] = UnaryIntegerIndirection(expression = p[2])
1189
+ elif p[1] == '$':
1190
+ p[0] = UnaryStringIndirection(expression = p[2])
1191
+ elif p[1] == '|':
1192
+ p[0] = UnaryFloatIndirection(expression = p[2])
1193
+ p[0].lineNum = p.lineno(1) - 1
1194
+
1195
+ def p_expr_list(p):
1196
+ '''expr_list : expr
1197
+ | expr_list COMMA expr'''
1198
+ if len(p) == 2:
1199
+ p[0] = ExpressionList()
1200
+ p[0].append(p[1])
1201
+ elif len(p) == 4:
1202
+ p[1].append(p[3])
1203
+ p[0] = p[1]
1204
+
1205
+ def p_nullable_expr(p):
1206
+ '''nullable_expr : expr
1207
+ | empty'''
1208
+ p[0] = p[1]
1209
+
1210
+ def p_nullable_expr_list(p):
1211
+ '''nullable_expr_list : nullable_expr
1212
+ | nullable_expr_list COMMA nullable_expr'''
1213
+ if len(p) == 2:
1214
+ p[0] = ExpressionList()
1215
+ p[0].append(p[1])
1216
+ elif len(p) == 4:
1217
+ p[1].append(p[3])
1218
+ p[0] = p[1]
1219
+
1220
+ # TODO : Should any of these expressions take factors rather than expr as operands
1221
+ def p_expr(p):
1222
+ '''expr : factor
1223
+ | expr PLUS expr
1224
+ | expr MINUS expr
1225
+ | expr TIMES expr
1226
+ | expr DIVIDE expr
1227
+ | expr MOD expr
1228
+ | expr DIV expr
1229
+ | expr DOT expr
1230
+ | expr CARET expr
1231
+ | expr EQ expr
1232
+ | expr NE expr
1233
+ | expr LTE expr
1234
+ | expr GTE expr
1235
+ | expr LT expr
1236
+ | expr GT expr
1237
+ | expr SHIFT_LEFT expr
1238
+ | expr SHIFT_RIGHT expr
1239
+ | expr SHIFT_RIGHT_UNSIGNED expr
1240
+ | expr AND expr
1241
+ | expr OR expr
1242
+ | expr EOR expr
1243
+ | dyadic_indirection'''
1244
+ if len(p) == 2:
1245
+ p[0] = p[1]
1246
+ elif len(p) == 4:
1247
+ if p[2] == '+':
1248
+ p[0] = Plus(lhs = p[1], rhs = p[3])
1249
+ elif p[2] == '-':
1250
+ p[0] = Minus(lhs = p[1], rhs = p[3])
1251
+ elif p[2] == '*':
1252
+ p[0] = Multiply(lhs = p[1], rhs = p[3])
1253
+ elif p[2] == '/':
1254
+ p[0] = Divide(lhs = p[1], rhs = p[3])
1255
+ elif p[2] == 'DIV':
1256
+ p[0] = IntegerDivide(lhs = p[1], rhs = p[3])
1257
+ elif p[2] == 'MOD':
1258
+ p[0] = IntegerModulus(lhs = p[1], rhs = p[3])
1259
+ elif p[2] == '.':
1260
+ p[0] = MatrixMultiply(lhs = p[1], rhs = p[3])
1261
+ elif p[2] == '^':
1262
+ p[0] = Power(lhs = p[1], rhs = p[3])
1263
+ elif p[2] == '=':
1264
+ p[0] = Equal(lhs = p[1], rhs = p[3])
1265
+ elif p[2] == '<>':
1266
+ p[0] = NotEqual(lhs = p[1], rhs = p[3])
1267
+ elif p[2] == '<':
1268
+ p[0] = LessThan(lhs = p[1], rhs = p[3])
1269
+ elif p[2] == '<=':
1270
+ p[0] = LessThanEqual(lhs = p[1], rhs = p[3])
1271
+ elif p[2] == '>':
1272
+ p[0] = GreaterThan(lhs = p[1], rhs = p[3])
1273
+ elif p[2] == '>=':
1274
+ p[0] = GreaterThanEqual(lhs = p[1], rhs = p[3])
1275
+ elif p[2] == '<<':
1276
+ p[0] = ShiftLeft(lhs = p[1], rhs = p[3])
1277
+ elif p[2] == '>>':
1278
+ p[0] = ShiftRight(lhs = p[1], rhs = p[3])
1279
+ elif p[2] == '>>>':
1280
+ p[0] = ShiftRightUnsigned(lhs = p[1], rhs = p[3])
1281
+ elif p[2] == 'AND':
1282
+ p[0] = And(lhs = p[1], rhs = p[3])
1283
+ elif p[2] == 'OR':
1284
+ p[0] = Or(lhs = p[1], rhs = p[3])
1285
+ elif p[2] == 'EOR':
1286
+ p[0] = Eor(lhs = p[1], rhs = p[3])
1287
+ p[0].lineNum = p.lineno(2) - 1
1288
+ p[0].isLValue = False
1289
+
1290
+ def p_dyadic_indirection(p):
1291
+ """dyadic_indirection : variable QUERY factor
1292
+ | variable PLING factor"""
1293
+ if p[2] == '?':
1294
+ # TODO: Ideally we would want to require that the LHS
1295
+ # of the dyadic indirection operators is a simple
1296
+ # variable. Doesn't work yet, though.
1297
+ p[0] = DyadicByteIndirection(base = p[1], offset = p[3])
1298
+ elif p[2] == '!':
1299
+ p[0] = DyadicIntegerIndirection(base = p[1], offset = p[3])
1300
+ p[0].lineNum = p.lineno(2) - 1
1301
+
1302
+ def p_expr_group(p):
1303
+ 'expr_group : LPAREN expr RPAREN'
1304
+ p[0] = p[2]
1305
+
1306
+
1307
+ #=============================================================================#
1308
+ # VALUES
1309
+ #
1310
+
1311
+ # This contains all of the lvalues which can occur on the
1312
+ # left-hand-side on an assignment operator (without the LET).
1313
+ def p_lvalue(p):
1314
+ '''lvalue : writable
1315
+ | pseudovariable
1316
+ | mid_str_lvalue
1317
+ | right_str_lvalue
1318
+ | left_str_lvalue'''
1319
+ p[0] = p[1]
1320
+ p[0].isLValue = True
1321
+
1322
+ # This contains values which can be written or assigned to in
1323
+ # for example FOR and READ
1324
+ def p_writable(p):
1325
+ '''writable : variable
1326
+ | indexer
1327
+ | unary_indirection
1328
+ | dyadic_indirection'''
1329
+ p[0] = p[1]
1330
+ p[0].isLValue = True
1331
+
1332
+ def p_writable_list(p):
1333
+ '''writable_list : writable
1334
+ | writable_list COMMA writable'''
1335
+ if len(p) == 2:
1336
+ p[0] = WritableList()
1337
+ p[0].append(p[1])
1338
+ elif len(p) == 4:
1339
+ p[1].append(p[3])
1340
+ p[0] = p[1]
1341
+
1342
+ def p_mid_str_lvalue(p):
1343
+ '''mid_str_lvalue : MID_STR_LPAREN variable COMMA expr RPAREN
1344
+ | MID_STR_LPAREN variable COMMA expr COMMA expr RPAREN'''
1345
+ if len(p) == 6:
1346
+ p[0] = MidStrLValue(target = p[2], position = p[4])
1347
+ elif len(p) == 8:
1348
+ p[0] = MidStrLValue(target = p[2], position = p[4], length = p[6])
1349
+ p[0].lineNum = p.lineno(1) - 1
1350
+
1351
+ def p_right_str_lvalue(p):
1352
+ '''right_str_lvalue : RIGHT_STR_LPAREN variable RPAREN
1353
+ | RIGHT_STR_LPAREN variable COMMA expr RPAREN'''
1354
+ if len(p) == 4:
1355
+ p[0] = RightStrLValue(target = p[2])
1356
+ elif len(p) == 6:
1357
+ p[0] = RightStrLValue(target = p[2], length = p[4])
1358
+ p[0].lineNum = p.lineno(1) - 1
1359
+
1360
+ def p_left_str_lvalue(p):
1361
+ '''left_str_lvalue : LEFT_STR_LPAREN variable RPAREN
1362
+ | LEFT_STR_LPAREN variable COMMA expr RPAREN'''
1363
+ if len(p) == 4:
1364
+ p[0] = LeftStrLValue(target = p[2])
1365
+ elif len(p) == 6:
1366
+ p[0] = LeftStrLValue(target = p[2], length = p[4])
1367
+ p[0].lineNum = p.lineno(1) - 1
1368
+
1369
+ #=============================================================================#
1370
+ # PSEUDOVARIABLES
1371
+ #
1372
+
1373
+ def p_pseudovariable(p):
1374
+ '''pseudovariable : end_value
1375
+ | ext_value
1376
+ | himem_value
1377
+ | lomem_value
1378
+ | ptr_value
1379
+ | time_value
1380
+ | time_str_value
1381
+ | page_value'''
1382
+ p[0] = p[1]
1383
+
1384
+ # END is not officially a pseudovariable, although it can be used like one,
1385
+ # although it may also be used as a statement
1386
+ def p_end_value(p):
1387
+ 'end_value : END'
1388
+ p[0] = EndValue()
1389
+ p[0].lineNum = p.lineno(1) - 1
1390
+
1391
+ def p_ext(p):
1392
+ '''ext_value : EXT channel'''
1393
+ p[0] = ExtValue(channel = p[2])
1394
+ p[0].lineNum = p.lineno(1) - 1
1395
+
1396
+ def p_himem_value(p):
1397
+ 'himem_value : HIMEM'
1398
+ p[0] = HimemValue()
1399
+ p[0].lineNum = p.lineno(1) - 1
1400
+
1401
+ def p_lomem_value(p):
1402
+ 'lomem_value : LOMEM'
1403
+ p[0] = LomemValue()
1404
+ p[0].lineNum = p.lineno(1) - 1
1405
+
1406
+ def p_page_value(p):
1407
+ 'page_value : PAGE'
1408
+ p[0] = PageValue()
1409
+ p[0].lineNum = p.lineno(1) - 1
1410
+
1411
+ def p_ptr_value(p):
1412
+ 'ptr_value : PTR channel'
1413
+ p[0] = PtrValue(channel = p[2])
1414
+ p[0].lineNum = p.lineno(1) - 1
1415
+
1416
+ def p_time_value(p):
1417
+ 'time_value : TIME'
1418
+ p[0] = TimeValue()
1419
+ p[0].lineNum = p.lineno(1) - 1
1420
+
1421
+ def p_time_str_value(p):
1422
+ 'time_str_value : TIME_STR'
1423
+ p[0] = TimeStrValue()
1424
+ p[0].lineNum = p.lineno(1) - 1
1425
+
1426
+
1427
+ #=============================================================================#
1428
+ # FUNCTIONS
1429
+ #
1430
+
1431
+ # TODO: Functions to be implemented
1432
+ ''' expr_function :
1433
+ | report_str_func
1434
+ | string_str_func
1435
+ | usr_func'''
1436
+
1437
+ def p_expr_function(p):
1438
+ '''expr_function : user_func
1439
+ | adval_func
1440
+ | abs_func
1441
+ | acs_func
1442
+ | asc_func
1443
+ | asn_func
1444
+ | atn_func
1445
+ | beat_func
1446
+ | beats_func
1447
+ | bget_func
1448
+ | chr_str_func
1449
+ | cos_func
1450
+ | count_func
1451
+ | deg_func
1452
+ | dim_func
1453
+ | err_func
1454
+ | erl_func
1455
+ | exp_func
1456
+ | eof_func
1457
+ | eval_func
1458
+ | false_func
1459
+ | get_func
1460
+ | get_str_func
1461
+ | get_str_file_func
1462
+ | inkey_func
1463
+ | inkey_str_func
1464
+ | instr_func
1465
+ | int_func
1466
+ | left_str_func
1467
+ | len_func
1468
+ | ln_func
1469
+ | log_func
1470
+ | mid_str_func
1471
+ | mod_func
1472
+ | mode_func
1473
+ | not_func
1474
+ | openin_func
1475
+ | openout_func
1476
+ | openup_func
1477
+ | pi_func
1478
+ | pos_func
1479
+ | point_func
1480
+ | quit_func
1481
+ | sin_func
1482
+ | sgn_func
1483
+ | sqr_func
1484
+ | tan_func
1485
+ | rad_func
1486
+ | report_str_func
1487
+ | right_str_func
1488
+ | rnd_func
1489
+ | str_str_func
1490
+ | sum_func
1491
+ | sumlen_func
1492
+ | tempo_func
1493
+ | tint_func
1494
+ | top_func
1495
+ | true_func
1496
+ | val_func
1497
+ | vpos_func
1498
+ | width_func'''
1499
+ p[0] = p[1]
1500
+
1501
+
1502
+ def p_user_func(p):
1503
+ '''user_func : FN_ID
1504
+ | FN_ID LPAREN actual_arg_list RPAREN %prec FUNCTION'''
1505
+ if len(p) == 2:
1506
+ p[0] = UserFunc(name = p[1], actualParameters = ActualArgList())
1507
+ else:
1508
+ p[0] = UserFunc(name = p[1], actualParameters = p[3])
1509
+ p[0].lineNum = p.lineno(1) - 1
1510
+
1511
+ def p_abs_func(p):
1512
+ 'abs_func : ABS factor %prec FUNCTION'
1513
+ p[0] = AbsFunc(factor = p[2])
1514
+ p[0].lineNum = p.lineno(1) - 1
1515
+
1516
+ def p_acs_func(p):
1517
+ 'acs_func : ACS factor %prec FUNCTION'
1518
+ p[0] = AcsFunc(factor = p[2])
1519
+ p[0].lineNum = p.lineno(1) - 1
1520
+
1521
+ def p_adval_func(p):
1522
+ 'adval_func : ADVAL factor %prec FUNCTION'
1523
+ p[0] = AdvalFunc(factor = p[2])
1524
+ p[0].lineNum = p.lineno(1) - 1
1525
+
1526
+ def p_asn_func(p):
1527
+ 'asn_func : ASN factor %prec FUNCTION'
1528
+ p[0] = AsnFunc(factor = p[2])
1529
+ p[0].lineNum = p.lineno(1) - 1
1530
+
1531
+ def p_asc_func(p):
1532
+ 'asc_func : ASC factor %prec FUNCTION'
1533
+ p[0] = AscFunc(factor = p[2])
1534
+ p[0].lineNum = p.lineno(1) - 1
1535
+
1536
+ def p_atn_func(p):
1537
+ '''atn_func : ATN factor %prec FUNCTION'''
1538
+ p[0] = AtnFunc(factor = p[2] )
1539
+ p[0].lineNum = p.lineno(1) - 1
1540
+
1541
+ def p_beat_func(p):
1542
+ 'beat_func : BEAT %prec FUNCTION'
1543
+ p[0] = BeatFunc()
1544
+ p[0].lineNum = p.lineno(1) - 1
1545
+
1546
+ def p_beats_func(p):
1547
+ '''beats_func : BEATS %prec FUNCTION'''
1548
+ p[0] = BeatsFunc()
1549
+ p[0].lineNum = p.lineno(1) - 1
1550
+
1551
+ def p_bget_func(p):
1552
+ 'bget_func : BGET channel %prec FUNCTION'
1553
+ p[0] = BgetFunc(channel = p[2])
1554
+ p[0].lineNum = p.lineno(1) - 1
1555
+
1556
+ def p_chr_str_func(p):
1557
+ 'chr_str_func : CHR_STR expr %prec FUNCTION'
1558
+ p[0] = ChrStrFunc(factor = p[2])
1559
+ p[0].lineNum = p.lineno(1) - 1
1560
+
1561
+ def p_cos_func(p):
1562
+ 'cos_func : COS expr %prec FUNCTION'
1563
+ p[0] = CosFunc(factor = p[2])
1564
+ p[0].lineNum = p.lineno(1) - 1
1565
+
1566
+ def p_count_func(p):
1567
+ 'count_func : COUNT %prec FUNCTION'
1568
+ p[0] = CountFunc()
1569
+ p[0].lineNum = p.lineno(1) - 1
1570
+
1571
+ def p_deg_func(p):
1572
+ 'deg_func : DEG factor %prec FUNCTION'
1573
+ p[0] = DegFunc(factor = p[2])
1574
+ p[0].lineNum = p.lineno(1) - 1
1575
+
1576
+ def p_dim_func(p):
1577
+ '''dim_func : DIM_LPAREN array RPAREN
1578
+ | DIM_LPAREN array COMMA expr RPAREN'''
1579
+ if len(p) == 4:
1580
+ p[0] = DimensionsFunc(array = p[2])
1581
+ elif len(p) == 6:
1582
+ p[0] = DimensionSizeFunc(array = p[2], dimension = p[4])
1583
+ p[0].lineNum = p.lineno(1) - 1
1584
+
1585
+ def p_erl_func(p):
1586
+ '''erl_func : ERL %prec FUNCTION'''
1587
+ p[0] = ErlFunc()
1588
+ p[0].lineNum = p.lineno(1) - 1
1589
+
1590
+ def p_eof(p):
1591
+ '''eof_func : EOF channel'''
1592
+ p[0] = EofFunc(channel = p[2])
1593
+ p[0].lineNum = p.lineno(1) - 1
1594
+
1595
+ def p_err_func(p):
1596
+ '''err_func : ERR %prec FUNCTION'''
1597
+ p[0] = ErrFunc()
1598
+ p[0].lineNum = p.lineno(1) - 1
1599
+
1600
+ def p_exp_func(p):
1601
+ '''exp_func : EXP factor %prec FUNCTION'''
1602
+ p[0] = ExpFunc(factor = p[2])
1603
+ p[0].lineNum = p.lineno(1) - 1
1604
+
1605
+ def p_eval_func(p):
1606
+ '''eval_func : EVAL factor %prec FUNCTION'''
1607
+ p[0] = EvalFunc(factor = p[2])
1608
+ p[0].lineNum = p.lineno(1) - 1
1609
+
1610
+ def p_false_func(p):
1611
+ '''false_func : FALSE'''
1612
+ p[0] = FalseFunc()
1613
+ p[0].lineNum = p.lineno(1) - 1
1614
+
1615
+ def p_get_func(p):
1616
+ '''get_func : GET %prec FUNCTION'''
1617
+ p[0] = GetFunc()
1618
+ p[0].lineNum = p.lineno(1) - 1
1619
+
1620
+ def p_get_str_func(p):
1621
+ '''get_str_func : GET_STR %prec FUNCTION'''
1622
+ p[0] = GetStrFunc()
1623
+ p[0].lineNum = p.lineno(1) - 1
1624
+
1625
+ def p_get_str_file_func(p):
1626
+ '''get_str_file_func : GET_STR channel %prec FUNCTION'''
1627
+ p[0] = GetStrFileFunc(channel = p[2])
1628
+ p[0].lineNum = p.lineno(1) - 1
1629
+
1630
+ def p_inkey_func(p):
1631
+ '''inkey_func : INKEY factor %prec FUNCTION'''
1632
+ #if factor 0<= then wait for any key and return keycode
1633
+ #if factor 0> then return true or false on that keycode
1634
+ #if factor = -256 return a number for OS version
1635
+ p[0] = InkeyFunc(factor = p[2])
1636
+ p[0].lineNum = p.lineno(1) - 1
1637
+
1638
+ def p_inkey_str_func(p):
1639
+ '''inkey_str_func : INKEY_STR factor %prec FUNCTION'''
1640
+ p[0] = InkeyStrFunc(factor = p[2])
1641
+ p[0].lineNum = p.lineno(1) - 1
1642
+
1643
+ def p_instr_func(p):
1644
+ '''instr_func : INSTR_LPAREN expr COMMA expr RPAREN
1645
+ | INSTR_LPAREN expr COMMA expr COMMA expr RPAREN'''
1646
+ if len(p) == 6:
1647
+ #INSTR expr COMMA expr
1648
+ p[0] = InstrFunc(source = p[2], subString = p[4] )
1649
+ elif len(p) == 8:
1650
+ #INSTR expr COMMA expr COMMA expr
1651
+ p[0] = InstrFunc(source = p[2], subString = p[4], startPosition = p[6] )
1652
+ p[0].lineNum = p.lineno(1) - 1
1653
+
1654
+ def p_int_func(p):
1655
+ '''int_func : INT factor %prec FUNCTION'''
1656
+ p[0] = IntFunc(factor = p[2])
1657
+ p[0].lineNum = p.lineno(1) - 1
1658
+
1659
+ def p_left_str_func(p):
1660
+ '''left_str_func : LEFT_STR_LPAREN expr RPAREN
1661
+ | LEFT_STR_LPAREN expr COMMA expr RPAREN'''
1662
+ if len(p) == 4:
1663
+ p[0] = LeftStrFunc(source = p[2])
1664
+ elif len(p) == 6:
1665
+ p[0] = LeftStrFunc(source = p[2], length = p[4])
1666
+ p[0].lineNum = p.lineno(1) - 1
1667
+
1668
+ def p_len_func(p):
1669
+ '''len_func : LEN factor %prec FUNCTION'''
1670
+ p[0] = LenFunc(factor = p[2])
1671
+ p[0].lineNum = p.lineno(1) - 1
1672
+
1673
+ def p_ln_func(p):
1674
+ '''ln_func : LN factor %prec FUNCTION'''
1675
+ p[0] = LnFunc(factpr = p[2])
1676
+ p[0].lineNum = p.lineno(1) - 1
1677
+
1678
+ def p_log_func(p):
1679
+ '''log_func : LOG factor %prec FUNCTION'''
1680
+ p[0] = LogFunc(factor = p[2])
1681
+ p[0].lineNum = p.lineno(1) - 1
1682
+
1683
+ def p_mid_str_func(p): # note for rob - is this missing %prec FUNCTION
1684
+ '''mid_str_func : MID_STR_LPAREN expr COMMA expr RPAREN
1685
+ | MID_STR_LPAREN expr COMMA expr COMMA expr RPAREN'''
1686
+ if len(p) == 6:
1687
+ p[0] = MidStrFunc(source = p[2], position = p[4])
1688
+ elif len(p) == 8:
1689
+ p[0] = MidStrFunc(source = p[2], position = p[4], length = p[6])
1690
+ p[0].lineNum = p.lineno(1) - 1
1691
+
1692
+ def p_mod_func(p):
1693
+ 'mod_func : MOD array %prec FUNCTION'
1694
+ p[0] = ArrayRootMeanSquare(p[2])
1695
+ p[0].lineNum = p.lineno(1) - 1
1696
+
1697
+ def p_mode_func(p):
1698
+ '''mode_func : MODE %prec FUNCTION'''
1699
+ p[0] = ModeFunc()
1700
+ p[0].lineNum = p.lineno(1) - 1
1701
+
1702
+ def p_not_func(p):
1703
+ 'not_func : NOT factor %prec FUNCTION'
1704
+ p[0] = Not(factor = p[2])
1705
+ p[0].lineNum = p.lineno(1) - 1
1706
+
1707
+ def p_openin_func(p):
1708
+ '''openin_func : OPENIN factor %prec FUNCTION'''
1709
+ p[0] = OpeninFunc(filename = p[2])
1710
+ p[0].lineNum = p.lineno(1) - 1
1711
+
1712
+ def p_openout_func(p):
1713
+ '''openout_func : OPENOUT factor %prec FUNCTION'''
1714
+ p[0] = OpenoutFunc(filename = p[2])
1715
+ p[0].lineNum = p.lineno(1) - 1
1716
+
1717
+ def p_openup_func(p):
1718
+ '''openup_func : OPENUP factor %prec FUNCTION'''
1719
+ p[0] = OpenupFunc(filename = p[2])
1720
+ p[0].lineNum = p.lineno(1) - 1
1721
+
1722
+ def p_pos_func(p):
1723
+ '''pos_func : POS %prec FUNCTION'''
1724
+ p[0] = PosFunc()
1725
+ p[0].lineNum = p.lineno(1) - 1
1726
+
1727
+ def p_pi_func(p):
1728
+ '''pi_func : PI %prec FUNCTION'''
1729
+ p[0] = PiFunc()
1730
+ p[0].lineNum = p.lineno(1) - 1
1731
+
1732
+ def p_point_func(p):
1733
+ '''point_func : POINT_LPAREN expr COMMA expr RPAREN %prec FUNCTION'''
1734
+ p[0] = PointFunc(xCoord = p[2] , yCoord = p[4])
1735
+ p[0].lineNum = p.lineno(1) - 1
1736
+
1737
+ def p_quit_func(p):
1738
+ '''quit_func : QUIT %prec FUNCTION'''
1739
+ p[0] = QuitFunc()
1740
+ p[0].lineNum = p.lineno(1) - 1
1741
+
1742
+ def p_rad_func(p):
1743
+ 'rad_func : RAD factor %prec FUNCTION'
1744
+ p[0] = RadFunc(factor = p[2])
1745
+ p[0].lineNum = p.lineno(1) - 1
1746
+
1747
+ def p_report_str_func(p):
1748
+ 'report_str_func : REPORT_STR %prec FUNCTION'
1749
+ p[0] = ReportStrFunc()
1750
+ p[0].lineNum = p.lineno(1) - 1
1751
+
1752
+ def p_right_str_func(p):
1753
+ '''right_str_func : RIGHT_STR_LPAREN expr RPAREN
1754
+ | RIGHT_STR_LPAREN expr COMMA expr RPAREN'''
1755
+ if len(p) == 4:
1756
+ p[0] = RightStrFunc(source = p[2])
1757
+ elif len(p) == 6:
1758
+ p[0] = RightStrFunc(source = p[2], length = p[4])
1759
+ p[0].lineNum = p.lineno(1) - 1
1760
+
1761
+ def p_rnd_func(p):
1762
+ '''rnd_func : RND %prec FUNCTION
1763
+ | RND_LPAREN expr RPAREN %prec FUNCTION'''
1764
+ if len(p) == 2:
1765
+ #RND
1766
+ p[0] = RndFunc(option=None)
1767
+ elif len(p) == 4:
1768
+ #RND expression
1769
+ p[0] = RndFunc(option = p[2])
1770
+ p[0].lineNum = p.lineno(1) - 1
1771
+
1772
+ def p_sin_func(p):
1773
+ 'sin_func : SIN factor %prec FUNCTION'
1774
+ p[0] = SinFunc(factor = p[2])
1775
+ p[0].lineNum = p.lineno(1) - 1
1776
+
1777
+ def p_sgn_func(p):
1778
+ 'sgn_func : SGN factor %prec FUNCTION'
1779
+ p[0] = SgnFunc(factor = p[2])
1780
+ p[0].lineNum = p.lineno(1) - 1
1781
+
1782
+ def p_sqr_func(p):
1783
+ 'sqr_func : SQR factor %prec FUNCTION'
1784
+ p[0] = SqrFunc(factor = p[2])
1785
+ p[0].lineNum = p.lineno(1) - 1
1786
+
1787
+ def p_str_str_func(p):
1788
+ '''str_str_func : str_str_dec_func
1789
+ | str_str_hex_func'''
1790
+ p[0] = p[1]
1791
+ p[0].lineNum = p.lineno(1) - 1
1792
+
1793
+ def p_str_str_dec_func(p):
1794
+ 'str_str_dec_func : STR_STR expr %prec FUNCTION'
1795
+ p[0] = StrStringFunc(factor = p[2], base = 10)
1796
+ p[0].lineNum = p.lineno(1) - 1
1797
+
1798
+ def p_str_str_hex_func(p):
1799
+ 'str_str_hex_func : STR_STR TILDE expr %prec FUNCTION'
1800
+ p[0] = StrStringFunc(factor = p[2], base = 16)
1801
+ p[0].lineNum = p.lineno(1) - 1
1802
+
1803
+ def p_sum_func(p):
1804
+ 'sum_func : SUM array %prec FUNCTION'
1805
+ # TODO: Accept factor and type check for array
1806
+ p[0] = Sum(array = p[2])
1807
+ p[0].lineNum = p.lineno(1) - 1
1808
+
1809
+ def p_sumlen_func(p):
1810
+ 'sumlen_func : SUMLEN array %prec FUNCTION'
1811
+ # TODO: Accept factor and type check for array
1812
+ p[0] = SumLenFunc(array = p[2])
1813
+ p[0].lineNum = p.lineno(1) - 1
1814
+
1815
+ def p_tan_func(p):
1816
+ 'tan_func : TAN factor %prec FUNCTION'
1817
+ p[0] = TanFunc(factor = p[2])
1818
+ p[0].lineNum = p.lineno(1) - 1
1819
+
1820
+ def p_tempo_func(p):
1821
+ '''tempo_func : TEMPO %prec FUNCTION'''
1822
+ p[0] = TempoFunc()
1823
+ p[0].lineNum = p.lineno(1) - 1
1824
+
1825
+ def p_tint_func(p):
1826
+ # TODO: The first of these is a statement
1827
+ '''tint_func : TINT LPAREN expr COMMA expr RPAREN %prec FUNCTION'''
1828
+ #TINT ( x, y )
1829
+ p[0] = TintFunc(xCoord = p[3] ,yCoord = p[5])
1830
+ p[0].lineNum = p.lineno(1) - 1
1831
+
1832
+ def p_top_func(p):
1833
+ '''top_func : TOP'''
1834
+ p[0] = TopFunc()
1835
+ p[0].lineNum = p.lineno(1) - 1
1836
+
1837
+ def p_true_func(p):
1838
+ '''true_func : TRUE'''
1839
+ p[0] = TrueFunc()
1840
+ p[0].lineNum = p.lineno(1) - 1
1841
+
1842
+ def p_val_func(p):
1843
+ '''val_func : VAL expr %prec FUNCTION'''
1844
+ p[0] = ValFunc(factor = p[2])
1845
+ p[0].lineNum = p.lineno(1) - 1
1846
+
1847
+ def p_vpos_func(p):
1848
+ '''vpos_func : VPOS %prec FUNCTION'''
1849
+ p[0] = VposFunc()
1850
+ p[0].lineNum = p.lineno(1) - 1
1851
+
1852
+ def p_width_func(p):
1853
+ 'width_func : WIDTH %prec FUNCTION'
1854
+ p[0] = WidthFunc()
1855
+ p[0].lineNum = p.lineno(1) - 1
1856
+
1857
+ #=============================================================================#
1858
+ # CHANNEL
1859
+ #
1860
+
1861
+ # Channels
1862
+ def p_channel(p):
1863
+ '''channel : HASH factor %prec UHASH'''
1864
+ p[0] = Channel(channel = p[2])
1865
+ p[0].lineNum = p.lineno(1) - 1
1866
+
1867
+
1868
+ #=============================================================================#
1869
+ # VARIABLE
1870
+
1871
+ def p_variable(p):
1872
+ 'variable : ID'
1873
+ p[0] = Variable(identifier = p[1])
1874
+ p[0].lineNum = p.lineno(1) - 1
1875
+
1876
+ def p_variable_list(p):
1877
+ '''variable_list : variable
1878
+ | variable_list COMMA variable'''
1879
+ if len(p) == 2:
1880
+ p[0] = VariableList()
1881
+ p[0].append(p[1])
1882
+ elif len(p) == 4:
1883
+ p[1].append(p[3])
1884
+ p[0] = p[1]
1885
+
1886
+ def p_nullable_variable(p):
1887
+ '''nullable_variable : variable
1888
+ | empty'''
1889
+ p[0] = p[1]
1890
+
1891
+ def p_nullable_variable_list(p):
1892
+ '''nullable_variable_list : nullable_variable
1893
+ | nullable_variable_list COMMA nullable_variable'''
1894
+ if len(p) == 2:
1895
+ p[0] = VariableList()
1896
+ p[0].append(p[1])
1897
+ elif len(p) == 4:
1898
+ p[1].append(p[3])
1899
+ p[0] = p[1]
1900
+
1901
+ def p_nullable_writable(p):
1902
+ '''nullable_writable : writable
1903
+ | empty'''
1904
+ p[0] = p[1]
1905
+
1906
+ def p_nullable_writable_list(p):
1907
+ '''nullable_writable_list : nullable_writable
1908
+ | nullable_writable_list COMMA nullable_writable'''
1909
+ if len(p) == 2:
1910
+ p[0] = WritableList()
1911
+ p[0].append(p[1])
1912
+ elif len(p) == 4:
1913
+ p[1].append(p[3])
1914
+ p[0] = p[1]
1915
+ #=============================================================================#
1916
+ # ARRAYS
1917
+
1918
+ # Array support
1919
+ def p_array(p):
1920
+ 'array : ARRAYID_LPAREN RPAREN'
1921
+ p[0] = Array(identifier = p[1])
1922
+ p[0].lineNum = p.lineno(1) - 1
1923
+
1924
+ def p_indexer(p):
1925
+ 'indexer : ARRAYID_LPAREN expr_list RPAREN'
1926
+ p[0] = Indexer(identifier = p[1], indices = p[2])
1927
+ p[0].lineNum = p.lineno(1) - 1
1928
+
1929
+ #=============================================================================#
1930
+ # LITERALS
1931
+
1932
+ def p_literal(p):
1933
+ '''literal : literal_string
1934
+ | literal_integer
1935
+ | literal_float'''
1936
+ p[0] = p[1]
1937
+
1938
+ def p_literal_string(p):
1939
+ 'literal_string : LITERAL_STRING'
1940
+ p[0] = LiteralString(value = p[1])
1941
+ p[0].lineNum = p.lineno(1) - 1
1942
+
1943
+ def p_literal_integer(p):
1944
+ 'literal_integer : LITERAL_INTEGER'
1945
+ p[0] = LiteralInteger(value = p[1])
1946
+ p[0].lineNum = p.lineno(1) - 1
1947
+
1948
+ def p_literal_float(p):
1949
+ 'literal_float : LITERAL_FLOAT'
1950
+ p[0] = LiteralFloat(value = p[1])
1951
+ p[0].lineNum = p.lineno(1) - 1
1952
+
1953
+ #=============================================================================#
1954
+ # STAR COMMANDS
1955
+
1956
+
1957
+ #=============================================================================#
1958
+ # EMPTY PRODUCTION
1959
+
1960
+ def p_empty(p):
1961
+ 'empty :'
1962
+ p[0] = None
1963
+
1964
+ #=============================================================================#
1965
+ # ERRORS
1966
+
1967
+ # Error rule for syntax errors
1968
+ def p_error(p):
1969
+ if p is None:
1970
+ logging.error("Syntax error at end of input (unexpected EOF)")
1971
+ else:
1972
+ logging.error("Syntax error at %r (physical line %s)", p.value, p.lineno)