rockit 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/BUGS +13 -0
  2. data/LICENSE +280 -0
  3. data/README +172 -0
  4. data/TODO +53 -0
  5. data/VERSION +1 -0
  6. data/lib/packrat/grammar.rb +537 -0
  7. data/lib/rockit/prettyprint/box.rb +60 -0
  8. data/lib/rockit/prettyprint/renderer.rb +41 -0
  9. data/lib/rockit/prettyprint/text_renderer.rb +47 -0
  10. data/lib/rockit/tree/base.rb +223 -0
  11. data/lib/rockit/tree/enter_leave_visitor.rb +12 -0
  12. data/lib/rockit/tree/graphviz.rb +69 -0
  13. data/lib/rockit/tree/visitor.rb +12 -0
  14. data/lib/util/array_alternatives.rb +20 -0
  15. data/lib/util/enter_leave_visitor.rb +69 -0
  16. data/lib/util/graphviz_dot.rb +182 -0
  17. data/lib/util/string_location.rb +42 -0
  18. data/lib/util/visitor.rb +49 -0
  19. data/lib/util/visitor_combinators.rb +14 -0
  20. data/rakefile +200 -0
  21. data/tests/acceptance/packrat/minibasic/atest_minibasic.rb +45 -0
  22. data/tests/acceptance/packrat/minibasic/minibasic.rb +137 -0
  23. data/tests/acceptance/rockit/dparser/atest_any_operator.rb +33 -0
  24. data/tests/acceptance/rockit/dparser/atest_arithmetic_grammar.rb +30 -0
  25. data/tests/acceptance/rockit/dparser/atest_list_operator.rb +57 -0
  26. data/tests/acceptance/rockit/dparser/atest_mult_operator.rb +60 -0
  27. data/tests/acceptance/rockit/dparser/atest_operator_grammar.rb +61 -0
  28. data/tests/acceptance/rockit/dparser/atest_plus_operator.rb +55 -0
  29. data/tests/acceptance/rockit/dparser/atest_samples_calculator.rb +14 -0
  30. data/tests/acceptance/rockit/dparser/atest_samples_minibasic.rb +20 -0
  31. data/tests/acceptance/rockit/dparser/atest_samples_multifunccalculator.rb +36 -0
  32. data/tests/acceptance/rockit/dparser/atest_simple_grammar.rb +34 -0
  33. data/tests/acceptance/rockit/dparser/atest_speculative_code_action.rb +128 -0
  34. data/tests/acceptance/rockit/dparser/calc_tests_common.rb +103 -0
  35. data/tests/unit/packrat/test_interpreting_parser.rb +296 -0
  36. data/tests/unit/parse/utest_ebnf_grammar.rb +50 -0
  37. data/tests/unit/parse/utest_expand_grammar.rb +23 -0
  38. data/tests/unit/parse/utest_grammar.rb +160 -0
  39. data/tests/unit/rockit/assembler/llvm/utest_instructions.rb +41 -0
  40. data/tests/unit/rockit/assembler/llvm/utest_module.rb +19 -0
  41. data/tests/unit/rockit/prettyprint/utest_box.rb +44 -0
  42. data/tests/unit/rockit/tree/utest_tree_base.rb +301 -0
  43. data/tests/unit/rockit/tree/utest_tree_enter_leave_visitor.rb +69 -0
  44. data/tests/unit/rockit/tree/utest_tree_visitor.rb +63 -0
  45. data/tests/unit/rockit/utest_grammar.rb +145 -0
  46. data/tests/unit/rockit/utest_grammar_symbol.rb +11 -0
  47. data/tests/unit/rockit/utest_maybe_operator.rb +12 -0
  48. data/tests/unit/rockit/utest_regexp_terminal.rb +45 -0
  49. data/tests/unit/rockit/utest_repetition_operators.rb +35 -0
  50. data/tests/unit/rockit/utest_rule.rb +23 -0
  51. data/tests/unit/rockit/utest_string_terminal.rb +40 -0
  52. data/tests/unit/util/utest_array_alternatives.rb +23 -0
  53. data/tests/unit/util/utest_enter_leave_visitor.rb +89 -0
  54. data/tests/unit/util/utest_string_location.rb +42 -0
  55. data/tests/unit/util/utest_visitor.rb +92 -0
  56. data/tests/unit/util/utest_visitor_combinators.rb +64 -0
  57. metadata +112 -0
@@ -0,0 +1,160 @@
1
+ require 'test/unit'
2
+
3
+ require 'parse/grammar'
4
+ include Parse::Grammar
5
+
6
+ class UT_Parse_Grammar < Test::Unit::TestCase
7
+ def test_01_Symbol
8
+ s = Parse::Grammar::GrammarSymbol.new "name"
9
+ assert_equal("name", s.name)
10
+ assert_equal("name", s.inspect)
11
+ assert_equal(s, s.to_grammar_symbol)
12
+ end
13
+
14
+ def test_02_Symbol_name_not_needed
15
+ s = Parse::Grammar::GrammarSymbol.new
16
+ assert_equal(nil, s.name)
17
+ assert_equal(s, s.to_grammar_symbol)
18
+ end
19
+
20
+ def test_03_NonTerminal
21
+ s = NonTerminal.new :name
22
+ assert_equal(:name, s.name)
23
+ assert_equal("name", s.inspect)
24
+ assert_kind_of(Parse::Grammar::GrammarSymbol, s)
25
+ assert_equal(s, s.to_grammar_symbol)
26
+ end
27
+
28
+ def test_04_Terminal
29
+ s = Terminal.new
30
+ assert_kind_of(Parse::Grammar::GrammarSymbol, s)
31
+ end
32
+
33
+ def test_05_Production
34
+ p = Production.new(n = NonTerminal.new(:N), [t = Terminal.new(:T)])
35
+ assert_equal(n, p.symbol)
36
+ assert_equal(t, p.rhs.first)
37
+ assert_equal(t, p.right_hand_side.first)
38
+ end
39
+
40
+ def test_06_Production_short_hand
41
+ p = Prod[n = NonTerminal.new(:N), [t = Terminal.new(:T)]]
42
+ assert_equal(n, p.symbol)
43
+ assert_equal(t, p.rhs.first)
44
+ assert_equal(t, p.right_hand_side.first)
45
+
46
+ p2 = Prod[:N, [t]]
47
+ assert_equal("N", p2.symbol.inspect)
48
+ end
49
+
50
+ def test_07_nonterminal_equality
51
+ n1 = NonTerminal.new(:N)
52
+ n2 = NonTerminal.new(:N)
53
+ assert(n1 == n2)
54
+ assert(n2 == n1)
55
+ end
56
+
57
+ def test_08_Rule
58
+ p1 = Prod[n = NonTerminal.new(:N), [Terminal.new(:T1)]]
59
+ p2 = Prod[:N, [Terminal.new(:T2)]]
60
+ r = Rule[p1]
61
+
62
+ assert(n == r.symbol)
63
+ assert_equal(1, r.productions.length)
64
+
65
+ r.add_production p2
66
+ assert_equal(n, r.symbol)
67
+ assert_equal(2, r.productions.length)
68
+
69
+ assert_raises(ArgumentError) {r.add_production(Prod[:N2, [Terminal[:T3]]])}
70
+ end
71
+
72
+ def test_09_Grammar
73
+ g = Grammar.new(:name => "Test Grammar 1", :author => "Robert")
74
+ assert_kind_of(Grammar, g)
75
+ assert_equal("Test Grammar 1", g.meta[:name])
76
+ assert_equal("Robert", g.meta[:author])
77
+ assert_equal(0, g.rules.length)
78
+ assert_equal(0, g.nonterminals.length)
79
+ assert_equal(0, g.terminals.length)
80
+ assert_equal(0, g.symbols.length)
81
+
82
+ g.add_rule(Rule[Prod[:N, [Terminal[:T1]]]])
83
+ assert_equal(1, g.rules.length)
84
+ assert_equal(1, g.nonterminals.length)
85
+ assert_equal(1, g.terminals.length)
86
+ assert_equal(2, g.symbols.length)
87
+ end
88
+
89
+ def test_10_symbol_predicates
90
+ nt = NonTerminal[:N]
91
+ assert_equal(true, nt.nonterminal?)
92
+ assert_equal(false, nt.terminal?)
93
+ assert_equal(false, nt.action?)
94
+
95
+ t = Terminal[:T]
96
+ assert_equal(false, t.nonterminal?)
97
+ assert_equal(true, t.terminal?)
98
+ assert_equal(false, t.action?)
99
+
100
+ a = Action[:A]
101
+ assert_equal(false, a.nonterminal?)
102
+ assert_equal(false, a.terminal?)
103
+ assert_equal(true, a.action?)
104
+ end
105
+
106
+ class TestGrammar < Grammar
107
+ r :S, [[:B]]
108
+ r :B, [
109
+ [Terminal.new(:T1)],
110
+ [Terminal.new(:T2), Terminal.new(:T3)],
111
+ ]
112
+ t :CT1, ["A"]
113
+ end
114
+
115
+ def test_11_embedded_grammar_def
116
+ t = TestGrammar.new
117
+
118
+ assert_equal(2, t.rules.length)
119
+
120
+ assert_equal(:S, t.rules.first.symbol.name)
121
+ assert_equal(1, t.rules.first.productions.length)
122
+
123
+ assert_equal(:B, t.rules.last.symbol.name)
124
+ assert_equal(2, t.rules.last.productions.length)
125
+ assert_equal(:T1, t.rules.last.productions.first.rhs.first.name)
126
+ assert_equal(:T2, t.rules.last.productions.last.rhs.first.name)
127
+ assert_equal(:T3, t.rules.last.productions.last.rhs.last.name)
128
+
129
+ assert_equal(1, t.complex_terminals.length)
130
+
131
+ assert_equal(:CT1, t.complex_terminals.first.name)
132
+ end
133
+
134
+ TestDeepClone = Struct.new(:a)
135
+
136
+ def test_12_deep_clone
137
+ a = [1,2,3]
138
+ t1 = TestDeepClone.new(a)
139
+ t1a = t1.clone
140
+ t1b = t1.deep_clone
141
+ assert_equal(t1.a.object_id, t1a.a.object_id)
142
+ assert_not_equal(t1.a.object_id, t1b.a.object_id)
143
+ end
144
+
145
+ def test_13_define_grammar_in_a_block
146
+ g = Grammar.new do
147
+ r :S, [["a", :B]]
148
+ r :B, [["b"]]
149
+ end
150
+ assert_equal(2, g.nonterminals.length)
151
+ end
152
+
153
+ def test_14_extending_a_grammar_with_a_block
154
+ g = TestGrammar.new do
155
+ r :A, [["a"]]
156
+ end
157
+ # Two nonterminals in the original grammar and one new here => 3
158
+ assert_equal(3, g.nonterminals.length)
159
+ end
160
+ end
@@ -0,0 +1,41 @@
1
+ require 'test/unit'
2
+
3
+ require 'rockit/assembler/llvm/instructions'
4
+ include Rockit::Assembler::LLVM
5
+
6
+ class UTestLLVMInstructions < Test::Unit::TestCase
7
+ def test_01_NamedValue_valid
8
+ nv1 = NamedValue.new("foo")
9
+ assert_equal("%foo", nv1.to_llvm)
10
+
11
+ nv2 = NamedValue.new("DivByZero")
12
+ assert_equal("%DivByZero", nv2.to_llvm)
13
+
14
+ nv3 = NamedValue.new("a.really.long.identifier")
15
+ assert_equal("%a.really.long.identifier", nv3.to_llvm)
16
+ end
17
+
18
+ def test_02_NamedValue_invalid
19
+ assert_raises(ArgumentError) {NamedValue.new("12")}
20
+ assert_raises(ArgumentError) {NamedValue.new("%")}
21
+ end
22
+
23
+ def test_03_UnnamedValue_valid
24
+ u1 = UnnamedValue.new(0)
25
+ assert_equal("%0", u1.to_llvm)
26
+
27
+ u2 = UnnamedValue.new(12)
28
+ assert_equal("%12", u2.to_llvm)
29
+
30
+ u3 = UnnamedValue.new(2)
31
+ assert_equal("%2", u3.to_llvm)
32
+
33
+ u4 = UnnamedValue.new(44)
34
+ assert_equal("%44", u4.to_llvm)
35
+ end
36
+
37
+ def test_04_UnnamedValue_invalid
38
+ assert_raises(ArgumentError) {UnnamedValue.new(-1)}
39
+ assert_raises(ArgumentError) {UnnamedValue.new(-18743)}
40
+ end
41
+ end
@@ -0,0 +1,19 @@
1
+ require 'test/unit'
2
+
3
+ require 'rockit/assembler/llvm/module'
4
+ include Rockit::Assembler::LLVM
5
+
6
+ class UTestLLVMInstructions < Test::Unit::TestCase
7
+ # Hello world example module
8
+ class TestModule1 < LLVM::Module
9
+ LC0 = internal constant '[13 x sbyte]' c("hello world\0A")
10
+
11
+ declare int "puts", [sbytep]
12
+
13
+ defmethod("main", int, []) do
14
+
15
+ end
16
+ end
17
+
18
+ def te
19
+ end
@@ -0,0 +1,44 @@
1
+ require 'test/unit'
2
+
3
+ require 'rockit/prettyprint/box'
4
+ include Rockit::PrettyPrint
5
+
6
+ class UTestBox < Test::Unit::TestCase
7
+ def setup
8
+ @h = Box::H.new(1, "a")
9
+ @h1 = Box::H.new(1, "a", "b")
10
+ @h2 = Box::H.new(2, "a", "b")
11
+ @h3 = Box::H.new(3, "a", "b", "c")
12
+ @v = Box::V.new("a", "2 2", "c")
13
+ @e = Box::Epsilon.new("x", " ", ":=")
14
+ end
15
+
16
+ def test_01_creation
17
+ assert_kind_of(Box::H, @h)
18
+ assert_equal(1, @h.num_spaces)
19
+ assert_equal(["a"], @h.elements)
20
+
21
+ assert_kind_of(Box::H, @h3)
22
+ assert_equal(3, @h3.num_spaces)
23
+ assert_equal(["a", "b", "c"], @h3.elements)
24
+
25
+ assert_kind_of(Box::V, @v)
26
+ assert_equal(["a", "2 2", "c"], @v.elements)
27
+
28
+ assert_kind_of(Box::Epsilon, @e)
29
+ end
30
+
31
+ def test_02_render
32
+ assert_equal("a", @h.render)
33
+ assert_equal("a b", @h1.render)
34
+ assert_equal("a b", @h2.render)
35
+ assert_equal("a b c", @h3.render)
36
+ assert_equal("a\n2 2\nc", @v.render)
37
+ assert_equal("x :=", @e.render)
38
+ end
39
+
40
+ def test_03_prepend
41
+ p = Box::Prepend["#", "A comment"]
42
+ assert_equal("# A comment", p.render)
43
+ end
44
+ end
@@ -0,0 +1,301 @@
1
+ require 'test/unit'
2
+
3
+ require 'rockit/tree/base'
4
+ require 'samples/rockit/ruby/sample_ruby_ast_trees/mr_1'
5
+
6
+ class UTestTreeBase < Test::Unit::TestCase
7
+ def setup
8
+ @a = Rockit::Tree::Base.new_tree_class(:A)
9
+ @b = Rockit::Tree::Base.new_tree_class(:B, [:c1])
10
+ @c = Rockit::Tree::Base.new_tree_class(:C, [:c1, :c2])
11
+ end
12
+
13
+ def test_01_subclass_with_no_named_children
14
+ t = @a[1]
15
+ assert_kind_of(@a, t)
16
+ assert_equal(1, t.children.length)
17
+ assert_equal(1, t[0])
18
+
19
+ t2 = @a["1", 2]
20
+ assert_kind_of(@a, t2)
21
+ assert_equal(2, t2.children.length)
22
+ assert_equal("1", t2[0])
23
+ assert_equal(2, t2[1])
24
+ end
25
+
26
+ def test_02_subclass_with_one_named_child
27
+ t = @b[:a]
28
+ assert_kind_of(@b, t)
29
+ assert_equal(1, t.children.length)
30
+ assert_equal(:a, t[0])
31
+ assert_equal(:a, t.c1)
32
+ end
33
+
34
+ def test_03_subclass_with_two_named_children
35
+ t = @c[3.0, 4]
36
+ assert_kind_of(@c, t)
37
+ assert_equal(2, t.children.length)
38
+ assert_equal(3.0, t[0])
39
+ assert_equal(3.0, t.c1)
40
+ assert_equal(4, t[1])
41
+ assert_equal(4, t.c2)
42
+
43
+ t.c1 = 5
44
+ assert_equal(5, t[0])
45
+ assert_equal(5, t.c1)
46
+
47
+ t.c2 = 6
48
+ assert_equal(6, t[1])
49
+ assert_equal(6, t.c2)
50
+ end
51
+
52
+ def test_04_complex_tree
53
+ t = @a[@b[@c[1, 2]], @c[3, 4]]
54
+ assert_kind_of(@a, t)
55
+ assert_kind_of(@b, t[0])
56
+ assert_kind_of(@c, t[1])
57
+ assert_kind_of(@c, t[0][0])
58
+ assert_equal(1, t[0][0][0])
59
+ assert_equal(2, t[0][0][1])
60
+ assert_equal(3, t[1][0])
61
+ assert_equal(4, t[1][1])
62
+ end
63
+
64
+ def test_05_subclass_of_tree
65
+ @d = @a.new_tree_class(:D, [:d1, :d2])
66
+
67
+ t = @d["sub", /a/]
68
+ assert_kind_of(@d, t)
69
+ assert_kind_of(@a, t)
70
+ assert_equal("sub", t[0])
71
+ assert_equal("sub", t.d1)
72
+ assert_equal(/a/, t[1])
73
+ assert_equal(/a/, t.d2)
74
+ end
75
+
76
+ def test_06_upcase_symbols_to_patternvar
77
+ t = @a[:X]
78
+ nt = t.upcase_symbols_to_pattern_vars
79
+ assert_kind_of(@a, nt)
80
+ pvar = nt[0]
81
+ assert_kind_of(Rockit::Tree::Base::PatternVar, pvar)
82
+ assert_equal(:X, pvar.name)
83
+
84
+ t2 = @c[@b[:X], @a[:Y, :Z]]
85
+ nt2 = t2.upcase_symbols_to_pattern_vars
86
+ assert_kind_of(@c, nt2)
87
+ xvar = nt2[0][0]
88
+ assert_kind_of(Rockit::Tree::Base::PatternVar, xvar)
89
+ assert_equal(:X, pvar.name)
90
+ yvar = nt2[1][0]
91
+ assert_kind_of(Rockit::Tree::Base::PatternVar, yvar)
92
+ assert_equal(:Y, yvar.name)
93
+ zvar = nt2[1][1]
94
+ assert_kind_of(Rockit::Tree::Base::PatternVar, zvar)
95
+ assert_equal(:Z, zvar.name)
96
+ end
97
+
98
+ def assert_match_result(expected, tree, pattern)
99
+ actual = pattern.upcase_symbols_to_pattern_vars.match_tree(tree)
100
+ assert_equal(expected, actual)
101
+ end
102
+
103
+ def test_07_match_tree_simple
104
+ pattern = @a[:X].upcase_symbols_to_pattern_vars
105
+ tree = @a[1]
106
+ res = pattern.match_tree(tree)
107
+ assert_kind_of(Hash, res)
108
+ assert_equal(1, res[:X])
109
+
110
+ t2 = @a[t3 = @b[1]]
111
+ assert_match_result({:X => t3}, t2, pattern)
112
+ end
113
+
114
+ def test_08_match_tree_complex
115
+ pattern = @c[@b[:X], @a[:Y]].upcase_symbols_to_pattern_vars
116
+ tree = @c[@b["23"], @a[/a/]]
117
+ res = pattern.match_tree(tree)
118
+ assert_kind_of(Hash, res)
119
+ assert_equal("23", res[:X])
120
+ assert_equal(/a/, res[:Y])
121
+
122
+ pattern = @b[@c[:L, :R]].upcase_symbols_to_pattern_vars
123
+ t2 = @b[t3 = @c[3, 4]]
124
+ res = pattern.match_tree(t2)
125
+ assert_equal({:L => 3, :R => 4}, res)
126
+ end
127
+
128
+ def test_09_match_tree_complex_with_subtrees
129
+ pattern = @c[@b[:ARNE], @a[:STree]].upcase_symbols_to_pattern_vars
130
+ stree = @c[3, 4]
131
+ tree = @c[@b[1.4], @a[stree]]
132
+ res = pattern.match_tree(tree)
133
+ assert_kind_of(Hash, res)
134
+ assert_equal(1.4, res[:ARNE])
135
+ assert_equal(stree, res[:STree])
136
+ end
137
+
138
+ def test_10_regexp_style_matching
139
+ stree = @a[]
140
+ res = @b[@c[stree, 2]] =~ @b[@c[:First, :Second]]
141
+ assert_kind_of(Hash, res)
142
+ assert_equal(2, res[:Second])
143
+ assert_equal(stree, res[:First])
144
+ end
145
+
146
+ def test_11_failing_match_tree
147
+ assert_match_result(nil, @b[1], @a[])
148
+ assert_match_result(nil, @a[1], @b[])
149
+ assert_match_result(nil, @a[1], @a[2])
150
+ assert_match_result(nil, @c[@a[], 1], @c[@a[], 2])
151
+ assert_match_result(nil, @c[@a[], "1"], @c[@a[], "2"])
152
+ end
153
+
154
+ def assert_pp(expected, tree, width = 79)
155
+ actual = ""
156
+ PP.pp(tree, actual, width)
157
+ assert_equal(expected, actual)
158
+ end
159
+
160
+ def test_12_pretty_print
161
+ assert_pp("A[1]\n", @a[1])
162
+ assert_pp("A[B[2]]\n", @a[@b[2]])
163
+ assert_pp("C[B[3.0], /a/]\n", @c[@b[3.0], /a/])
164
+ lstr = "." * 75
165
+ assert_pp("C[\n B[3.0],\n #{lstr.inspect}]\n", @c[@b[3.0], lstr])
166
+ end
167
+
168
+ def collect_trees(tree)
169
+ ary = []
170
+ tree.each_tree {|t| ary << t}
171
+ ary
172
+ end
173
+
174
+ def test_13_each_tree_simple
175
+ t = @a[]
176
+ assert_equal([t], collect_trees(t))
177
+ end
178
+
179
+ def test_14_each_tree_complex
180
+ t = @c[t2 = @b[t3 = @a[1]], t4 = @b[2]]
181
+ assert_equal([t, t2, t3, 1, t4, 2], collect_trees(t))
182
+ end
183
+
184
+ def collect_trees_of_class(tree, klass, recursive = false)
185
+ ary = []
186
+ tree.each_tree_of_class(klass, recursive) {|t| ary << t}
187
+ ary
188
+ end
189
+
190
+ def test_15_each_tree_of_klass
191
+ t = @c[t2 = @b[t3 = @a[t4 = @b[1]]], t5 = @b[t6 = @c[3, 4]]]
192
+ assert_equal([t2, t5], collect_trees_of_class(t, @b))
193
+ assert_equal([t2, t4, t5], collect_trees_of_class(t, @b, true))
194
+ assert_equal([t3], collect_trees_of_class(t, @a))
195
+ assert_equal([t], collect_trees_of_class(t, @c))
196
+ assert_equal([t, t6], collect_trees_of_class(t, @c, true))
197
+ end
198
+
199
+ def test_16_set_parents_and_parent
200
+ t = @c[t2 = @b[t3 = @a[t4 = @b[1]]], t5 = @b[t6 = @c[3, 4]]]
201
+
202
+ assert_equal(nil, t.parent)
203
+ assert_equal(nil, t2.parent)
204
+ assert_equal(nil, t3.parent)
205
+ assert_equal(nil, t4.parent)
206
+ assert_equal(nil, t5.parent)
207
+ assert_equal(nil, t6.parent)
208
+
209
+ t.set_parents
210
+
211
+ assert_equal(nil, t.parent)
212
+ assert_equal(t, t2.parent)
213
+ assert_equal(t2, t3.parent)
214
+ assert_equal(t3, t4.parent)
215
+ assert_equal(t, t5.parent)
216
+ assert_equal(t5, t6.parent)
217
+ end
218
+
219
+ def test_17_all_matching_trees
220
+ t = @c[t2 = @b[t3 = @a[t4 = @b[1]]], t5 = @b[t6 = @c[3, 4]]]
221
+
222
+ pattern = @a[:X]
223
+ res = pattern.all_matching_trees(t)
224
+ assert_kind_of(Array, res)
225
+ assert_equal(1, res.length)
226
+ mapping, subtree = res[0]
227
+ assert_kind_of(Hash, mapping)
228
+ assert_equal({:X => t4}, mapping)
229
+ assert_kind_of(Rockit::Tree::Base, subtree)
230
+ assert_equal(t3, subtree)
231
+
232
+ pattern = @b[:X]
233
+ res = pattern.all_matching_trees(t)
234
+ assert_equal(3, res.length)
235
+ assert_equal({:X => t3}, res[0][0])
236
+ assert_equal(t2, res[0][1])
237
+ assert_equal({:X => 1}, res[1][0])
238
+ assert_equal(t4, res[1][1])
239
+ assert_equal({:X => t6}, res[2][0])
240
+ assert_equal(t5, res[2][1])
241
+
242
+ pattern = @c[:Left, :Right]
243
+ res = pattern.all_matching_trees(t)
244
+ assert_equal(2, res.length)
245
+ assert_equal({:Left => t2, :Right => t5}, res[0][0])
246
+ assert_equal(t, res[0][1])
247
+ assert_equal({:Left => 3, :Right => 4}, res[1][0])
248
+ assert_equal(t6, res[1][1])
249
+
250
+ pattern = @b[@a[:Z]]
251
+ res = pattern.all_matching_trees(t)
252
+ assert_equal(1, res.length)
253
+ assert_equal({:Z => t4}, res[0][0])
254
+ assert_equal(t2, res[0][1])
255
+
256
+ pattern = @b[@c[:L, :R]]
257
+ res = pattern.all_matching_trees(t)
258
+ assert_equal(1, res.length)
259
+ assert_equal({:L => 3, :R => 4}, res[0][0])
260
+ assert_equal(t5, res[0][1])
261
+ end
262
+
263
+ def test_18_bug_with_nested_string_child
264
+ t = @a["y", 1]
265
+ res = @a["y", :X].upcase_symbols_to_pattern_vars.match_tree(t)
266
+ assert_equal({:X => 1}, res)
267
+
268
+ t = @a[@b["y"], 1]
269
+ res = @a[@b["y"], :X].upcase_symbols_to_pattern_vars.match_tree(t)
270
+ assert_equal({:X => 1}, res)
271
+
272
+ res = @a[@b["y"], :X].all_matching_trees(t)
273
+ assert_equal(1, res.length)
274
+ end
275
+
276
+ def test_18_complex_tree_binop_bug
277
+ pattern = BinOpCall[:X, "-", :Y]
278
+ res = pattern.all_matching_trees(MR1Tree)
279
+ assert_equal(1, res.length)
280
+
281
+ res = BinOpCall[:X, "/", :Y].all_matching_trees(MR1Tree)
282
+ assert_equal(1, res.length)
283
+
284
+ res = BinOpCall[:X, "+", :Y].all_matching_trees(MR1Tree)
285
+ assert_equal(1, res.length)
286
+
287
+ res = BinOpCall[:X, "*", :Y].all_matching_trees(MR1Tree)
288
+ assert_equal(0, res.length)
289
+
290
+ res = Assign[LVar["y"], :X].all_matching_trees(MR1Tree)
291
+ assert_equal(4, res.length)
292
+ end
293
+
294
+ def test_19_should_traverse_into_arrays
295
+ # We need this since it is quite common that a collection of statements
296
+ # are simply given in an Array. It might be a design smell though!
297
+ tree = @a[[@b[1]]]
298
+ bs = tree.select_trees_of_class(@b)
299
+ assert_equal(1, bs.length)
300
+ end
301
+ end
@@ -0,0 +1,69 @@
1
+ require 'test/unit'
2
+
3
+ require 'rockit/tree/enter_leave_visitor'
4
+
5
+ class UTestTreeEnterLeaveVisitor < Test::Unit::TestCase
6
+ def setup
7
+ @a = Rockit::Tree::Base.new_tree_class(:A)
8
+ @b = Rockit::Tree::Base.new_tree_class(:B, [:c1])
9
+ @c = Rockit::Tree::Base.new_tree_class(:C, [:c1, :c2])
10
+ @d = Rockit::Tree::Base.new_tree_class(:D)
11
+ @e = Rockit::Tree::Base.new_tree_class(:E)
12
+ end
13
+
14
+ # Visits a node both on the way down in the tree and on the way up.
15
+ # Still a depth-first search.
16
+ class TreeELVisitor
17
+ include EnterLeaveVisitor
18
+
19
+ def initialize
20
+ @visited = []
21
+ end
22
+
23
+ def [](index); @visited[index]; end
24
+
25
+ def enter_A(obj); @visited << obj; end
26
+ def leave_A(obj); @visited << obj; end
27
+ def enter_B(obj); @visited << obj; end
28
+ def leave_B(obj); @visited << obj; end
29
+ def enter_C(obj); @visited << obj; end
30
+ def leave_C(obj); @visited << obj; end
31
+ def visit_E(obj); @visited << obj; end
32
+ end
33
+
34
+ class TreeAndFixnumELVisitor < TreeELVisitor
35
+ def enter_Fixnum(obj); @visited << obj; end
36
+ end
37
+
38
+ def test_01_visitor
39
+ tree = @c[tb1 = @b[ta = @a[@d[te = @e[]]]], tb2 = @b[t1 = 1]]
40
+ visitor = TreeELVisitor.new
41
+ tree.accept_visitor(visitor)
42
+
43
+ assert_equal(tree, visitor[0])
44
+ assert_equal(tb1, visitor[1])
45
+ assert_equal(ta, visitor[2])
46
+ # D is never visited sine we have no enter, visit or leave method for it.
47
+ # E is visited even though we only have a visit method but no enter or
48
+ # leave methods.
49
+ assert_equal(te, visitor[3])
50
+ assert_equal(ta, visitor[4])
51
+ assert_equal(tb1, visitor[5])
52
+ assert_equal(tb2, visitor[6])
53
+ assert_equal(tb2, visitor[7])
54
+ assert_equal(tree, visitor[8])
55
+
56
+ visitor2 = TreeAndFixnumELVisitor.new
57
+ tree.accept_visitor(visitor2)
58
+ assert_equal(tree, visitor2[0])
59
+ assert_equal(tb1, visitor2[1])
60
+ assert_equal(ta, visitor2[2])
61
+ assert_equal(te, visitor[3])
62
+ assert_equal(ta, visitor2[4])
63
+ assert_equal(tb1, visitor2[5])
64
+ assert_equal(tb2, visitor2[6])
65
+ assert_equal(1, visitor2[7])
66
+ assert_equal(tb2, visitor2[8])
67
+ assert_equal(tree, visitor2[9])
68
+ end
69
+ end
@@ -0,0 +1,63 @@
1
+ require 'test/unit'
2
+
3
+ require 'rockit/tree/visitor'
4
+
5
+ class UTestTreeVisitor < Test::Unit::TestCase
6
+ def setup
7
+ @a = Rockit::Tree::Base.new_tree_class(:A)
8
+ @b = Rockit::Tree::Base.new_tree_class(:B, [:c1])
9
+ @c = Rockit::Tree::Base.new_tree_class(:C, [:c1, :c2])
10
+ end
11
+
12
+ class TreeVisitor
13
+ include Visitor
14
+
15
+ def initialize
16
+ @visited = []
17
+ end
18
+
19
+ def [](index); @visited[index]; end
20
+
21
+ def visit_A(obj)
22
+ @visited << obj
23
+ end
24
+
25
+ def visit_B(obj)
26
+ @visited << obj
27
+ end
28
+
29
+ def visit_C(obj)
30
+ @visited << obj
31
+ end
32
+ end
33
+
34
+ class TreeAndFixnumVisitor < TreeVisitor
35
+ def visit_Fixnum(obj)
36
+ @visited << obj
37
+ end
38
+ end
39
+
40
+ def test_01_visitor
41
+ tree = @c[tb1 = @b[ta = @a[]], tb2 = @b[t1 = 1]]
42
+ visitor = TreeVisitor.new
43
+ tree.accept_visitor(visitor)
44
+ # The visitor pattern by default does a depth-first visit of the nodes
45
+ # in the tree. Note that the 1 is not in the visited list since the visitor
46
+ # has no method to visit Fixnums.
47
+ assert_equal(tree, visitor[0])
48
+ assert_equal(tb1, visitor[1])
49
+ assert_equal(ta, visitor[2])
50
+ assert_equal(tb2, visitor[3])
51
+
52
+ # This visitor has a method to visit Fixnums so it should have the same
53
+ # obj's in the visited array as the previous one but then followed by
54
+ # the 1 that is the child of the tb2 tree above.
55
+ visitor2 = TreeAndFixnumVisitor.new
56
+ tree.accept_visitor(visitor2)
57
+ assert_equal(tree, visitor2[0])
58
+ assert_equal(tb1, visitor2[1])
59
+ assert_equal(ta, visitor2[2])
60
+ assert_equal(tb2, visitor2[3])
61
+ assert_equal(t1, visitor2[4])
62
+ end
63
+ end