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
@@ -0,0 +1,20 @@
1
+ module Basic101
2
+
3
+ class Parser < Parslet::Parser
4
+
5
+ rule(:data_statement) do
6
+ str('DATA') >>
7
+ (space? >> data_item >>
8
+ (space? >> str(',') >>
9
+ space? >> data_item
10
+ ).repeat(0)
11
+ ).as(:data_items)
12
+ end
13
+
14
+ rule(:data_item) do
15
+ float | integer | quoted_string | unquoted_string
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,18 @@
1
+ module Basic101
2
+
3
+ class Parser < Parslet::Parser
4
+
5
+ rule(:define_function_statement) do
6
+ str('DEF').as(:def) >>
7
+ space? >> user_defined_function_identifier.as(:identifier) >>
8
+ (space? >> str('(') >>
9
+ space? >> scalar_reference_list >>
10
+ space? >> str(')')
11
+ ).as(:parameters) >>
12
+ space? >> str('=') >>
13
+ space? >> expression.as(:expression)
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,16 @@
1
+ module Basic101
2
+
3
+ class Parser < Parslet::Parser
4
+
5
+ rule(:dim_statement) do
6
+ str('DIM').as(:dim) >>
7
+ (space? >> array_reference >>
8
+ (space? >> str(',') >>
9
+ space? >> array_reference
10
+ ).repeat(0)
11
+ ).as(:references)
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,11 @@
1
+ module Basic101
2
+
3
+ class Parser < Parslet::Parser
4
+
5
+ rule(:end_statement) do
6
+ str('END').as(:end)
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,100 @@
1
+ module Basic101
2
+
3
+ class Parser < Parslet::Parser
4
+
5
+ rule(:multiply_op) do
6
+ (str('*').as(:multiply) |
7
+ str('/').as(:divide))
8
+ end
9
+
10
+ rule(:addition_op) do
11
+ (str('+').as(:add) |
12
+ str('-').as(:subtract))
13
+ end
14
+
15
+ rule(:comparison_op) do
16
+ (str('=').as(:eq) |
17
+ str('<>').as(:ne) |
18
+ str('>=').as(:ge) |
19
+ str('<=').as(:le)) |
20
+ str('<').as(:lt) |
21
+ str('>').as(:gt)
22
+ end
23
+
24
+ rule(:and_op) do
25
+ str('AND').as(:and)
26
+ end
27
+
28
+ rule(:or_op) do
29
+ str('OR').as(:or)
30
+ end
31
+
32
+ rule(:factor) do
33
+ quoted_string |
34
+ float |
35
+ integer |
36
+ function_call |
37
+ reference |
38
+ str('(') >> space? >> expression >> space? >> str(')')
39
+ end
40
+
41
+ rule(:power) do
42
+ (factor.as(:left) >>
43
+ space? >> str('^').as(:power) >>
44
+ space? >> power.as(:right)) |
45
+ factor
46
+ end
47
+
48
+ rule(:negation) do
49
+ (str('-') >>
50
+ space? >> power).as(:negation) |
51
+ power
52
+ end
53
+
54
+ rule(:term) do
55
+ negation.as(:left) >>
56
+ (space? >> multiply_op.as(:operator) >>
57
+ space? >> negation.as(:right)
58
+ ).repeat(1).as(:operations).maybe
59
+ end
60
+
61
+ rule(:simple_expression) do
62
+ term.as(:left) >>
63
+ (space? >> addition_op.as(:operator) >>
64
+ space? >> term.as(:right)
65
+ ).repeat(1).as(:operations).maybe
66
+ end
67
+
68
+ rule(:comparison_expression) do
69
+ simple_expression.as(:left) >>
70
+ (space? >> comparison_op.as(:operator) >>
71
+ space? >> simple_expression.as(:right)
72
+ ).repeat(1).as(:operations).maybe
73
+ end
74
+
75
+ rule(:not_expression) do
76
+ (str('NOT') >> space? >> comparison_expression).as(:not) |
77
+ comparison_expression
78
+ end
79
+
80
+ rule(:and_expression) do
81
+ not_expression.as(:left) >>
82
+ (space? >> and_op.as(:operator) >>
83
+ space? >> not_expression.as(:right)
84
+ ).repeat(1).as(:operations).maybe
85
+ end
86
+
87
+ rule(:or_expression) do
88
+ and_expression.as(:left) >>
89
+ (space? >> or_op.as(:operator) >>
90
+ space? >> and_expression.as(:right)
91
+ ).repeat(1).as(:operations).maybe
92
+ end
93
+
94
+ rule(:expression) do
95
+ or_expression
96
+ end
97
+
98
+ end
99
+
100
+ end
@@ -0,0 +1,17 @@
1
+ module Basic101
2
+
3
+ class Parser < Parslet::Parser
4
+
5
+ rule(:for_statement) do
6
+ str('FOR') >>
7
+ space? >> scalar_reference.as(:reference) >>
8
+ space? >> str('=') >>
9
+ space? >> expression.as(:from) >>
10
+ space? >> str('TO') >>
11
+ space? >> expression.as(:to) >>
12
+ (space? >> str('STEP') >> space? >> expression).maybe.as(:step)
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,13 @@
1
+ module Basic101
2
+
3
+ class Parser < Parslet::Parser
4
+
5
+ rule(:function_call) do
6
+ function_identifier.as(:function_identifier) >> space? >>
7
+ str('(') >> space? >> argument_list.as(:argument_list) >>
8
+ space? >> str(')')
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,12 @@
1
+ module Basic101
2
+
3
+ class Parser < Parslet::Parser
4
+
5
+ rule(:gosub_statement) do
6
+ str('GOSUB').as(:gosub) >>
7
+ space? >> integer.as(:line_number)
8
+ end
9
+
10
+ end
11
+
12
+ end
@@ -0,0 +1,11 @@
1
+ module Basic101
2
+
3
+ class Parser < Parslet::Parser
4
+
5
+ rule(:goto_statement) do
6
+ str('GOTO').as(:goto) >> space? >> integer
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,87 @@
1
+ module Basic101
2
+
3
+ class Parser < Parslet::Parser
4
+
5
+ rule(:identifier) do
6
+ string_identifier | numeric_identifier
7
+ end
8
+
9
+ rule(:numeric_identifier) do
10
+ base_identifier.as(:numeric_identifier)
11
+ end
12
+
13
+ rule(:string_identifier) do
14
+ (base_identifier >> str('$')).as(:string_identifier)
15
+ end
16
+
17
+ rule(:function_identifier) do
18
+ user_defined_function_identifier |
19
+ built_in_function_identifier
20
+ end
21
+
22
+ rule(:user_defined_function_identifier) do
23
+ (str('FN') >> base_identifier >>
24
+ str('$').maybe).as(:function_identifier)
25
+ end
26
+
27
+ rule(:built_in_function_identifier) do
28
+ (str('ABS') |
29
+ str('ASC') |
30
+ str('CHR$') |
31
+ str('COS') |
32
+ str('EXP') |
33
+ str('INT') |
34
+ str('LEFT$') |
35
+ str('LEN') |
36
+ str('LOG') |
37
+ str('MID$') |
38
+ str('RIGHT$') |
39
+ str('RND') |
40
+ str('SGN') |
41
+ str('SIN') |
42
+ str('SQR') |
43
+ str('STR$') |
44
+ str('TAB') |
45
+ str('TAN') |
46
+ str('VAL')).as(:function_identifier)
47
+ end
48
+
49
+ rule(:base_identifier) do
50
+ (keyword.absent? >> match('[A-Z]')) >>
51
+ (keyword.absent? >> match('[A-Z0-9]')).repeat(0)
52
+ end
53
+
54
+ rule(:keyword) do
55
+ str('AND') |
56
+ str('DATA') |
57
+ str('DEF') |
58
+ str('DIM') |
59
+ str('ELSE') |
60
+ str('ELSE') |
61
+ str('END') |
62
+ str('FOR') |
63
+ str('GOSUB') |
64
+ str('GOTO') |
65
+ str('GOTO') |
66
+ str('IF') |
67
+ str('INPUT') |
68
+ str('LET') |
69
+ str('NEXT') |
70
+ str('NOT') |
71
+ str('ON') |
72
+ str('OR') |
73
+ str('PRINT') |
74
+ str('RANDOMIZE') |
75
+ str('READ') |
76
+ str('REM') |
77
+ str('RESTORE') |
78
+ str('RETURN') |
79
+ str('STEP') |
80
+ str('STOP') |
81
+ str('THEN') |
82
+ str('TO')
83
+ end
84
+
85
+ end
86
+
87
+ end
@@ -0,0 +1,20 @@
1
+ module Basic101
2
+
3
+ class Parser < Parslet::Parser
4
+
5
+ rule(:if_statement) do
6
+ str('IF').as(:if) >>
7
+ space? >> expression.as(:condition) >>
8
+ (space? >> str('THEN')).maybe >>
9
+ space? >> if_block.as(:then_block) >>
10
+ (space? >> str('ELSE') >> space? >> if_block).maybe.as(:else_block)
11
+ end
12
+
13
+ rule(:if_block) do
14
+ (integer.as(:if_line_number) |
15
+ statements)
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,19 @@
1
+ module Basic101
2
+
3
+ class Parser < Parslet::Parser
4
+
5
+ rule(:input_statement) do
6
+ str('INPUT').as(:input) >>
7
+ (space? >> quoted_string.as(:prompt) >>
8
+ space? >> prompt_delimeter.as(:prompt_delimeter)).maybe >>
9
+ space? >> reference_list.as(:references)
10
+ end
11
+
12
+ rule(:prompt_delimeter) do
13
+ str(';').as(:prompt_delimeter) |
14
+ str(',').as(:null_prompt_delimeter)
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,13 @@
1
+ module Basic101
2
+
3
+ class Parser < Parslet::Parser
4
+
5
+ rule(:let_statement) do
6
+ (str('LET') >> space?).maybe >>
7
+ reference.as(:lvalue) >> space? >>
8
+ str('=') >> space? >> expression.as(:rvalue)
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,16 @@
1
+ module Basic101
2
+
3
+ class Parser < Parslet::Parser
4
+
5
+ rule(:next_statement) do
6
+ str('NEXT').as(:next) >>
7
+ (space? >> reference >>
8
+ (space? >> str(',') >>
9
+ space? >> reference
10
+ ).repeat(0)
11
+ ).maybe.as(:references)
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,34 @@
1
+ module Basic101
2
+
3
+ class Parser < Parslet::Parser
4
+
5
+ rule(:float) do
6
+ (fixed >> exponent.maybe |
7
+ sign.maybe >> decimal >> exponent).as(:float)
8
+ end
9
+
10
+ rule(:integer) do
11
+ (sign.maybe >> decimal).as(:integer)
12
+ end
13
+
14
+ rule(:decimal) do
15
+ match('[0-9]').repeat(1)
16
+ end
17
+
18
+ rule(:sign) do
19
+ match('[+-]')
20
+ end
21
+
22
+ rule(:fixed) do
23
+ sign.maybe >>
24
+ (decimal >> str('.') >> decimal.maybe) |
25
+ (str('.') >> decimal)
26
+ end
27
+
28
+ rule(:exponent) do
29
+ str('E') >> sign.maybe >> decimal
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,20 @@
1
+ module Basic101
2
+
3
+ class Parser < Parslet::Parser
4
+
5
+ rule(:on_goto_statement) do
6
+ str('ON').as(:on_goto) >>
7
+ space? >>expression.as(:expression) >>
8
+ space? >> str('GOTO') >>
9
+ (
10
+ space? >> integer >>
11
+ (
12
+ space? >> str(',') >>
13
+ space? >> integer
14
+ ).repeat(0)
15
+ ).as(:line_numbers)
16
+ end
17
+
18
+ end
19
+
20
+ end