basic101 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -0
  3. data/Changelog.md +9 -1
  4. data/Gemfile +9 -8
  5. data/Gemfile.lock +66 -53
  6. data/README.md +8 -6
  7. data/VERSION +1 -1
  8. data/basic101.gemspec +688 -0
  9. data/lib/basic101/parser.rb +28 -457
  10. data/lib/basic101/parser/data_statement.rb +20 -0
  11. data/lib/basic101/parser/define_function_statement.rb +18 -0
  12. data/lib/basic101/parser/dim_statement.rb +16 -0
  13. data/lib/basic101/parser/end_statement.rb +11 -0
  14. data/lib/basic101/parser/expression.rb +100 -0
  15. data/lib/basic101/parser/for_statement.rb +17 -0
  16. data/lib/basic101/parser/function_call.rb +13 -0
  17. data/lib/basic101/parser/gosub_statement.rb +12 -0
  18. data/lib/basic101/parser/goto_statement.rb +11 -0
  19. data/lib/basic101/parser/identifier.rb +87 -0
  20. data/lib/basic101/parser/if_statement.rb +20 -0
  21. data/lib/basic101/parser/input_statement.rb +19 -0
  22. data/lib/basic101/parser/let_statement.rb +13 -0
  23. data/lib/basic101/parser/next_statement.rb +16 -0
  24. data/lib/basic101/parser/numeric.rb +34 -0
  25. data/lib/basic101/parser/on_goto_statement.rb +20 -0
  26. data/lib/basic101/parser/print_statement.rb +19 -0
  27. data/lib/basic101/parser/program.rb +17 -0
  28. data/lib/basic101/parser/randomize_statement.rb +11 -0
  29. data/lib/basic101/parser/read_statement.rb +12 -0
  30. data/lib/basic101/parser/reference.rb +36 -0
  31. data/lib/basic101/parser/remark_statement.rb +11 -0
  32. data/lib/basic101/parser/restore_statement.rb +12 -0
  33. data/lib/basic101/parser/return_statement.rb +11 -0
  34. data/lib/basic101/parser/space.rb +23 -0
  35. data/lib/basic101/parser/statements.rb +36 -0
  36. data/lib/basic101/parser/stop_statement.rb +11 -0
  37. data/lib/basic101/parser/string.rb +17 -0
  38. data/test/spec/basic_float_spec.rb +2 -2
  39. data/test/spec/basic_object_spec.rb +1 -1
  40. data/test/spec/basic_string_spec.rb +2 -2
  41. data/test/spec/input_reader_spec.rb +11 -11
  42. data/test/spec/input_spec.rb +5 -5
  43. data/test/spec/output_spec.rb +3 -3
  44. data/test/spec/spec_helper.rb +2 -1
  45. data/test/spec/support/basic_numeric_helpers.rb +3 -3
  46. metadata +82 -34
@@ -1,457 +1,28 @@
1
- module Basic101
2
-
3
- class Parser < Parslet::Parser
4
-
5
- rule(:space) do
6
- match(' ').repeat(1)
7
- end
8
-
9
- rule(:new_line) do
10
- str("\r").maybe >> str("\n")
11
- end
12
-
13
- rule(:space?) do
14
- space.maybe
15
- end
16
-
17
- rule(:printable) do
18
- match('[[:print:]]')
19
- end
20
-
21
- rule(:decimal) do
22
- match('[0-9]').repeat(1)
23
- end
24
-
25
- rule(:sign) do
26
- match('[+-]')
27
- end
28
-
29
- rule(:integer) do
30
- (sign.maybe >> decimal).as(:integer)
31
- end
32
-
33
- rule(:fixed) do
34
- sign.maybe >>
35
- (decimal >> str('.') >> decimal.maybe) |
36
- (str('.') >> decimal)
37
- end
38
-
39
- rule(:exponent) do
40
- str('E') >> sign.maybe >> decimal
41
- end
42
-
43
- rule(:float) do
44
- (fixed >> exponent.maybe |
45
- sign.maybe >> decimal >> exponent).as(:float)
46
- end
47
-
48
- rule(:unquoted_string) do
49
- match('(?=[[:print:]])[^,": ]').repeat(0).as(:string)
50
- end
51
-
52
- rule(:quoted_string) do
53
- str('"') >>
54
- match('(?=[[:print:]])[^"]').repeat(0).maybe.as(:string) >>
55
- str('"')
56
- end
57
-
58
- rule(:user_defined_function_identifier) do
59
- (str('FN') >> base_identifier >>
60
- str('$').maybe).as(:function_identifier)
61
- end
62
-
63
- rule(:built_in_function_identifier) do
64
- (str('ABS') |
65
- str('ASC') |
66
- str('CHR$') |
67
- str('COS') |
68
- str('EXP') |
69
- str('INT') |
70
- str('LEFT$') |
71
- str('LEN') |
72
- str('LOG') |
73
- str('MID$') |
74
- str('RIGHT$') |
75
- str('RND') |
76
- str('SGN') |
77
- str('SIN') |
78
- str('SQR') |
79
- str('STR$') |
80
- str('TAB') |
81
- str('TAN') |
82
- str('VAL')).as(:function_identifier)
83
- end
84
-
85
- rule(:function_identifier) do
86
- user_defined_function_identifier |
87
- built_in_function_identifier
88
- end
89
-
90
- rule(:keyword) do
91
- str('AND') |
92
- str('DATA') |
93
- str('DEF') |
94
- str('DIM') |
95
- str('ELSE') |
96
- str('ELSE') |
97
- str('END') |
98
- str('FOR') |
99
- str('GOSUB') |
100
- str('GOTO') |
101
- str('GOTO') |
102
- str('IF') |
103
- str('INPUT') |
104
- str('LET') |
105
- str('NEXT') |
106
- str('NOT') |
107
- str('ON') |
108
- str('OR') |
109
- str('PRINT') |
110
- str('RANDOMIZE') |
111
- str('READ') |
112
- str('REM') |
113
- str('RESTORE') |
114
- str('RETURN') |
115
- str('STEP') |
116
- str('STOP') |
117
- str('THEN') |
118
- str('TO')
119
- end
120
-
121
- rule(:base_identifier) do
122
- (keyword.absent? >> match('[A-Z]')) >>
123
- (keyword.absent? >> match('[A-Z0-9]')).repeat(0)
124
- end
125
-
126
- rule(:numeric_identifier) do
127
- base_identifier.as(:numeric_identifier)
128
- end
129
-
130
- rule(:string_identifier) do
131
- (base_identifier >> str('$')).as(:string_identifier)
132
- end
133
-
134
- rule(:identifier) do
135
- string_identifier | numeric_identifier
136
- end
137
-
138
- rule(:argument_list) do
139
- expression >> (space? >> str(',') >> space? >> expression).repeat(0)
140
- end
141
-
142
- rule(:array_reference) do
143
- identifier.as(:subscript_base) >> space? >>
144
- str('(') >> space? >> argument_list.as(:argument_list) >>
145
- space? >> str(')')
146
- end
147
-
148
- rule(:scalar_reference) do
149
- identifier.as(:scalar_reference)
150
- end
151
-
152
- rule(:reference) do
153
- array_reference | scalar_reference
154
- end
155
-
156
- rule(:scalar_reference_list) do
157
- scalar_reference >>
158
- (space? >> str(',') >>
159
- space? >> scalar_reference).repeat(0)
160
- end
161
-
162
- rule(:reference_list) do
163
- reference >> (space? >> str(',') >> space? >> reference).repeat(0)
164
- end
165
-
166
- rule(:let_statement) do
167
- (str('LET') >> space?).maybe >>
168
- reference.as(:lvalue) >> space? >>
169
- str('=') >> space? >> expression.as(:rvalue)
170
- end
171
-
172
- rule(:multiply_op) do
173
- (str('*').as(:multiply) |
174
- str('/').as(:divide))
175
- end
176
-
177
- rule(:addition_op) do
178
- (str('+').as(:add) |
179
- str('-').as(:subtract))
180
- end
181
-
182
- rule(:comparison_op) do
183
- (str('=').as(:eq) |
184
- str('<>').as(:ne) |
185
- str('>=').as(:ge) |
186
- str('<=').as(:le)) |
187
- str('<').as(:lt) |
188
- str('>').as(:gt)
189
- end
190
-
191
- rule(:and_op) do
192
- str('AND').as(:and)
193
- end
194
-
195
- rule(:or_op) do
196
- str('OR').as(:or)
197
- end
198
-
199
- rule(:function_call) do
200
- function_identifier.as(:function_identifier) >> space? >>
201
- str('(') >> space? >> argument_list.as(:argument_list) >>
202
- space? >> str(')')
203
- end
204
-
205
- rule(:factor) do
206
- quoted_string |
207
- float |
208
- integer |
209
- function_call |
210
- reference |
211
- str('(') >> space? >> expression >> space? >> str(')')
212
- end
213
-
214
- rule(:power) do
215
- (factor.as(:left) >>
216
- space? >> str('^').as(:power) >>
217
- space? >> power.as(:right)) |
218
- factor
219
- end
220
-
221
- rule(:negation) do
222
- (str('-') >>
223
- space? >> power).as(:negation) |
224
- power
225
- end
226
-
227
- rule(:term) do
228
- negation.as(:left) >>
229
- (space? >> multiply_op.as(:operator) >>
230
- space? >> negation.as(:right)
231
- ).repeat(1).as(:operations).maybe
232
- end
233
-
234
- rule(:simple_expression) do
235
- term.as(:left) >>
236
- (space? >> addition_op.as(:operator) >>
237
- space? >> term.as(:right)
238
- ).repeat(1).as(:operations).maybe
239
- end
240
-
241
- rule(:comparison_expression) do
242
- simple_expression.as(:left) >>
243
- (space? >> comparison_op.as(:operator) >>
244
- space? >> simple_expression.as(:right)
245
- ).repeat(1).as(:operations).maybe
246
- end
247
-
248
- rule(:not_expression) do
249
- (str('NOT') >> space? >> comparison_expression).as(:not) |
250
- comparison_expression
251
- end
252
-
253
- rule(:and_expression) do
254
- not_expression.as(:left) >>
255
- (space? >> and_op.as(:operator) >>
256
- space? >> not_expression.as(:right)
257
- ).repeat(1).as(:operations).maybe
258
- end
259
-
260
- rule(:or_expression) do
261
- and_expression.as(:left) >>
262
- (space? >> or_op.as(:operator) >>
263
- space? >> and_expression.as(:right)
264
- ).repeat(1).as(:operations).maybe
265
- end
266
-
267
- rule(:expression) do
268
- or_expression
269
- end
270
-
271
- rule(:remark_statement) do
272
- (str('REM') >> printable.repeat(0)).as(:remark)
273
- end
274
-
275
- rule(:print_separator) do
276
- match('[;,]').as(:print_separator)
277
- end
278
-
279
- rule(:print_arguments) do
280
- (space? >> (expression | print_separator)).repeat(0)
281
- end
282
-
283
- rule(:print_separator) do
284
- match('[;,]').as(:print_separator)
285
- end
286
-
287
- rule(:print_statement) do
288
- str('PRINT').as(:print) >> print_arguments.as(:print_arguments)
289
- end
290
-
291
- rule(:goto_statement) do
292
- str('GOTO').as(:goto) >> space? >> integer
293
- end
294
-
295
- rule(:if_block) do
296
- (integer.as(:if_line_number) |
297
- statements)
298
- end
299
-
300
- rule(:if_statement) do
301
- str('IF').as(:if) >>
302
- space? >> expression.as(:condition) >>
303
- (space? >> str('THEN')).maybe >>
304
- space? >> if_block.as(:then_block) >>
305
- (space? >> str('ELSE') >> space? >> if_block).maybe.as(:else_block)
306
- end
307
-
308
- rule(:randomize_statement) do
309
- str('RANDOMIZE').as(:randomize)
310
- end
311
-
312
- rule(:prompt_delimeter) do
313
- str(';').as(:prompt_delimeter) |
314
- str(',').as(:null_prompt_delimeter)
315
- end
316
-
317
- rule(:input_statement) do
318
- str('INPUT').as(:input) >>
319
- (space? >> quoted_string.as(:prompt) >>
320
- space? >> prompt_delimeter.as(:prompt_delimeter)).maybe >>
321
- space? >> reference_list.as(:references)
322
- end
323
-
324
- rule(:end_statement) do
325
- str('END').as(:end)
326
- end
327
-
328
- rule(:dim_statement) do
329
- str('DIM').as(:dim) >>
330
- (space? >> array_reference >>
331
- (space? >> str(',') >>
332
- space? >> array_reference
333
- ).repeat(0)
334
- ).as(:references)
335
- end
336
-
337
- rule(:for_statement) do
338
- str('FOR') >>
339
- space? >> scalar_reference.as(:reference) >>
340
- space? >> str('=') >>
341
- space? >> expression.as(:from) >>
342
- space? >> str('TO') >>
343
- space? >> expression.as(:to) >>
344
- (space? >> str('STEP') >> space? >> expression).maybe.as(:step)
345
- end
346
-
347
- rule(:next_statement) do
348
- str('NEXT').as(:next) >>
349
- (space? >> reference >>
350
- (space? >> str(',') >>
351
- space? >> reference
352
- ).repeat(0)
353
- ).maybe.as(:references)
354
- end
355
-
356
- rule(:on_goto_statement) do
357
- str('ON').as(:on_goto) >>
358
- space? >>expression.as(:expression) >>
359
- space? >> str('GOTO') >>
360
- (
361
- space? >> integer >>
362
- (
363
- space? >> str(',') >>
364
- space? >> integer
365
- ).repeat(0)
366
- ).as(:line_numbers)
367
- end
368
-
369
- rule(:data_item) do
370
- float | integer | quoted_string | unquoted_string
371
- end
372
-
373
- rule(:data_statement) do
374
- str('DATA') >>
375
- (space? >> data_item >>
376
- (space? >> str(',') >>
377
- space? >> data_item
378
- ).repeat(0)
379
- ).as(:data_items)
380
- end
381
-
382
- rule(:read_statement) do
383
- str('READ').as(:read) >>
384
- space? >> reference_list.as(:references)
385
- end
386
-
387
- rule(:gosub_statement) do
388
- str('GOSUB').as(:gosub) >>
389
- space? >> integer.as(:line_number)
390
- end
391
-
392
- rule(:return_statement) do
393
- str('RETURN').as(:return)
394
- end
395
-
396
- rule(:stop_statement) do
397
- str('STOP').as(:stop)
398
- end
399
-
400
- rule(:restore_statement) do
401
- str('RESTORE').as(:restore) >>
402
- (space? >> integer).maybe.as(:line_number)
403
- end
404
-
405
- rule(:define_function_statement) do
406
- str('DEF').as(:def) >>
407
- space? >> user_defined_function_identifier.as(:identifier) >>
408
- (space? >> str('(') >>
409
- space? >> scalar_reference_list >>
410
- space? >> str(')')
411
- ).as(:parameters) >>
412
- space? >> str('=') >>
413
- space? >> expression.as(:expression)
414
- end
415
-
416
- rule(:statement) do
417
- (goto_statement |
418
- remark_statement |
419
- print_statement |
420
- if_statement |
421
- randomize_statement |
422
- input_statement |
423
- end_statement |
424
- dim_statement |
425
- for_statement |
426
- next_statement |
427
- on_goto_statement |
428
- data_statement |
429
- read_statement |
430
- gosub_statement |
431
- return_statement |
432
- stop_statement |
433
- restore_statement |
434
- define_function_statement |
435
- let_statement)
436
- end
437
-
438
- rule(:statements) do
439
- statement >>
440
- (space? >> str(':') >>
441
- space? >> statement).repeat(0) >>
442
- space? >> str(':').maybe
443
- end
444
-
445
- rule(:line) do
446
- (integer >> space? >> statements.as(:statements))
447
- end
448
-
449
- rule(:program) do
450
- ((line >> (new_line >> line).repeat(0) >> new_line.maybe).maybe).as(:program)
451
- end
452
-
453
- root(:program)
454
-
455
- end
456
-
457
- end
1
+ require_relative 'parser/data_statement'
2
+ require_relative 'parser/define_function_statement'
3
+ require_relative 'parser/dim_statement'
4
+ require_relative 'parser/end_statement'
5
+ require_relative 'parser/expression'
6
+ require_relative 'parser/for_statement'
7
+ require_relative 'parser/function_call'
8
+ require_relative 'parser/gosub_statement'
9
+ require_relative 'parser/goto_statement'
10
+ require_relative 'parser/identifier'
11
+ require_relative 'parser/if_statement'
12
+ require_relative 'parser/input_statement'
13
+ require_relative 'parser/let_statement'
14
+ require_relative 'parser/next_statement'
15
+ require_relative 'parser/numeric'
16
+ require_relative 'parser/on_goto_statement'
17
+ require_relative 'parser/print_statement'
18
+ require_relative 'parser/program'
19
+ require_relative 'parser/randomize_statement'
20
+ require_relative 'parser/read_statement'
21
+ require_relative 'parser/reference'
22
+ require_relative 'parser/remark_statement'
23
+ require_relative 'parser/restore_statement'
24
+ require_relative 'parser/return_statement'
25
+ require_relative 'parser/space'
26
+ require_relative 'parser/statements'
27
+ require_relative 'parser/stop_statement'
28
+ require_relative 'parser/string'