rltk3 3.0.2

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 (56) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS +1 -0
  3. data/LICENSE +27 -0
  4. data/README.md +852 -0
  5. data/Rakefile +197 -0
  6. data/lib/rltk/ast.rb +573 -0
  7. data/lib/rltk/cfg.rb +683 -0
  8. data/lib/rltk/cg/basic_block.rb +157 -0
  9. data/lib/rltk/cg/bindings.rb +151 -0
  10. data/lib/rltk/cg/builder.rb +1127 -0
  11. data/lib/rltk/cg/context.rb +48 -0
  12. data/lib/rltk/cg/contractor.rb +51 -0
  13. data/lib/rltk/cg/execution_engine.rb +194 -0
  14. data/lib/rltk/cg/function.rb +237 -0
  15. data/lib/rltk/cg/generated_bindings.rb +8118 -0
  16. data/lib/rltk/cg/generic_value.rb +95 -0
  17. data/lib/rltk/cg/instruction.rb +519 -0
  18. data/lib/rltk/cg/llvm.rb +150 -0
  19. data/lib/rltk/cg/memory_buffer.rb +75 -0
  20. data/lib/rltk/cg/module.rb +451 -0
  21. data/lib/rltk/cg/pass_manager.rb +252 -0
  22. data/lib/rltk/cg/support.rb +29 -0
  23. data/lib/rltk/cg/target.rb +230 -0
  24. data/lib/rltk/cg/triple.rb +58 -0
  25. data/lib/rltk/cg/type.rb +554 -0
  26. data/lib/rltk/cg/value.rb +1272 -0
  27. data/lib/rltk/cg.rb +32 -0
  28. data/lib/rltk/lexer.rb +372 -0
  29. data/lib/rltk/lexers/calculator.rb +44 -0
  30. data/lib/rltk/lexers/ebnf.rb +38 -0
  31. data/lib/rltk/parser.rb +1702 -0
  32. data/lib/rltk/parsers/infix_calc.rb +43 -0
  33. data/lib/rltk/parsers/postfix_calc.rb +34 -0
  34. data/lib/rltk/parsers/prefix_calc.rb +34 -0
  35. data/lib/rltk/token.rb +90 -0
  36. data/lib/rltk/version.rb +11 -0
  37. data/lib/rltk.rb +16 -0
  38. data/test/cg/tc_basic_block.rb +83 -0
  39. data/test/cg/tc_control_flow.rb +191 -0
  40. data/test/cg/tc_function.rb +54 -0
  41. data/test/cg/tc_generic_value.rb +33 -0
  42. data/test/cg/tc_instruction.rb +256 -0
  43. data/test/cg/tc_llvm.rb +25 -0
  44. data/test/cg/tc_math.rb +88 -0
  45. data/test/cg/tc_module.rb +89 -0
  46. data/test/cg/tc_transforms.rb +68 -0
  47. data/test/cg/tc_type.rb +69 -0
  48. data/test/cg/tc_value.rb +151 -0
  49. data/test/cg/ts_cg.rb +23 -0
  50. data/test/tc_ast.rb +332 -0
  51. data/test/tc_cfg.rb +164 -0
  52. data/test/tc_lexer.rb +216 -0
  53. data/test/tc_parser.rb +711 -0
  54. data/test/tc_token.rb +34 -0
  55. data/test/ts_rltk.rb +47 -0
  56. metadata +317 -0
@@ -0,0 +1,151 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/05/09
4
+ # Description: This file contains unit tests for the RLTK::CG::Value class and
5
+ # its subclasses.
6
+
7
+ ############
8
+ # Requires #
9
+ ############
10
+
11
+ # Gems
12
+ require 'minitest/autorun'
13
+
14
+ # Ruby Language Toolkit
15
+ require 'rltk/cg/llvm'
16
+ require 'rltk/cg/module'
17
+ require 'rltk/cg/execution_engine'
18
+ require 'rltk/cg/type'
19
+ require 'rltk/cg/value'
20
+
21
+ class ValueTester < Minitest::Test
22
+ def setup
23
+ RLTK::CG::LLVM.init(:X86)
24
+
25
+ @mod = RLTK::CG::Module.new('Testing Module')
26
+ @jit = RLTK::CG::JITCompiler.new(@mod)
27
+ end
28
+
29
+ def test_array_values
30
+ fun = @mod.functions.add('array_function_tester', RLTK::CG::NativeIntType,
31
+ [RLTK::CG::NativeIntType, RLTK::CG::NativeIntType]) do |fun|
32
+
33
+ blocks.append do
34
+ ptr = alloca(RLTK::CG::ArrayType.new(RLTK::CG::NativeIntType, 2))
35
+
36
+ array = load(ptr)
37
+ array = insert_value(array, fun.params[0], 0)
38
+ array = insert_value(array, fun.params[1], 1)
39
+
40
+ ret(add(extract_value(array, 0), extract_value(array, 1)))
41
+ end
42
+ end
43
+
44
+ assert_equal(5, @jit.run_function(fun, 2, 3).to_i)
45
+ end
46
+
47
+ def test_constant_array_from_array
48
+ array = RLTK::CG::ConstantArray.new(RLTK::CG::NativeIntType, [RLTK::CG::NativeInt.new(0), RLTK::CG::NativeInt.new(1)])
49
+
50
+ assert_instance_of(RLTK::CG::ConstantArray, array)
51
+ assert_equal(2, array.length)
52
+ end
53
+
54
+ def test_constant_array_from_size
55
+ array = RLTK::CG::ConstantArray.new(RLTK::CG::NativeIntType, 2) { |i| RLTK::CG::NativeInt.new(i) }
56
+
57
+ assert_instance_of(RLTK::CG::ConstantArray, array)
58
+ assert_equal(2, array.length)
59
+ end
60
+
61
+ def test_constant_vector_elements
62
+ fun = @mod.functions.add('constant_vector_elements_tester', RLTK::CG::NativeIntType,
63
+ [RLTK::CG::NativeIntType, RLTK::CG::NativeIntType]) do |fun|
64
+
65
+ blocks.append do
66
+ ptr = alloca(RLTK::CG::VectorType.new(RLTK::CG::NativeIntType, 2))
67
+
68
+ vector = load(ptr)
69
+ vector = insert_element(vector, fun.params[0], RLTK::CG::NativeInt.new(0))
70
+ vector = insert_element(vector, fun.params[1], RLTK::CG::NativeInt.new(1))
71
+
72
+ ret(add(extract_element(vector, RLTK::CG::NativeInt.new(0)), extract_element(vector, RLTK::CG::NativeInt.new(1))))
73
+ end
74
+ end
75
+
76
+ assert_equal(5, @jit.run_function(fun, 2, 3).to_i)
77
+ end
78
+
79
+ def test_constant_vector_from_array
80
+ vector = RLTK::CG::ConstantVector.new([RLTK::CG::NativeInt.new(0), RLTK::CG::NativeInt.new(1)])
81
+
82
+ assert_instance_of(RLTK::CG::ConstantVector, vector)
83
+ assert_equal(2, vector.size)
84
+ end
85
+
86
+ def test_constant_vector_from_size
87
+ vector = RLTK::CG::ConstantVector.new(2) { |i| RLTK::CG::NativeInt.new(i) }
88
+
89
+ assert_instance_of(RLTK::CG::ConstantVector, vector)
90
+ assert_equal(2, vector.size)
91
+ end
92
+
93
+ def test_constant_vector_shuffle
94
+ fun = @mod.functions.add('constant_vector_shuffle_tester', RLTK::CG::NativeIntType, Array.new(4, RLTK::CG::NativeIntType)) do |fun|
95
+ blocks.append do
96
+ vec_type = RLTK::CG::VectorType.new(RLTK::CG::NativeIntType, 2)
97
+
98
+ v0 = load(alloca(vec_type))
99
+ v0 = insert_element(v0, fun.params[0], RLTK::CG::NativeInt.new(0))
100
+ v0 = insert_element(v0, fun.params[1], RLTK::CG::NativeInt.new(1))
101
+
102
+ v1 = load(alloca(vec_type))
103
+ v1 = insert_element(v1, fun.params[2], RLTK::CG::NativeInt.new(0))
104
+ v1 = insert_element(v1, fun.params[3], RLTK::CG::NativeInt.new(1))
105
+
106
+ v2 = shuffle_vector(v0, v1, RLTK::CG::ConstantVector.new([RLTK::CG::NativeInt.new(0), RLTK::CG::NativeInt.new(3)]))
107
+
108
+ ret(add(extract_element(v2, RLTK::CG::NativeInt.new(0)), extract_element(v2, RLTK::CG::NativeInt.new(1))))
109
+ end
110
+ end
111
+
112
+ assert_equal(5, @jit.run_function(fun, 1, 2, 3, 4).to_i)
113
+ end
114
+
115
+ def test_constant_struct_from_size_packed
116
+ struct = RLTK::CG::ConstantStruct.new(2, true) { |i| RLTK::CG::NativeInt.new(i) }
117
+
118
+ assert_instance_of(RLTK::CG::ConstantStruct, struct)
119
+ assert_equal(2, struct.operands.size)
120
+ end
121
+
122
+ def test_constant_struct_from_size_unpacked
123
+ struct = RLTK::CG::ConstantStruct.new(2, false) { |i| RLTK::CG::NativeInt.new(i) }
124
+
125
+ assert_instance_of(RLTK::CG::ConstantStruct, struct)
126
+ assert_equal(2, struct.operands.size)
127
+ end
128
+
129
+ def test_constant_struct_from_values_packed
130
+ struct = RLTK::CG::ConstantStruct.new([RLTK::CG::NativeInt.new(0), RLTK::CG::NativeInt.new(1)], true)
131
+
132
+ assert_instance_of(RLTK::CG::ConstantStruct, struct)
133
+ assert_equal(2, struct.operands.size)
134
+ end
135
+
136
+ def test_constant_struct_from_values_unpacked
137
+ struct = RLTK::CG::ConstantStruct.new([RLTK::CG::NativeInt.new(0), RLTK::CG::NativeInt.new(1)], false)
138
+
139
+ assert_instance_of(RLTK::CG::ConstantStruct, struct)
140
+ assert_equal(2, struct.operands.size)
141
+ end
142
+
143
+ def test_equality
144
+ v0 = RLTK::CG::NativeInt.new(0)
145
+ v1 = RLTK::CG::NativeInt.new(1)
146
+ v2 = RLTK::CG::NativeInt.new(v0.ptr)
147
+
148
+ assert_equal(v0, v2)
149
+ refute_equal(v0, v1)
150
+ end
151
+ end
data/test/cg/ts_cg.rb ADDED
@@ -0,0 +1,23 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/05/04
4
+ # Description: This file contains test suit for the RLTK LLVM bindigns. It
5
+ # requires the individual tests from their respective files.
6
+
7
+ ############
8
+ # Requires #
9
+ ############
10
+
11
+ # Ruby Language Toolkit
12
+ require 'cg/tc_llvm'
13
+ require 'cg/tc_module'
14
+
15
+ require 'cg/tc_basic_block'
16
+ require 'cg/tc_control_flow'
17
+ require 'cg/tc_function'
18
+ require 'cg/tc_generic_value'
19
+ require 'cg/tc_instruction'
20
+ require 'cg/tc_math'
21
+ require 'cg/tc_transforms'
22
+ require 'cg/tc_type'
23
+ require 'cg/tc_value'
data/test/tc_ast.rb ADDED
@@ -0,0 +1,332 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2011/04/06
4
+ # Description: This file contains unit tests for the RLTK::ASTNode class.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Gems
11
+ require 'minitest/autorun'
12
+
13
+ # Ruby Language Toolkit
14
+ require 'rltk/ast'
15
+
16
+ #######################
17
+ # Classes and Modules #
18
+ #######################
19
+
20
+ class ASTNodeTester < Minitest::Test
21
+ class ANode < RLTK::ASTNode
22
+ child :left, ANode
23
+ child :right, ANode
24
+ end
25
+
26
+ class BNode < ANode; end
27
+ class CNode < ANode; end
28
+
29
+ class DNode < RLTK::ASTNode; end
30
+
31
+ class ENode < RLTK::ASTNode
32
+ value :str, String
33
+ end
34
+
35
+ class FNode < ENode
36
+ child :c, [ENode]
37
+ end
38
+
39
+ class SNode < RLTK::ASTNode
40
+ value :string, String
41
+
42
+ child :left, SNode
43
+ child :right, SNode
44
+ end
45
+
46
+ class VNode < RLTK::ASTNode
47
+ value :a, Integer
48
+ value :b, Integer
49
+ end
50
+
51
+ class ONode < RLTK::ASTNode
52
+ value :a, Integer
53
+ value :b, Integer, true
54
+ value :c, Integer
55
+ end
56
+
57
+ class ValuesFirstNode < RLTK::ASTNode
58
+ child :b, ValuesFirstNode
59
+ value :a, Integer
60
+ end
61
+
62
+ class ChildrenFirstNode < RLTK::ASTNode
63
+ order :children
64
+
65
+ value :b, Integer
66
+ child :a, ChildrenFirstNode
67
+ end
68
+
69
+ class DefOrderNode < RLTK::ASTNode
70
+ order :def
71
+
72
+ value :a, Integer
73
+ child :b, DefOrderNode
74
+ value :c, Float
75
+ end
76
+
77
+ class CustomOrderNode < RLTK::ASTNode
78
+ custom_order :a, :b, :c, :d
79
+
80
+ child :b, CustomOrderNode
81
+ child :d, CustomOrderNode
82
+
83
+ value :a, Integer
84
+ value :c, String
85
+ end
86
+
87
+ def setup
88
+ @leaf0 = CNode.new
89
+ @tree0 = ANode.new(BNode.new(@leaf0), BNode.new)
90
+
91
+ @tree1 = ANode.new(BNode.new(CNode.new), BNode.new)
92
+ @tree2 = ANode.new(BNode.new, BNode.new(CNode.new))
93
+ @tree3 = ANode.new(CNode.new(BNode.new), CNode.new)
94
+
95
+ @tree4 = SNode.new('F',
96
+ SNode.new('B',
97
+ SNode.new('A'),
98
+ SNode.new('D',
99
+ SNode.new('C'),
100
+ SNode.new('E')
101
+ ),
102
+ ),
103
+ SNode.new('G',
104
+ nil,
105
+ SNode.new('I',
106
+ SNode.new('H')
107
+ )
108
+ )
109
+ )
110
+
111
+ @tree5 = FNode.new('one',
112
+ [FNode.new('two',
113
+ [ENode.new('three')]),
114
+ ENode.new('four')])
115
+
116
+ @tree6 = FNode.new('one',
117
+ [FNode.new('two',
118
+ [ENode.new('three')]),
119
+ ENode.new('four')])
120
+
121
+ @tree7 = FNode.new('one!',
122
+ [FNode.new('two!',
123
+ [ENode.new('three!')]),
124
+ ENode.new('four!')])
125
+
126
+ @bc_proc = Proc.new do |n|
127
+ case n
128
+ when BNode then CNode.new(n.left, n.right)
129
+ when CNode then BNode.new(n.left, n.right)
130
+ else n
131
+ end
132
+ end
133
+ end
134
+
135
+ def test_children
136
+ node = ANode.new
137
+
138
+ assert_equal(node.children, [nil, nil])
139
+
140
+ node.children = (expected_children = [BNode.new, CNode.new])
141
+
142
+ assert_equal(node.children, expected_children)
143
+
144
+ node.children = (expected_children = {:left => CNode.new, :right => BNode.new})
145
+
146
+ assert_equal(node.children(Hash), expected_children)
147
+ end
148
+
149
+ def test_copy
150
+ new_tree = @tree5.copy
151
+
152
+ assert_equal(@tree5, new_tree)
153
+ end
154
+
155
+ def test_dump
156
+ tree0_string = @tree0.dump
157
+
158
+ reloaded_tree = Marshal.load(tree0_string)
159
+
160
+ assert_equal(@tree0, reloaded_tree)
161
+ end
162
+
163
+ def test_each
164
+ # Test pre-order
165
+ nodes = []
166
+ expected = ['F', 'B', 'A', 'D', 'C', 'E', 'G', 'I', 'H']
167
+ @tree4.each(:pre) { |n| nodes << n.string }
168
+
169
+ assert_equal(expected, nodes)
170
+
171
+ # Test post-order
172
+ nodes = []
173
+ expected = ['A', 'C', 'E', 'D', 'B', 'H', 'I', 'G', 'F']
174
+ @tree4.each(:post) { |n| nodes << n.string }
175
+
176
+ assert_equal(expected, nodes)
177
+
178
+ # Test level-order
179
+ nodes = []
180
+ expected = ['F', 'B', 'G', 'A', 'D', 'I', 'C', 'E', 'H']
181
+ @tree4.each(:level) { |n| nodes << n.string }
182
+
183
+ assert_equal(expected, nodes)
184
+
185
+ # Test iteration with array children.
186
+
187
+ res = ''
188
+ @tree5.each(:pre) { |node| res += ' ' + node.str }
189
+ assert_equal(res, ' one two three four')
190
+
191
+ res = ''
192
+ @tree5.each(:post) { |node| res += ' ' + node.str }
193
+ assert_equal(res, ' three two four one')
194
+
195
+ res = ''
196
+ @tree5.each(:level) { |node| res += ' ' + node.str }
197
+ assert_equal(res, ' one two four three')
198
+ end
199
+
200
+ def test_equal
201
+ assert_equal(@tree0, @tree1)
202
+ refute_equal(@tree0, @tree2)
203
+ end
204
+
205
+ def test_initialize
206
+ assert_raises(AbstractClassError) { RLTK::ASTNode.new }
207
+
208
+ node = ENode.new { self.str = 'hello world' }
209
+ assert_equal('hello world', node.str)
210
+ end
211
+
212
+ def test_map
213
+ mapped_tree = @tree1.map(&@bc_proc)
214
+
215
+ assert_equal(@tree0, @tree1)
216
+ assert_equal(@tree3, mapped_tree)
217
+
218
+ mapped_tree = @tree5.map do |c|
219
+ c.str += '!'
220
+
221
+ c
222
+ end
223
+
224
+ assert_equal(@tree6, @tree5)
225
+ assert_equal(@tree7, mapped_tree)
226
+ end
227
+
228
+ def test_map!
229
+ tree1_clone = @tree1.clone
230
+ tree1_clone.map!(&@bc_proc)
231
+
232
+ refute_equal(@tree1, tree1_clone)
233
+ assert_equal(@tree3, tree1_clone)
234
+
235
+ replace_node = BNode.new
236
+ replace_node = replace_node.map!(&@bc_proc)
237
+
238
+ assert_equal(CNode.new, replace_node)
239
+
240
+ @tree5.map! do |c|
241
+ c.str += '!'
242
+
243
+ c
244
+ end
245
+
246
+ refute_equal(@tree6, @tree5)
247
+ assert_equal(@tree7, @tree5)
248
+ end
249
+
250
+ def test_notes
251
+ node = ANode.new
252
+
253
+ assert_nil(node[:a])
254
+ assert_equal(node[:a] = :b, :b)
255
+ assert_equal(node.note?(:a), true)
256
+ assert_equal(node.note?(:b), false)
257
+ assert_equal(node.delete_note(:a), :b)
258
+ assert_nil(node[:a])
259
+ end
260
+
261
+ def test_omit
262
+ onode = ONode.new(1, 3)
263
+
264
+ assert_equal(1, onode.a)
265
+ assert_nil(onode.b)
266
+ assert_equal(3, onode.c)
267
+ end
268
+
269
+ def test_one_definition_rule
270
+ asserter = self
271
+
272
+ Class.new(ANode) do
273
+ asserter.assert_raises(ArgumentError) { child :left, ANode }
274
+ end
275
+
276
+ Class.new(ENode) do
277
+ asserter.assert_raises(ArgumentError) { value :str, String }
278
+ end
279
+ end
280
+
281
+ def test_ordering
282
+ vfn = ValuesFirstNode.new(42, ValuesFirstNode.new)
283
+
284
+ a, b = vfn.destructure(2)
285
+
286
+ assert_equal(42, a)
287
+ assert_instance_of(ValuesFirstNode, b)
288
+
289
+ cfn = ChildrenFirstNode.new(ChildrenFirstNode.new, 42)
290
+
291
+ a, b = cfn.destructure(2)
292
+
293
+ assert_instance_of(ChildrenFirstNode, a)
294
+ assert_equal(42, b)
295
+
296
+ dfn = DefOrderNode.new(4, DefOrderNode.new, 2.0)
297
+
298
+ a, b, c = dfn.destructure(3)
299
+
300
+ assert_equal(4, a)
301
+ assert_instance_of(DefOrderNode, b)
302
+ assert_equal(2.0, c)
303
+
304
+ con = CustomOrderNode.new(42, CustomOrderNode.new, 'foo')
305
+
306
+ a, b, c, d = con.destructure(4)
307
+
308
+ assert_equal(42, a)
309
+ assert_instance_of(CustomOrderNode, b)
310
+ assert_equal('foo', c)
311
+ assert_nil(d)
312
+ end
313
+
314
+ def test_root
315
+ assert_same(@tree0, @tree0.root)
316
+ assert_same(@tree0, @leaf0.root)
317
+ end
318
+
319
+ def test_value
320
+ node = VNode.new
321
+
322
+ assert_equal(node.values, [nil, nil])
323
+
324
+ node.values = (expected_values = [42, 1984])
325
+
326
+ assert_equal(node.values, expected_values)
327
+
328
+ node.values = (expected_values = {:a => 1984, :b => 42})
329
+
330
+ assert_equal(node.values(Hash), expected_values)
331
+ end
332
+ end
data/test/tc_cfg.rb ADDED
@@ -0,0 +1,164 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2011/04/06
4
+ # Description: This file contains unit tests for the RLTK::CFG class.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Gems
11
+ require 'minitest/autorun'
12
+
13
+ # Ruby Language Toolkit
14
+ require 'rltk/cfg'
15
+
16
+ #######################
17
+ # Classes and Modules #
18
+ #######################
19
+
20
+ class CFGTester < Minitest::Test
21
+ def setup
22
+ @grammar = RLTK::CFG.new
23
+
24
+ @grammar.production(:s) do
25
+ clause('A G D')
26
+ clause('A a C')
27
+ clause('B a D')
28
+ clause('B G C')
29
+ end
30
+
31
+ @grammar.production(:a, 'b')
32
+ @grammar.production(:b, 'G')
33
+ end
34
+
35
+ def test_callback
36
+ grammar = RLTK::CFG.new
37
+
38
+ call_count = 0
39
+ grammar.callback do |type, which, p|
40
+ refute_nil(p)
41
+ assert_equal(type, :optional)
42
+
43
+ case call_count
44
+ when 0 then assert_equal(:empty, which)
45
+ when 1 then assert_equal(:nonempty, which)
46
+ end
47
+
48
+ call_count += 1
49
+ end
50
+
51
+ grammar.production(:a, 'A?') { |a| a }
52
+ assert_equal(2, call_count)
53
+
54
+ call_count = 0
55
+ grammar.callback do |type, which, p|
56
+ refute_nil(p)
57
+
58
+ case call_count
59
+ when 0
60
+ assert_equal(:elp, type)
61
+ assert_equal(:empty, which)
62
+
63
+ when 1
64
+ assert_equal(:elp, type)
65
+ assert_equal(:nonempty, which)
66
+
67
+ when 2
68
+ assert_equal(:nelp, type)
69
+ assert_equal(:single, which)
70
+
71
+ when 3
72
+ assert_equal(:nelp, type)
73
+ assert_equal(:multiple, which)
74
+ end
75
+
76
+ call_count += 1
77
+ end
78
+
79
+ grammar.production(:a, 'A*') { |a| a }
80
+ assert_equal(4, call_count)
81
+
82
+ call_count = 0
83
+ grammar.callback do |type, which, p|
84
+ refute_nil(p)
85
+ assert_equal(type, :nelp)
86
+
87
+ case call_count
88
+ when 0 then assert_equal(:single, which)
89
+ when 1 then assert_equal(:multiple, which)
90
+ end
91
+
92
+ call_count += 1
93
+ end
94
+
95
+ grammar.production(:a, 'A+') { |a| a }
96
+ assert_equal(2, call_count)
97
+ end
98
+
99
+ def test_first_set
100
+ @grammar.first_set(:s).each do |sym|
101
+ assert_includes([:A, :B], sym)
102
+ end
103
+
104
+ assert_equal([:G], @grammar.first_set(:b))
105
+ assert_equal([:G], @grammar.first_set(:a))
106
+ end
107
+
108
+ def test_follow_set
109
+ assert_equal(@grammar.follow_set(:s), [:EOS])
110
+
111
+ @grammar.follow_set(:a).each do |sym|
112
+ assert([:C, :D].include?(sym))
113
+ end
114
+
115
+ @grammar.follow_set(:b).each do |sym|
116
+ assert([:C, :D].include?(sym))
117
+ end
118
+ end
119
+
120
+ def test_is_nonterminal
121
+ assert(RLTK::CFG::is_nonterminal?(:lowercase))
122
+ assert(!RLTK::CFG::is_nonterminal?(:UPERCASE))
123
+ end
124
+
125
+ def test_is_terminal
126
+ assert(!RLTK::CFG::is_terminal?(:lowercase))
127
+ assert(RLTK::CFG::is_terminal?(:UPERCASE))
128
+ end
129
+
130
+ def test_item
131
+ i0 = RLTK::CFG::Item.new(0, 0, :a, [:b, :C, :D, :e])
132
+ i1 = i0.copy
133
+
134
+ assert_equal(i0, i1)
135
+ assert(!i0.at_end?)
136
+ assert_equal(:b, i0.next_symbol)
137
+
138
+ i0.advance
139
+
140
+ refute_equal(i0, i1)
141
+ assert(!i0.at_end?)
142
+ assert_equal(:C, i0.next_symbol)
143
+
144
+ i0.advance
145
+ assert(!i0.at_end?)
146
+ assert_equal(:D, i0.next_symbol)
147
+
148
+ i0.advance
149
+ assert(!i0.at_end?)
150
+ assert_equal(:e, i0.next_symbol)
151
+
152
+ i0.advance
153
+ assert(i0.at_end?)
154
+ assert_nil(i0.next_symbol)
155
+ end
156
+
157
+ def test_production
158
+ p0 = RLTK::CFG::Production.new(0, :a, [:b, :C, :D, :e])
159
+ p1 = p0.copy
160
+
161
+ assert_equal(p0, p1)
162
+ assert_equal(:D, p0.last_terminal)
163
+ end
164
+ end