rltk 3.0.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +21 -22
  3. data/lib/rltk/ast.rb +185 -118
  4. data/lib/rltk/cfg.rb +157 -103
  5. data/lib/rltk/cg/basic_block.rb +19 -19
  6. data/lib/rltk/cg/bindings.rb +16 -16
  7. data/lib/rltk/cg/builder.rb +129 -129
  8. data/lib/rltk/cg/context.rb +7 -7
  9. data/lib/rltk/cg/contractor.rb +7 -7
  10. data/lib/rltk/cg/execution_engine.rb +30 -30
  11. data/lib/rltk/cg/function.rb +37 -37
  12. data/lib/rltk/cg/generated_bindings.rb +3932 -3932
  13. data/lib/rltk/cg/generic_value.rb +17 -17
  14. data/lib/rltk/cg/instruction.rb +116 -116
  15. data/lib/rltk/cg/llvm.rb +22 -22
  16. data/lib/rltk/cg/memory_buffer.rb +7 -7
  17. data/lib/rltk/cg/module.rb +73 -73
  18. data/lib/rltk/cg/pass_manager.rb +35 -35
  19. data/lib/rltk/cg/target.rb +41 -41
  20. data/lib/rltk/cg/triple.rb +7 -7
  21. data/lib/rltk/cg/type.rb +75 -75
  22. data/lib/rltk/cg/value.rb +161 -161
  23. data/lib/rltk/lexer.rb +57 -57
  24. data/lib/rltk/lexers/calculator.rb +7 -7
  25. data/lib/rltk/lexers/ebnf.rb +5 -5
  26. data/lib/rltk/parser.rb +338 -295
  27. data/lib/rltk/parsers/infix_calc.rb +7 -7
  28. data/lib/rltk/parsers/postfix_calc.rb +3 -3
  29. data/lib/rltk/parsers/prefix_calc.rb +3 -3
  30. data/lib/rltk/token.rb +13 -13
  31. data/lib/rltk/version.rb +6 -6
  32. data/test/cg/tc_basic_block.rb +17 -17
  33. data/test/cg/tc_control_flow.rb +41 -41
  34. data/test/cg/tc_function.rb +4 -4
  35. data/test/cg/tc_generic_value.rb +3 -3
  36. data/test/cg/tc_instruction.rb +53 -53
  37. data/test/cg/tc_math.rb +12 -12
  38. data/test/cg/tc_module.rb +14 -14
  39. data/test/cg/tc_transforms.rb +11 -11
  40. data/test/cg/tc_type.rb +12 -12
  41. data/test/cg/tc_value.rb +35 -35
  42. data/test/cg/ts_cg.rb +5 -5
  43. data/test/tc_ast.rb +137 -60
  44. data/test/tc_cfg.rb +34 -34
  45. data/test/tc_lexer.rb +42 -42
  46. data/test/tc_parser.rb +250 -173
  47. data/test/tc_token.rb +2 -2
  48. data/test/ts_rltk.rb +8 -8
  49. metadata +84 -85
  50. data/lib/rltk/cg/old_generated_bindings.rb +0 -6152
@@ -20,144 +20,144 @@ require 'rltk/cfg'
20
20
  class CFGTester < Minitest::Test
21
21
  def setup
22
22
  @grammar = RLTK::CFG.new
23
-
23
+
24
24
  @grammar.production(:s) do
25
25
  clause('A G D')
26
26
  clause('A a C')
27
27
  clause('B a D')
28
28
  clause('B G C')
29
29
  end
30
-
30
+
31
31
  @grammar.production(:a, 'b')
32
32
  @grammar.production(:b, 'G')
33
33
  end
34
-
34
+
35
35
  def test_callback
36
36
  grammar = RLTK::CFG.new
37
-
37
+
38
38
  call_count = 0
39
39
  grammar.callback do |type, which, p|
40
40
  refute_nil(p)
41
41
  assert_equal(type, :optional)
42
-
42
+
43
43
  case call_count
44
44
  when 0 then assert_equal(:empty, which)
45
45
  when 1 then assert_equal(:nonempty, which)
46
46
  end
47
-
47
+
48
48
  call_count += 1
49
49
  end
50
-
50
+
51
51
  grammar.production(:a, 'A?') { |a| a }
52
52
  assert_equal(2, call_count)
53
-
53
+
54
54
  call_count = 0
55
55
  grammar.callback do |type, which, p|
56
56
  refute_nil(p)
57
-
57
+
58
58
  case call_count
59
59
  when 0
60
60
  assert_equal(:elp, type)
61
61
  assert_equal(:empty, which)
62
-
62
+
63
63
  when 1
64
64
  assert_equal(:elp, type)
65
65
  assert_equal(:nonempty, which)
66
-
66
+
67
67
  when 2
68
68
  assert_equal(:nelp, type)
69
69
  assert_equal(:single, which)
70
-
70
+
71
71
  when 3
72
72
  assert_equal(:nelp, type)
73
73
  assert_equal(:multiple, which)
74
74
  end
75
-
75
+
76
76
  call_count += 1
77
77
  end
78
-
78
+
79
79
  grammar.production(:a, 'A*') { |a| a }
80
80
  assert_equal(4, call_count)
81
-
81
+
82
82
  call_count = 0
83
83
  grammar.callback do |type, which, p|
84
84
  refute_nil(p)
85
85
  assert_equal(type, :nelp)
86
-
86
+
87
87
  case call_count
88
88
  when 0 then assert_equal(:single, which)
89
89
  when 1 then assert_equal(:multiple, which)
90
90
  end
91
-
91
+
92
92
  call_count += 1
93
93
  end
94
-
94
+
95
95
  grammar.production(:a, 'A+') { |a| a }
96
96
  assert_equal(2, call_count)
97
97
  end
98
-
98
+
99
99
  def test_first_set
100
100
  @grammar.first_set(:s).each do |sym|
101
101
  assert_includes([:A, :B], sym)
102
102
  end
103
-
103
+
104
104
  assert_equal([:G], @grammar.first_set(:b))
105
105
  assert_equal([:G], @grammar.first_set(:a))
106
106
  end
107
-
107
+
108
108
  def test_follow_set
109
109
  assert_equal(@grammar.follow_set(:s), [:EOS])
110
-
110
+
111
111
  @grammar.follow_set(:a).each do |sym|
112
112
  assert([:C, :D].include?(sym))
113
113
  end
114
-
114
+
115
115
  @grammar.follow_set(:b).each do |sym|
116
116
  assert([:C, :D].include?(sym))
117
117
  end
118
118
  end
119
-
119
+
120
120
  def test_is_nonterminal
121
121
  assert(RLTK::CFG::is_nonterminal?(:lowercase))
122
122
  assert(!RLTK::CFG::is_nonterminal?(:UPERCASE))
123
123
  end
124
-
124
+
125
125
  def test_is_terminal
126
126
  assert(!RLTK::CFG::is_terminal?(:lowercase))
127
127
  assert(RLTK::CFG::is_terminal?(:UPERCASE))
128
128
  end
129
-
129
+
130
130
  def test_item
131
131
  i0 = RLTK::CFG::Item.new(0, 0, :a, [:b, :C, :D, :e])
132
132
  i1 = i0.copy
133
-
133
+
134
134
  assert_equal(i0, i1)
135
135
  assert(!i0.at_end?)
136
136
  assert_equal(:b, i0.next_symbol)
137
-
137
+
138
138
  i0.advance
139
-
139
+
140
140
  refute_equal(i0, i1)
141
141
  assert(!i0.at_end?)
142
142
  assert_equal(:C, i0.next_symbol)
143
-
143
+
144
144
  i0.advance
145
145
  assert(!i0.at_end?)
146
146
  assert_equal(:D, i0.next_symbol)
147
-
147
+
148
148
  i0.advance
149
149
  assert(!i0.at_end?)
150
150
  assert_equal(:e, i0.next_symbol)
151
-
151
+
152
152
  i0.advance
153
153
  assert(i0.at_end?)
154
154
  assert_nil(i0.next_symbol)
155
155
  end
156
-
156
+
157
157
  def test_production
158
158
  p0 = RLTK::CFG::Production.new(0, :a, [:b, :C, :D, :e])
159
159
  p1 = p0.copy
160
-
160
+
161
161
  assert_equal(p0, p1)
162
162
  assert_equal(:D, p0.last_terminal)
163
163
  end
@@ -24,28 +24,28 @@ class LexerTester < Minitest::Test
24
24
  class ABLongest < RLTK::Lexer
25
25
  rule(/a+/) { :APLUS }
26
26
  rule(/b+/) { :BPLUS }
27
-
27
+
28
28
  rule(/a+b+/) { :APLUSBPLUS }
29
29
  end
30
30
 
31
31
  class ABFirst < RLTK::Lexer
32
32
  match_first
33
-
33
+
34
34
  rule(/a+/) { :APLUS }
35
35
  rule(/b+/) { :BPLUS }
36
-
36
+
37
37
  rule(/a+b+/) { :APLUSBPLUS }
38
38
  end
39
39
 
40
40
  class ENVLexer < RLTK::Lexer
41
41
  rule(/a/) { [:A, next_value] }
42
-
42
+
43
43
  class Environment < Environment
44
44
  def initialize(*args)
45
45
  super(*args)
46
46
  @value = -1
47
47
  end
48
-
48
+
49
49
  def next_value
50
50
  @value += 1
51
51
  end
@@ -55,7 +55,7 @@ class LexerTester < Minitest::Test
55
55
  class FlagLexer < RLTK::Lexer
56
56
  rule(/a/) { set_flag(:a); :A }
57
57
  rule(/\s/)
58
-
58
+
59
59
  rule(/b/, :default, [:a]) { set_flag(:b); :B }
60
60
  rule(/c/, :default, [:a, :b]) { :C }
61
61
  end
@@ -63,9 +63,9 @@ class LexerTester < Minitest::Test
63
63
  class StateLexer < RLTK::Lexer
64
64
  rule(/a/) { :A }
65
65
  rule(/\s/)
66
-
66
+
67
67
  rule(/\(\*/) { push_state(:comment) }
68
-
68
+
69
69
  rule(/\(\*/, :comment) { push_state(:comment) }
70
70
  rule(/\*\)/, :comment) { pop_state }
71
71
  rule(/./, :comment)
@@ -74,42 +74,42 @@ class LexerTester < Minitest::Test
74
74
  class MatchDataLexer < RLTK::Lexer
75
75
  rule(/a(b*)(c+)/) { [:FOO, match[1,2]] }
76
76
  end
77
-
77
+
78
78
  def test_calc
79
79
  expected = [
80
80
  RLTK::Token.new(:NUM, 1),
81
-
81
+
82
82
  RLTK::Token.new(:PLS),
83
83
  RLTK::Token.new(:SUB),
84
84
  RLTK::Token.new(:MUL),
85
85
  RLTK::Token.new(:DIV),
86
-
86
+
87
87
  RLTK::Token.new(:LPAREN),
88
88
  RLTK::Token.new(:RPAREN),
89
89
  RLTK::Token.new(:EOS)
90
90
  ]
91
-
91
+
92
92
  actual = RLTK::Lexers::Calculator.lex('1 + - * / ( )')
93
-
93
+
94
94
  assert_equal(expected, actual)
95
95
  end
96
-
96
+
97
97
  def test_ebnf
98
98
  expected = [
99
99
  RLTK::Token.new(:NONTERM, :aaa),
100
100
  RLTK::Token.new(:TERM, :BBB),
101
-
101
+
102
102
  RLTK::Token.new(:STAR),
103
103
  RLTK::Token.new(:PLUS),
104
104
  RLTK::Token.new(:QUESTION),
105
105
  RLTK::Token.new(:EOS)
106
106
  ]
107
-
107
+
108
108
  actual = RLTK::Lexers::EBNF.lex('aaa BBB * + ?')
109
-
109
+
110
110
  assert_equal(expected, actual)
111
111
  end
112
-
112
+
113
113
  def test_environment
114
114
  expected = [
115
115
  RLTK::Token.new(:A, 0),
@@ -117,52 +117,52 @@ class LexerTester < Minitest::Test
117
117
  RLTK::Token.new(:A, 2),
118
118
  RLTK::Token.new(:EOS)
119
119
  ]
120
-
120
+
121
121
  actual = ENVLexer.lex('aaa')
122
-
122
+
123
123
  assert_equal(expected, actual)
124
-
124
+
125
125
  lexer = ENVLexer.new
126
-
126
+
127
127
  assert_equal(expected, lexer.lex('aaa'))
128
-
128
+
129
129
  expected = [
130
130
  RLTK::Token.new(:A, 3),
131
131
  RLTK::Token.new(:A, 4),
132
132
  RLTK::Token.new(:A, 5),
133
133
  RLTK::Token.new(:EOS)
134
134
  ]
135
-
135
+
136
136
  assert_equal(expected, lexer.lex('aaa'))
137
137
  end
138
-
138
+
139
139
  def test_first_match
140
140
  expected = [
141
141
  RLTK::Token.new(:APLUS),
142
142
  RLTK::Token.new(:BPLUS),
143
143
  RLTK::Token.new(:EOS)
144
144
  ]
145
-
145
+
146
146
  actual = ABFirst.lex('aaabbb')
147
-
147
+
148
148
  assert_equal(expected, actual)
149
149
  end
150
-
150
+
151
151
  def test_flags
152
-
152
+
153
153
  assert_raises(RLTK::LexingError) { FlagLexer.lex('b') }
154
154
  assert_raises(RLTK::LexingError) { FlagLexer.lex('ac') }
155
-
155
+
156
156
  expected = [
157
157
  RLTK::Token.new(:A),
158
158
  RLTK::Token.new(:B),
159
159
  RLTK::Token.new(:C),
160
160
  RLTK::Token.new(:EOS)
161
161
  ]
162
-
162
+
163
163
  actual = FlagLexer.lex('abc')
164
164
  assert_equal(expected, actual)
165
-
165
+
166
166
  expected = [
167
167
  RLTK::Token.new(:A),
168
168
  RLTK::Token.new(:B),
@@ -172,44 +172,44 @@ class LexerTester < Minitest::Test
172
172
  RLTK::Token.new(:C),
173
173
  RLTK::Token.new(:EOS)
174
174
  ]
175
-
175
+
176
176
  actual = FlagLexer.lex('abcabc')
177
177
  assert_equal(expected, actual)
178
178
  end
179
-
179
+
180
180
  def test_lex
181
181
  assert_raises(RLTK::LexingError) { ABFirst.lex('aaabbbCCC') }
182
182
  assert_raises(RLTK::LexingError) { ABLongest.lex('aaabbbCCC') }
183
183
  end
184
-
184
+
185
185
  def test_longest_match
186
186
  expected = [
187
187
  RLTK::Token.new(:APLUSBPLUS),
188
188
  RLTK::Token.new(:EOS)
189
189
  ]
190
-
190
+
191
191
  actual = ABLongest.lex('aaabbb')
192
-
192
+
193
193
  assert_equal(expected, actual)
194
194
  end
195
-
195
+
196
196
  def test_match_data
197
197
  expected = [RLTK::Token.new(:FOO, ['', 'ccc']), RLTK::Token.new(:EOS)]
198
198
  actual = MatchDataLexer.lex('accc')
199
-
199
+
200
200
  assert_equal(expected, actual)
201
201
  end
202
-
202
+
203
203
  def test_state
204
204
  expected = [
205
205
  RLTK::Token.new(:A),
206
206
  RLTK::Token.new(:A),
207
207
  RLTK::Token.new(:EOS)
208
208
  ]
209
-
209
+
210
210
  actual = StateLexer.lex('a (* bbb *) a')
211
211
  assert_equal(expected, actual)
212
-
212
+
213
213
  actual = StateLexer.lex('a (* b (* ccc *) b *) a')
214
214
  assert_equal(expected, actual)
215
215
  end
@@ -29,606 +29,683 @@ class ParserTester < Minitest::Test
29
29
  class ABLexer < RLTK::Lexer
30
30
  rule(/a/) { [:A, 1] }
31
31
  rule(/b/) { [:B, 2] }
32
-
32
+
33
33
  rule(/\s/)
34
34
  end
35
-
35
+
36
36
  class AlphaLexer < RLTK::Lexer
37
37
  rule(/[A-Za-z]/) { |t| [t.upcase.to_sym, t] }
38
-
38
+
39
39
  rule(/,/) { :COMMA }
40
-
40
+
41
41
  rule(/\s/)
42
42
  end
43
-
43
+
44
44
  class UnderscoreLexer < RLTK::Lexer
45
45
  rule(/\w/) { |t| [:A_TOKEN, t] }
46
46
  end
47
-
47
+
48
48
  class APlusBParser < RLTK::Parser
49
49
  production(:a, 'A+ B') { |a, _| a.length }
50
-
50
+
51
51
  finalize
52
52
  end
53
-
53
+
54
54
  class AQuestionBParser < RLTK::Parser
55
55
  production(:a, 'A? B') { |a, _| a }
56
-
56
+
57
57
  finalize
58
58
  end
59
-
59
+
60
60
  class AStarBParser < RLTK::Parser
61
61
  production(:a, 'A* B') { |a, _| a.length }
62
-
62
+
63
63
  finalize
64
64
  end
65
-
65
+
66
66
  class AmbiguousParser < RLTK::Parser
67
67
  production(:e) do
68
68
  clause('NUM') {|n| n}
69
-
69
+
70
70
  clause('e PLS e') { |e0, _, e1| e0 + e1 }
71
71
  clause('e SUB e') { |e0, _, e1| e0 - e1 }
72
72
  clause('e MUL e') { |e0, _, e1| e0 * e1 }
73
73
  clause('e DIV e') { |e0, _, e1| e0 / e1 }
74
74
  end
75
-
75
+
76
76
  finalize
77
77
  end
78
-
78
+
79
79
  class ArrayCalc < RLTK::Parser
80
80
  dat :array
81
-
81
+
82
82
  production(:e) do
83
83
  clause('NUM') { |v| v[0] }
84
-
84
+
85
85
  clause('PLS e e') { |v| v[1] + v[2] }
86
86
  clause('SUB e e') { |v| v[1] - v[2] }
87
87
  clause('MUL e e') { |v| v[1] * v[2] }
88
88
  clause('DIV e e') { |v| v[1] / v[2] }
89
89
  end
90
-
90
+
91
91
  finalize
92
92
  end
93
-
93
+
94
94
  # This grammar is purposefully ambiguous. This should not be equivalent
95
95
  # to the grammar produced with `e -> A B? B?`, due to greedy Kleene
96
96
  # operators.
97
97
  class AmbiguousParseStackParser < RLTK::Parser
98
98
  production(:s, 'e*') { |e| e }
99
-
99
+
100
100
  production(:e, 'A b_question b_question') { |a, b0, b1| [a, b0, b1] }
101
-
101
+
102
102
  production(:b_question) do
103
103
  clause('') { | | nil }
104
104
  clause('B') { |b| b }
105
105
  end
106
-
106
+
107
107
  finalize
108
108
  end
109
-
109
+
110
+ class EBNFSelectorParser < RLTK::Parser
111
+ dat :array
112
+
113
+ production(:s) do
114
+ clause('.A .B* .A') { |a| a }
115
+ clause('.B C* .B') { |a| a }
116
+ end
117
+
118
+ finalize
119
+ end
120
+
110
121
  class EmptyListParser0 < RLTK::Parser
111
122
  list('list', :A, :COMMA)
112
-
123
+
113
124
  finalize
114
125
  end
115
-
126
+
116
127
  class EmptyListParser1 < RLTK::Parser
117
128
  dat :array
118
-
129
+
119
130
  list('list', ['A', 'B', 'C D'], :COMMA)
120
-
131
+
121
132
  finalize
122
133
  end
123
-
134
+
124
135
  class GreedTestParser0 < RLTK::Parser
125
136
  production(:e, 'A? A') { |a0, a1| [a0, a1] }
126
-
137
+
127
138
  finalize
128
139
  end
129
-
140
+
130
141
  class GreedTestParser1 < RLTK::Parser
131
142
  production(:e, 'A? A?') { |a0, a1| [a0, a1] }
132
-
143
+
133
144
  finalize
134
145
  end
135
-
146
+
136
147
  class GreedTestParser2 < RLTK::Parser
137
148
  production(:e, 'A* A') { |a0, a1| [a0, a1] }
138
-
149
+
139
150
  finalize
140
151
  end
141
-
152
+
142
153
  class GreedTestParser3 < RLTK::Parser
143
154
  production(:e, 'A+ A') { |a0, a1| [a0, a1] }
144
-
155
+
145
156
  finalize
146
157
  end
147
-
158
+
148
159
  class NonEmptyListParser0 < RLTK::Parser
149
160
  nonempty_list('list', :A, :COMMA)
150
-
161
+
151
162
  finalize
152
163
  end
153
-
164
+
154
165
  class NonEmptyListParser1 < RLTK::Parser
155
166
  nonempty_list('list', [:A, :B], :COMMA)
156
-
167
+
157
168
  finalize explain: 'nelp1.tbl'
158
169
  end
159
-
170
+
160
171
  class NonEmptyListParser2 < RLTK::Parser
161
172
  nonempty_list('list', ['A', 'B', 'C D'], :COMMA)
162
-
173
+
163
174
  finalize
164
175
  end
165
-
176
+
166
177
  class NonEmptyListParser3 < RLTK::Parser
167
178
  nonempty_list('list', 'A+', :COMMA)
168
-
179
+
169
180
  finalize
170
181
  end
171
-
182
+
172
183
  class NonEmptyListParser4 < RLTK::Parser
173
184
  nonempty_list('list', :A)
174
-
185
+
175
186
  finalize
176
187
  end
177
-
188
+
178
189
  class NonEmptyListParser5 < RLTK::Parser
179
190
  nonempty_list('list', :A, 'B C?')
180
-
191
+
181
192
  finalize
182
193
  end
183
-
194
+
184
195
  class DummyError1 < StandardError; end
185
196
  class DummyError2 < StandardError; end
186
-
197
+
187
198
  class ErrorCalc < RLTK::Parser
188
199
  left :ERROR
189
200
  right :PLS, :SUB, :MUL, :DIV, :NUM
190
-
201
+
191
202
  production(:e) do
192
203
  clause('NUM') {|n| n}
193
-
204
+
194
205
  clause('e PLS e') { |e0, _, e1| e0 + e1 }
195
206
  clause('e SUB e') { |e0, _, e1| e0 - e1 }
196
207
  clause('e MUL e') { |e0, _, e1| e0 * e1 }
197
208
  clause('e DIV e') { |e0, _, e1| e0 / e1 }
198
-
209
+
199
210
  clause('e PLS ERROR e') { |e0, _, ts, e1| error(ts); e0 + e1 }
200
211
  end
201
-
212
+
202
213
  finalize
203
214
  end
204
215
 
205
216
  class ELLexer < RLTK::Lexer
206
- rule(/\n/) { :NEWLINE }
207
- rule(/;/) { :SEMI }
208
-
217
+ rule(/\n/) { :NEWLINE }
218
+ rule(/;/) { :SEMI }
219
+
209
220
  rule(/\s/)
210
-
211
- rule(/[A-Za-z]+/) { |t| [:WORD, t] }
221
+
222
+ rule(/[A-Za-z]+/) { |t| [:WORD, t] }
212
223
  end
213
224
 
214
225
  class ErrorLine < RLTK::Parser
215
-
226
+
216
227
  production(:s, 'line*') { |l| l }
217
-
228
+
218
229
  production(:line) do
219
230
  clause('NEWLINE') { |_| nil }
220
-
231
+
221
232
  clause('WORD+ SEMI NEWLINE') { |w, _, _| w }
222
233
  clause('WORD+ ERROR') { |w, e| error(pos(1).line_number); w }
223
234
  end
224
-
235
+
225
236
  finalize
226
237
  end
227
-
238
+
228
239
  class UnderscoreParser < RLTK::Parser
229
240
  production(:s, 'A_TOKEN+') { |o| o }
230
-
241
+
231
242
  finalize
232
243
  end
233
-
244
+
234
245
  class RotatingCalc < RLTK::Parser
235
246
  production(:e) do
236
247
  clause('NUM') {|n| n}
237
-
248
+
238
249
  clause('PLS e e') { |_, e0, e1| e0.send(get_op(:+), e1) }
239
250
  clause('SUB e e') { |_, e0, e1| e0.send(get_op(:-), e1) }
240
251
  clause('MUL e e') { |_, e0, e1| e0.send(get_op(:*), e1) }
241
252
  clause('DIV e e') { |_, e0, e1| e0.send(get_op(:/), e1) }
242
253
  end
243
-
254
+
244
255
  class Environment < Environment
245
256
  def initialize
246
257
  @map = { :+ => 0, :- => 1, :* => 2, :/ => 3 }
247
258
  @ops = [ :+, :-, :*, :/ ]
248
259
  end
249
-
260
+
250
261
  def get_op(orig_op)
251
262
  new_op = @ops[@map[orig_op]]
252
-
263
+
253
264
  @ops = @ops[1..-1] << @ops[0]
254
-
265
+
255
266
  new_op
256
267
  end
257
268
  end
258
-
269
+
259
270
  finalize
260
271
  end
261
-
272
+
262
273
  class SelectionParser < RLTK::Parser
263
274
  production(:s, 'A+ .B+') { |bs| bs.inject &:+ }
264
-
275
+
265
276
  finalize
266
277
  end
267
-
278
+
279
+ class UselessParser < RLTK::Parser
280
+ production(:s, 'A+') { |a| a }
281
+ end
282
+
283
+ class TokenHookParser < RLTK::Parser
284
+ dat :array
285
+
286
+ production(:s) do
287
+ clause('A A A A') { |_| nil }
288
+ clause('B B B B') { |_| nil }
289
+ end
290
+
291
+ token_hook(:A) { @counter += 1 }
292
+ token_hook(:B) { @counter += 2 }
293
+
294
+ class Environment < Environment
295
+ attr_reader :counter
296
+
297
+ def initialize
298
+ @counter = 0
299
+ end
300
+ end
301
+
302
+ finalize
303
+ end
304
+
268
305
  def test_ambiguous_grammar
269
306
  actual = AmbiguousParser.parse(RLTK::Lexers::Calculator.lex('1 + 2 * 3'), {:accept => :all})
270
307
  assert_equal([7, 9], actual.sort)
271
308
  end
272
-
309
+
273
310
  # This test is to ensure that objects placed on the output stack are
274
311
  # cloned when we split the parse stack. This was posted as Issue #17 on
275
312
  # Github.
276
313
  def test_ambiguous_parse_stack
277
314
  assert_equal(1, AmbiguousParseStackParser.parse(ABLexer.lex('ab')).length)
278
315
  end
279
-
316
+
280
317
  def test_array_args
281
318
  actual = ArrayCalc.parse(RLTK::Lexers::Calculator.lex('+ 1 2'))
282
319
  assert_equal(3, actual)
283
-
320
+
284
321
  actual = ArrayCalc.parse(RLTK::Lexers::Calculator.lex('+ 1 * 2 3'))
285
322
  assert_equal(7, actual)
286
-
323
+
287
324
  actual = ArrayCalc.parse(RLTK::Lexers::Calculator.lex('* + 1 2 3'))
288
325
  assert_equal(9, actual)
289
326
  end
290
-
327
+
328
+ def test_construction_error
329
+ assert_raises(RLTK::ParserConstructionException) do
330
+ Class.new(RLTK::Parser) do
331
+ finalize
332
+ end
333
+ end
334
+ end
335
+
291
336
  def test_ebnf_parsing
292
337
  ################
293
338
  # APlusBParser #
294
339
  ################
295
-
340
+
296
341
  assert_raises(RLTK::NotInLanguage) { APlusBParser.parse(ABLexer.lex('b')) }
297
-
342
+
298
343
  assert_equal(1, APlusBParser.parse(ABLexer.lex('ab')))
299
344
  assert_equal(2, APlusBParser.parse(ABLexer.lex('aab')))
300
345
  assert_equal(3, APlusBParser.parse(ABLexer.lex('aaab')))
301
346
  assert_equal(4, APlusBParser.parse(ABLexer.lex('aaaab')))
302
-
347
+
303
348
  ####################
304
349
  # AQuestionBParser #
305
350
  ####################
306
-
351
+
307
352
  assert_raises(RLTK::NotInLanguage) { AQuestionBParser.parse(ABLexer.lex('aab')) }
308
353
  assert_nil(AQuestionBParser.parse(ABLexer.lex('b')))
309
354
  refute_nil(AQuestionBParser.parse(ABLexer.lex('ab')))
310
-
355
+
311
356
  ################
312
357
  # AStarBParser #
313
358
  ################
314
-
359
+
315
360
  assert_equal(0, AStarBParser.parse(ABLexer.lex('b')))
316
361
  assert_equal(1, AStarBParser.parse(ABLexer.lex('ab')))
317
362
  assert_equal(2, AStarBParser.parse(ABLexer.lex('aab')))
318
363
  assert_equal(3, AStarBParser.parse(ABLexer.lex('aaab')))
319
364
  assert_equal(4, AStarBParser.parse(ABLexer.lex('aaaab')))
320
365
  end
321
-
366
+
322
367
  def test_empty_list
323
368
  ####################
324
369
  # EmptyListParser0 #
325
370
  ####################
326
-
371
+
327
372
  expected = []
328
373
  actual = EmptyListParser0.parse(AlphaLexer.lex(''))
329
374
  assert_equal(expected, actual)
330
-
375
+
331
376
  ####################
332
377
  # EmptyListParser1 #
333
378
  ####################
334
-
379
+
335
380
  expected = ['a', 'b', ['c', 'd']]
336
381
  actual = EmptyListParser1.parse(AlphaLexer.lex('a, b, c d'))
337
382
  assert_equal(expected, actual)
338
383
  end
339
-
384
+
340
385
  def test_greed
341
-
386
+
342
387
  ####################
343
388
  # GreedTestParser0 #
344
389
  ####################
345
-
390
+
346
391
  expected = [nil, 'a']
347
392
  actual = GreedTestParser0.parse(AlphaLexer.lex('a'))
348
393
  assert_equal(expected, actual)
349
-
394
+
350
395
  expected = ['a', 'a']
351
396
  actual = GreedTestParser0.parse(AlphaLexer.lex('a a'))
352
397
  assert_equal(expected, actual)
353
-
398
+
354
399
  ####################
355
400
  # GreedTestParser1 #
356
401
  ####################
357
-
402
+
358
403
  expected = [nil, nil]
359
404
  actual = GreedTestParser1.parse(AlphaLexer.lex(''))
360
405
  assert_equal(expected, actual)
361
-
406
+
362
407
  # expected = ['a', nil]
363
408
  # actual = GreedTestParser1.parse(AlphaLexer.lex('a'))
364
409
  # assert_equal(expected, actual)
365
-
410
+
366
411
  expected = ['a', 'a']
367
412
  actual = GreedTestParser1.parse(AlphaLexer.lex('a a'))
368
413
  assert_equal(expected, actual)
369
-
414
+
370
415
  ####################
371
416
  # GreedTestParser2 #
372
417
  ####################
373
-
418
+
374
419
  expected = [[], 'a']
375
420
  actual = GreedTestParser2.parse(AlphaLexer.lex('a'))
376
421
  assert_equal(expected, actual)
377
-
422
+
378
423
  expected = [['a'], 'a']
379
424
  actual = GreedTestParser2.parse(AlphaLexer.lex('a a'))
380
425
  assert_equal(expected, actual)
381
-
426
+
382
427
  expected = [['a', 'a'], 'a']
383
428
  actual = GreedTestParser2.parse(AlphaLexer.lex('a a a'))
384
429
  assert_equal(expected, actual)
385
-
430
+
386
431
  ####################
387
432
  # GreedTestParser3 #
388
433
  ####################
389
-
434
+
390
435
  expected = [['a'], 'a']
391
436
  actual = GreedTestParser3.parse(AlphaLexer.lex('a a'))
392
437
  assert_equal(expected, actual)
393
-
438
+
394
439
  expected = [['a', 'a'], 'a']
395
440
  actual = GreedTestParser3.parse(AlphaLexer.lex('a a a'))
396
441
  assert_equal(expected, actual)
397
442
  end
398
-
443
+
444
+ def test_ebnf_selector_interplay
445
+ expected = ['a', ['b', 'b', 'b'], 'a']
446
+ actual = EBNFSelectorParser.parse(AlphaLexer.lex('abbba'))
447
+ assert_equal(expected, actual)
448
+
449
+ expected = ['a', [], 'a']
450
+ actual = EBNFSelectorParser.parse(AlphaLexer.lex('aa'))
451
+ assert_equal(expected, actual)
452
+
453
+ expected = ['b', 'b']
454
+ actual = EBNFSelectorParser.parse(AlphaLexer.lex('bb'))
455
+ assert_equal(expected, actual)
456
+
457
+ expected = ['b', 'b']
458
+ actual = EBNFSelectorParser.parse(AlphaLexer.lex('bcccccb'))
459
+ assert_equal(expected, actual)
460
+ end
461
+
399
462
  def test_environment
400
463
  actual = RotatingCalc.parse(RLTK::Lexers::Calculator.lex('+ 1 2'))
401
464
  assert_equal(3, actual)
402
-
465
+
403
466
  actual = RotatingCalc.parse(RLTK::Lexers::Calculator.lex('/ 1 * 2 3'))
404
467
  assert_equal(7, actual)
405
-
468
+
406
469
  actual = RotatingCalc.parse(RLTK::Lexers::Calculator.lex('- + 1 2 3'))
407
470
  assert_equal(9, actual)
408
-
471
+
409
472
  parser = RotatingCalc.new
410
-
473
+
411
474
  actual = parser.parse(RLTK::Lexers::Calculator.lex('+ 1 2'))
412
475
  assert_equal(3, actual)
413
-
476
+
414
477
  actual = parser.parse(RLTK::Lexers::Calculator.lex('/ 1 2'))
415
478
  assert_equal(3, actual)
416
479
  end
417
-
480
+
418
481
  def test_error_productions
419
-
482
+
420
483
  # Test to see if error reporting is working correctly.
421
-
484
+
422
485
  test_string = "first line;\n"
423
486
  test_string += "second line\n"
424
487
  test_string += "third line;\n"
425
488
  test_string += "fourth line\n"
426
-
489
+
427
490
  assert_raises(RLTK::HandledError) { ErrorLine.parse(ELLexer.lex(test_string)) }
428
-
491
+
429
492
  begin
430
493
  ErrorLine.parse(ELLexer.lex(test_string))
431
-
494
+
432
495
  rescue RLTK::HandledError => e
433
496
  assert_equal([2,4], e.errors)
434
497
  end
435
-
498
+
436
499
  # Test to see if we can continue parsing after errors are encounterd.
437
-
500
+
438
501
  begin
439
502
  ErrorCalc.parse(RLTK::Lexers::Calculator.lex('1 + + 1'))
440
-
503
+
441
504
  rescue RLTK::HandledError => e
442
505
  assert_equal(1, e.errors.first.length)
443
506
  assert_equal(2, e.result)
444
507
  end
445
-
508
+
446
509
  # Test to see if we pop tokens correctly after an error is
447
510
  # encountered.
448
-
511
+
449
512
  begin
450
513
  ErrorCalc.parse(RLTK::Lexers::Calculator.lex('1 + + + + + + 1'))
451
-
514
+
452
515
  rescue RLTK::HandledError => e
453
516
  assert_equal(5, e.errors.first.length)
454
517
  assert_equal(2, e.result)
455
518
  end
456
519
  end
457
-
520
+
458
521
  def test_infix_calc
459
522
  actual = RLTK::Parsers::InfixCalc.parse(RLTK::Lexers::Calculator.lex('1 + 2'))
460
523
  assert_equal(3, actual)
461
-
524
+
462
525
  actual = RLTK::Parsers::InfixCalc.parse(RLTK::Lexers::Calculator.lex('1 + 2 * 3'))
463
526
  assert_equal(7, actual)
464
-
527
+
465
528
  actual = RLTK::Parsers::InfixCalc.parse(RLTK::Lexers::Calculator.lex('(1 + 2) * 3'))
466
529
  assert_equal(9, actual)
467
-
530
+
468
531
  assert_raises(RLTK::NotInLanguage) { RLTK::Parsers::InfixCalc.parse(RLTK::Lexers::Calculator.lex('1 2 + 3 *')) }
469
532
  end
470
-
533
+
471
534
  def test_input
472
535
  assert_raises(RLTK::BadToken) { RLTK::Parsers::InfixCalc.parse(RLTK::Lexers::EBNF.lex('A B C')) }
473
536
  end
474
-
537
+
475
538
  def test_nonempty_list
476
539
  #######################
477
540
  # NonEmptyListParser0 #
478
541
  #######################
479
-
542
+
480
543
  expected = ['a']
481
544
  actual = NonEmptyListParser0.parse(AlphaLexer.lex('a'))
482
545
  assert_equal(expected, actual)
483
-
546
+
484
547
  expected = ['a', 'a']
485
548
  actual = NonEmptyListParser0.parse(AlphaLexer.lex('a, a'))
486
549
  assert_equal(expected, actual)
487
-
550
+
488
551
  assert_raises(RLTK::NotInLanguage) { NonEmptyListParser0.parse(AlphaLexer.lex('')) }
489
552
  assert_raises(RLTK::NotInLanguage) { NonEmptyListParser0.parse(AlphaLexer.lex(',')) }
490
553
  assert_raises(RLTK::NotInLanguage) { NonEmptyListParser0.parse(AlphaLexer.lex('aa')) }
491
554
  assert_raises(RLTK::NotInLanguage) { NonEmptyListParser0.parse(AlphaLexer.lex('a,')) }
492
555
  assert_raises(RLTK::NotInLanguage) { NonEmptyListParser0.parse(AlphaLexer.lex(',a')) }
493
-
556
+
494
557
  #######################
495
558
  # NonEmptyListParser1 #
496
559
  #######################
497
-
560
+
498
561
  expected = ['a']
499
562
  actual = NonEmptyListParser1.parse(AlphaLexer.lex('a'))
500
563
  assert_equal(expected, actual)
501
-
564
+
502
565
  expected = ['b']
503
566
  actual = NonEmptyListParser1.parse(AlphaLexer.lex('b'))
504
567
  assert_equal(expected, actual)
505
-
568
+
506
569
  expected = ['a', 'b', 'a', 'b']
507
570
  actual = NonEmptyListParser1.parse(AlphaLexer.lex('a, b, a, b'))
508
571
  assert_equal(expected, actual)
509
-
572
+
510
573
  assert_raises(RLTK::NotInLanguage) { NonEmptyListParser1.parse(AlphaLexer.lex('a b')) }
511
574
  assert_raises(RLTK::NotInLanguage) { NonEmptyListParser1.parse(AlphaLexer.lex('a, ')) }
512
-
575
+
513
576
  #######################
514
577
  # NonEmptyListParser2 #
515
578
  #######################
516
-
579
+
517
580
  expected = ['a']
518
581
  actual = NonEmptyListParser2.parse(AlphaLexer.lex('a'))
519
582
  assert_equal(expected, actual)
520
-
583
+
521
584
  expected = ['b']
522
585
  actual = NonEmptyListParser2.parse(AlphaLexer.lex('b'))
523
586
  assert_equal(expected, actual)
524
-
587
+
525
588
  expected = [['c', 'd']]
526
589
  actual = NonEmptyListParser2.parse(AlphaLexer.lex('c d'))
527
590
  assert_equal(expected, actual)
528
-
591
+
529
592
  expected = [['c', 'd'], ['c', 'd']]
530
593
  actual = NonEmptyListParser2.parse(AlphaLexer.lex('c d, c d'))
531
594
  assert_equal(expected, actual)
532
-
595
+
533
596
  expected = ['a', 'b', ['c', 'd']]
534
597
  actual = NonEmptyListParser2.parse(AlphaLexer.lex('a, b, c d'))
535
598
  assert_equal(expected, actual)
536
-
599
+
537
600
  assert_raises(RLTK::NotInLanguage) { NonEmptyListParser2.parse(AlphaLexer.lex('c')) }
538
601
  assert_raises(RLTK::NotInLanguage) { NonEmptyListParser2.parse(AlphaLexer.lex('d')) }
539
-
602
+
540
603
  #######################
541
604
  # NonEmptyListParser3 #
542
605
  #######################
543
-
606
+
544
607
  expected = [['a'], ['a', 'a'], ['a', 'a', 'a']]
545
608
  actual = NonEmptyListParser3.parse(AlphaLexer.lex('a, aa, aaa'))
546
609
  assert_equal(expected, actual)
547
-
610
+
548
611
  #######################
549
612
  # NonEmptyListParser4 #
550
613
  #######################
551
-
614
+
552
615
  expected = ['a', 'a', 'a']
553
616
  actual = NonEmptyListParser4.parse(AlphaLexer.lex('a a a'))
554
617
  assert_equal(expected, actual)
555
-
618
+
556
619
  #######################
557
620
  # NonEmptyListParser5 #
558
621
  #######################
559
-
622
+
560
623
  expected = ['a', 'a', 'a']
561
624
  actual = NonEmptyListParser5.parse(AlphaLexer.lex('a b a b c a'))
562
625
  assert_equal(expected, actual)
563
-
626
+
564
627
  assert_raises(RLTK::NotInLanguage) { NonEmptyListParser5.parse(AlphaLexer.lex('a b b a')) }
565
628
  end
566
-
629
+
567
630
  def test_postfix_calc
568
631
  actual = RLTK::Parsers::PostfixCalc.parse(RLTK::Lexers::Calculator.lex('1 2 +'))
569
632
  assert_equal(3, actual)
570
-
633
+
571
634
  actual = RLTK::Parsers::PostfixCalc.parse(RLTK::Lexers::Calculator.lex('1 2 3 * +'))
572
635
  assert_equal(7, actual)
573
-
636
+
574
637
  actual = RLTK::Parsers::PostfixCalc.parse(RLTK::Lexers::Calculator.lex('1 2 + 3 *'))
575
638
  assert_equal(9, actual)
576
-
639
+
577
640
  assert_raises(RLTK::NotInLanguage) { RLTK::Parsers::InfixCalc.parse(RLTK::Lexers::Calculator.lex('* + 1 2 3')) }
578
641
  end
579
-
642
+
580
643
  def test_prefix_calc
581
644
  actual = RLTK::Parsers::PrefixCalc.parse(RLTK::Lexers::Calculator.lex('+ 1 2'))
582
645
  assert_equal(3, actual)
583
-
646
+
584
647
  actual = RLTK::Parsers::PrefixCalc.parse(RLTK::Lexers::Calculator.lex('+ 1 * 2 3'))
585
648
  assert_equal(7, actual)
586
-
649
+
587
650
  actual = RLTK::Parsers::PrefixCalc.parse(RLTK::Lexers::Calculator.lex('* + 1 2 3'))
588
651
  assert_equal(9, actual)
589
-
652
+
590
653
  assert_raises(RLTK::NotInLanguage) { RLTK::Parsers::PrefixCalc.parse(RLTK::Lexers::Calculator.lex('1 + 2 * 3')) }
591
654
  end
592
-
655
+
593
656
  def test_selection_parser
594
657
  actual = SelectionParser.parse(ABLexer.lex('aaabbb'))
595
658
  expected = 6
596
-
659
+
597
660
  assert_equal(expected, actual)
598
661
  end
599
-
662
+
663
+ def test_token_hooks
664
+ parser = TokenHookParser.new
665
+
666
+ parser.parse(AlphaLexer.lex('a a a a'))
667
+ assert_equal(4, parser.env.counter)
668
+
669
+ parser.parse(AlphaLexer.lex('b b b b'))
670
+ assert_equal(12, parser.env.counter)
671
+ end
672
+
600
673
  def test_underscore_tokens
601
674
  actual = UnderscoreParser.parse(UnderscoreLexer.lex('abc')).join
602
675
  expected = 'abc'
603
-
676
+
604
677
  assert_equal(expected, actual)
605
678
  end
606
-
679
+
607
680
  def test_use
608
681
  tmpfile = File.join(Dir.tmpdir, 'usetest')
609
-
682
+
610
683
  FileUtils.rm(tmpfile) if File.exist?(tmpfile)
611
-
684
+
612
685
  parser0 = Class.new(RLTK::Parser) do
613
686
  production(:a, 'A+') { |a| a.length }
614
-
687
+
615
688
  finalize use: tmpfile
616
689
  end
617
-
690
+
618
691
  result0 = parser0.parse(ABLexer.lex('a'))
619
-
692
+
620
693
  assert(File.exist?(tmpfile), 'Serialized parser file not found.')
621
-
694
+
622
695
  parser1 = Class.new(RLTK::Parser) do
623
696
  production(:a, 'A+') { |a| a.length }
624
-
697
+
625
698
  finalize use: tmpfile
626
699
  end
627
-
700
+
628
701
  result1 = parser1.parse(ABLexer.lex('a'))
629
-
702
+
630
703
  assert_equal(result0, result1)
631
-
704
+
632
705
  File.unlink(tmpfile)
633
706
  end
707
+
708
+ def test_uesless_parser_exception
709
+ assert_raises(RLTK::UselessParserException) { UselessParser.new }
710
+ end
634
711
  end