rockit 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/BUGS +13 -0
- data/LICENSE +280 -0
- data/README +172 -0
- data/TODO +53 -0
- data/VERSION +1 -0
- data/lib/packrat/grammar.rb +537 -0
- data/lib/rockit/prettyprint/box.rb +60 -0
- data/lib/rockit/prettyprint/renderer.rb +41 -0
- data/lib/rockit/prettyprint/text_renderer.rb +47 -0
- data/lib/rockit/tree/base.rb +223 -0
- data/lib/rockit/tree/enter_leave_visitor.rb +12 -0
- data/lib/rockit/tree/graphviz.rb +69 -0
- data/lib/rockit/tree/visitor.rb +12 -0
- data/lib/util/array_alternatives.rb +20 -0
- data/lib/util/enter_leave_visitor.rb +69 -0
- data/lib/util/graphviz_dot.rb +182 -0
- data/lib/util/string_location.rb +42 -0
- data/lib/util/visitor.rb +49 -0
- data/lib/util/visitor_combinators.rb +14 -0
- data/rakefile +200 -0
- data/tests/acceptance/packrat/minibasic/atest_minibasic.rb +45 -0
- data/tests/acceptance/packrat/minibasic/minibasic.rb +137 -0
- data/tests/acceptance/rockit/dparser/atest_any_operator.rb +33 -0
- data/tests/acceptance/rockit/dparser/atest_arithmetic_grammar.rb +30 -0
- data/tests/acceptance/rockit/dparser/atest_list_operator.rb +57 -0
- data/tests/acceptance/rockit/dparser/atest_mult_operator.rb +60 -0
- data/tests/acceptance/rockit/dparser/atest_operator_grammar.rb +61 -0
- data/tests/acceptance/rockit/dparser/atest_plus_operator.rb +55 -0
- data/tests/acceptance/rockit/dparser/atest_samples_calculator.rb +14 -0
- data/tests/acceptance/rockit/dparser/atest_samples_minibasic.rb +20 -0
- data/tests/acceptance/rockit/dparser/atest_samples_multifunccalculator.rb +36 -0
- data/tests/acceptance/rockit/dparser/atest_simple_grammar.rb +34 -0
- data/tests/acceptance/rockit/dparser/atest_speculative_code_action.rb +128 -0
- data/tests/acceptance/rockit/dparser/calc_tests_common.rb +103 -0
- data/tests/unit/packrat/test_interpreting_parser.rb +296 -0
- data/tests/unit/parse/utest_ebnf_grammar.rb +50 -0
- data/tests/unit/parse/utest_expand_grammar.rb +23 -0
- data/tests/unit/parse/utest_grammar.rb +160 -0
- data/tests/unit/rockit/assembler/llvm/utest_instructions.rb +41 -0
- data/tests/unit/rockit/assembler/llvm/utest_module.rb +19 -0
- data/tests/unit/rockit/prettyprint/utest_box.rb +44 -0
- data/tests/unit/rockit/tree/utest_tree_base.rb +301 -0
- data/tests/unit/rockit/tree/utest_tree_enter_leave_visitor.rb +69 -0
- data/tests/unit/rockit/tree/utest_tree_visitor.rb +63 -0
- data/tests/unit/rockit/utest_grammar.rb +145 -0
- data/tests/unit/rockit/utest_grammar_symbol.rb +11 -0
- data/tests/unit/rockit/utest_maybe_operator.rb +12 -0
- data/tests/unit/rockit/utest_regexp_terminal.rb +45 -0
- data/tests/unit/rockit/utest_repetition_operators.rb +35 -0
- data/tests/unit/rockit/utest_rule.rb +23 -0
- data/tests/unit/rockit/utest_string_terminal.rb +40 -0
- data/tests/unit/util/utest_array_alternatives.rb +23 -0
- data/tests/unit/util/utest_enter_leave_visitor.rb +89 -0
- data/tests/unit/util/utest_string_location.rb +42 -0
- data/tests/unit/util/utest_visitor.rb +92 -0
- data/tests/unit/util/utest_visitor_combinators.rb +64 -0
- metadata +112 -0
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'rockit/grammar'
|
4
|
+
include Rockit
|
5
|
+
|
6
|
+
class UTestGrammar < Test::Unit::TestCase
|
7
|
+
def test_01_creation
|
8
|
+
g = Rockit::Grammar.new
|
9
|
+
assert_kind_of(Rockit::Grammar, g)
|
10
|
+
end
|
11
|
+
|
12
|
+
TestGrammar1 = Rockit::Grammar.new do
|
13
|
+
rule :A, [["1", :B, :C]]
|
14
|
+
rule :B, [["2", :D]]
|
15
|
+
term :C, "a"
|
16
|
+
term :D, "b"
|
17
|
+
end
|
18
|
+
|
19
|
+
def symbols_as_strings(symbols)
|
20
|
+
symbols.map {|s| s.to_s}.sort
|
21
|
+
end
|
22
|
+
|
23
|
+
def assert_symbols(expected, actual, msg = "")
|
24
|
+
assert_equal(symbols_as_strings(expected), symbols_as_strings(actual), msg)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_02_simple_grammar
|
28
|
+
assert_kind_of(Rockit::Grammar, TestGrammar1)
|
29
|
+
|
30
|
+
assert_equal(2, TestGrammar1.rules.length)
|
31
|
+
assert_symbols([:A, :B], TestGrammar1.nonterminals)
|
32
|
+
assert_equal(2, TestGrammar1.terms.length)
|
33
|
+
assert_symbols([:C, :D], TestGrammar1.terms.keys)
|
34
|
+
|
35
|
+
assert_kind_of(Rule, ra = TestGrammar1.rules.first)
|
36
|
+
assert_kind_of(Rule, rb = TestGrammar1.rules.last)
|
37
|
+
|
38
|
+
assert_kind_of(Terminal, TestGrammar1.terms[:C])
|
39
|
+
assert_kind_of(Terminal, TestGrammar1.terms[:D])
|
40
|
+
|
41
|
+
assert_equal(:A, ra.name)
|
42
|
+
assert_equal(3, (rarhs = ra.right_hand_side).length)
|
43
|
+
rarhs1, rarhs2, rarhs3 = rarhs
|
44
|
+
assert_kind_of(StringTerminal, rarhs1)
|
45
|
+
assert_kind_of(NonTerminal, rarhs2)
|
46
|
+
assert_kind_of(NonTerminal, rarhs3)
|
47
|
+
assert_equal("1", rarhs1.string)
|
48
|
+
assert_equal(:B, rarhs2.symbol)
|
49
|
+
assert_equal(:C, rarhs3.symbol)
|
50
|
+
|
51
|
+
assert_equal(:B, rb.name)
|
52
|
+
assert_equal(2, (rbrhs = rb.right_hand_side).length)
|
53
|
+
rbrhs1, rbrhs2 = rbrhs
|
54
|
+
assert_kind_of(StringTerminal, rbrhs1)
|
55
|
+
assert_kind_of(NonTerminal, rbrhs2)
|
56
|
+
assert_equal("2", rbrhs1.string)
|
57
|
+
assert_equal(:D, rbrhs2.symbol)
|
58
|
+
end
|
59
|
+
|
60
|
+
Arithmetic = Rockit::Grammar.new do
|
61
|
+
# Additive <- Multitive '+' Additive
|
62
|
+
# / Multitive
|
63
|
+
# Multitive <- Primary '*' Multitive
|
64
|
+
# / Primary
|
65
|
+
# Primary <- '(' Additive ')'
|
66
|
+
# / Decimal
|
67
|
+
# Decimal <- '0' / '1' / '2' / '3' / '4' / '5' / '6' / '7' / '8' / '9'
|
68
|
+
|
69
|
+
start :Additive, [
|
70
|
+
[:Multitive, '+', :Additive],
|
71
|
+
[:Multitive],
|
72
|
+
]
|
73
|
+
rule :Multitive, [
|
74
|
+
[:Primary, '*', :Multitive],
|
75
|
+
[:Primary]
|
76
|
+
]
|
77
|
+
rule :Primary, [
|
78
|
+
['(', :Additive, ')'],
|
79
|
+
[:Decimal]
|
80
|
+
]
|
81
|
+
term :Decimal, /[0-9]/
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_03_arithmetic_grammar
|
85
|
+
assert_equal(6, Arithmetic.rules.length)
|
86
|
+
assert_symbols([:Additive, :Multitive, :Primary], Arithmetic.nonterminals)
|
87
|
+
assert_equal(1, Arithmetic.terms.length)
|
88
|
+
assert_symbols([:Decimal], Arithmetic.terms.keys)
|
89
|
+
assert_equal(:Additive, Arithmetic.start_symbol)
|
90
|
+
assert_raise(NotImplementedError) {Arithmetic.new_parser.parse("2")}
|
91
|
+
|
92
|
+
ras = Arithmetic.find_rules(:Additive)
|
93
|
+
assert_equal(2, ras.length)
|
94
|
+
ra1, ra2 = ras
|
95
|
+
|
96
|
+
assert_equal(:Additive, ra1.name)
|
97
|
+
assert_equal(3, (ra1rhs = ra1.right_hand_side).length)
|
98
|
+
assert_kind_of(NonTerminal, ra1rhs[0])
|
99
|
+
assert_kind_of(StringTerminal, ra1rhs[1])
|
100
|
+
assert_kind_of(NonTerminal, ra1rhs[2])
|
101
|
+
assert_equal(:Multitive, ra1rhs[0].symbol)
|
102
|
+
assert_equal("+", ra1rhs[1].string)
|
103
|
+
assert_equal(:Additive, ra1rhs[2].symbol)
|
104
|
+
|
105
|
+
assert_equal(:Additive, ra2.name)
|
106
|
+
assert_equal(1, (ra2rhs = ra2.right_hand_side).length)
|
107
|
+
assert_kind_of(NonTerminal, ra2rhs[0])
|
108
|
+
assert_equal(:Multitive, ra2rhs[0].symbol)
|
109
|
+
|
110
|
+
td = Arithmetic.terms[:Decimal]
|
111
|
+
assert_equal(:Decimal, td.name)
|
112
|
+
rdrhs1 = td.right_hand_side
|
113
|
+
assert_equal(1, rdrhs1.length)
|
114
|
+
assert_kind_of(RegexpTerminal, rdrhs1[0])
|
115
|
+
end
|
116
|
+
|
117
|
+
Operators = Rockit::Grammar.new do
|
118
|
+
start :Number, [
|
119
|
+
[plus(:Digit), maybe(/e|E/), maybe("-")],
|
120
|
+
[:Dummy]
|
121
|
+
]
|
122
|
+
rule :Dummy, [[mult("a"), rep("b", 3, 6)]]
|
123
|
+
term :Digit, /[0-9]/
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_04_operators
|
127
|
+
assert_equal(3, Operators.rules.length)
|
128
|
+
assert_symbols([:Number, :Dummy], Operators.nonterminals)
|
129
|
+
assert_equal(1, Operators.terms.length)
|
130
|
+
assert_symbols([:Digit], Operators.terms.keys)
|
131
|
+
assert_equal(:Number, Operators.start_symbol)
|
132
|
+
|
133
|
+
rn1, rn2 = Operators.find_rules(:Number)
|
134
|
+
assert_equal(:Number, rn1.name)
|
135
|
+
|
136
|
+
assert_equal(3, (rn1rhs = rn1.right_hand_side).length)
|
137
|
+
assert_kind_of(Plus, rn1rhs[0])
|
138
|
+
assert_kind_of(Maybe, rn1rhs[1])
|
139
|
+
assert_kind_of(Maybe, rn1rhs[2])
|
140
|
+
|
141
|
+
assert_kind_of(NonTerminal, rn1rhs[0].symbol)
|
142
|
+
assert_kind_of(RegexpTerminal, rn1rhs[1].symbol)
|
143
|
+
assert_kind_of(StringTerminal, rn1rhs[2].symbol)
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'rockit/grammar'
|
4
|
+
include Rockit
|
5
|
+
|
6
|
+
require 'strscan'
|
7
|
+
|
8
|
+
class UTestRegexpTerminal < Test::Unit::TestCase
|
9
|
+
def setup
|
10
|
+
@ret = RegexpTerminal.new(/a/)
|
11
|
+
@retas = RegexpTerminal.new(/a+/)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_01_smoke
|
15
|
+
assert_kind_of(RegexpTerminal, @ret)
|
16
|
+
assert_kind_of(GrammarSymbol, @ret)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_02_inspect
|
20
|
+
assert_kind_of(String, @ret.inspect)
|
21
|
+
assert_equal("/a/", @ret.inspect)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_03_regexp
|
25
|
+
assert_kind_of(Regexp, @ret.regexp)
|
26
|
+
assert_equal(/\s*(a)/, @ret.regexp)
|
27
|
+
assert_equal(/\s*(a+)/, @retas.regexp)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_04_scan
|
31
|
+
s = StringScanner.new("a")
|
32
|
+
assert_equal("a", @ret.scan(s))
|
33
|
+
assert_equal(1, s.pos)
|
34
|
+
|
35
|
+
s = StringScanner.new("b")
|
36
|
+
assert_equal(nil, @ret.scan(s))
|
37
|
+
assert_equal(0, s.pos)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_05_dont_scan_over_whitespace
|
41
|
+
s = StringScanner.new("a b")
|
42
|
+
assert_equal("a", @ret.scan(s))
|
43
|
+
assert_equal(1, s.pos)
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'rockit/grammar'
|
4
|
+
include Rockit
|
5
|
+
|
6
|
+
class UTestRepetitionOperator < Test::Unit::TestCase
|
7
|
+
def test_01_creation_of_repetition
|
8
|
+
r = Repetition.new(:A, 2, 10)
|
9
|
+
assert_kind_of(Repetition, r)
|
10
|
+
assert_kind_of(Operator, r)
|
11
|
+
assert_kind_of(GrammarSymbol, r)
|
12
|
+
assert_equal(2, r.min)
|
13
|
+
assert_equal(10, r.max)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_02_creation_of_mult
|
17
|
+
r = Mult.new(:C)
|
18
|
+
assert_kind_of(Mult, r)
|
19
|
+
assert_kind_of(Repetition, r)
|
20
|
+
assert_kind_of(Operator, r)
|
21
|
+
assert_kind_of(GrammarSymbol, r)
|
22
|
+
assert_equal(0, r.min)
|
23
|
+
assert_equal((1.0/0.0), r.max)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_03_creation_of_plus
|
27
|
+
r = Plus.new(:C)
|
28
|
+
assert_kind_of(Plus, r)
|
29
|
+
assert_kind_of(Repetition, r)
|
30
|
+
assert_kind_of(Operator, r)
|
31
|
+
assert_kind_of(GrammarSymbol, r)
|
32
|
+
assert_equal(1, r.min)
|
33
|
+
assert_equal((1.0/0.0), r.max)
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'rockit/grammar'
|
4
|
+
include Rockit
|
5
|
+
|
6
|
+
class UTestRule < Test::Unit::TestCase
|
7
|
+
def test_01_empty_rule
|
8
|
+
r = Rule.new(:r1, [])
|
9
|
+
assert_equal(:r1, r.name)
|
10
|
+
assert_equal([], r.right_hand_side)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_02
|
14
|
+
r = Rule.new(:r1, [[:a, "B"]])
|
15
|
+
assert_equal(:r1, r.name)
|
16
|
+
assert_equal(2, r.right_hand_side.length)
|
17
|
+
s1, s2 = r.right_hand_side
|
18
|
+
assert_kind_of(NonTerminal, s1)
|
19
|
+
assert_kind_of(StringTerminal, s2)
|
20
|
+
assert_equal(:a, s1.symbol)
|
21
|
+
assert_equal("B", s2.string)
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'rockit/grammar'
|
4
|
+
include Rockit
|
5
|
+
|
6
|
+
require 'strscan'
|
7
|
+
|
8
|
+
class UTestStringTerminal < Test::Unit::TestCase
|
9
|
+
def setup
|
10
|
+
@sta = StringTerminal.new("a")
|
11
|
+
@stp = StringTerminal.new("+")
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_01_smoke
|
15
|
+
assert_kind_of(StringTerminal, @sta)
|
16
|
+
assert_kind_of(GrammarSymbol, @sta)
|
17
|
+
assert_kind_of(StringTerminal, @stp)
|
18
|
+
assert_kind_of(GrammarSymbol, @stp)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_02_inspect
|
22
|
+
assert_kind_of(String, @sta.inspect)
|
23
|
+
assert_equal("a", @sta.inspect)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_03_string
|
27
|
+
assert_kind_of(String, @sta.string)
|
28
|
+
assert_equal("a", @sta.string)
|
29
|
+
assert_kind_of(String, @stp.string)
|
30
|
+
assert_equal("+", @stp.string)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_04_regexp
|
34
|
+
assert_kind_of(Regexp, @sta.regexp)
|
35
|
+
assert_equal(/\s*(a)/, @sta.regexp)
|
36
|
+
assert_kind_of(Regexp, @stp.regexp)
|
37
|
+
assert_equal(/\s*(\+)/, @stp.regexp)
|
38
|
+
assert_equal("/\\s*(\\+)/", @stp.regexp.inspect)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'util/array_alternatives'
|
3
|
+
|
4
|
+
class UTestArrayAlternatives < Test::Unit::TestCase
|
5
|
+
def test_01_normal_use
|
6
|
+
first, second, third = [1], [2], [3, 4]
|
7
|
+
a = first / second / third
|
8
|
+
alts = a.assemble_alternatives
|
9
|
+
assert_kind_of(Array, alts)
|
10
|
+
assert_equal(3, alts.length)
|
11
|
+
assert_equal(first, alts[0])
|
12
|
+
assert_equal(second, alts[1])
|
13
|
+
assert_equal(third, alts[2])
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_02_without_any_alternatives
|
17
|
+
a = [1]
|
18
|
+
alts = a.assemble_alternatives
|
19
|
+
assert_kind_of(Array, alts)
|
20
|
+
assert_equal(1, alts.length)
|
21
|
+
assert_equal(a, alts[0])
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'util/enter_leave_visitor'
|
3
|
+
|
4
|
+
class TestEnterLeaveVisitor < Test::Unit::TestCase
|
5
|
+
class Mock
|
6
|
+
end
|
7
|
+
|
8
|
+
class SuperMock
|
9
|
+
include EnterLeaveVisitable
|
10
|
+
end
|
11
|
+
|
12
|
+
class ELMock < SuperMock
|
13
|
+
end
|
14
|
+
|
15
|
+
class SuperTELVisitor
|
16
|
+
include EnterLeaveVisitor
|
17
|
+
attr_reader :calls
|
18
|
+
def initialize; @calls = []; end
|
19
|
+
|
20
|
+
def enter_SuperMock(obj); @calls << :enterSuperM; end
|
21
|
+
def visit_SuperMock(obj); @calls << :visitSuperM; end
|
22
|
+
def leave_SuperMock(obj); @calls << :leaveSuperM; end
|
23
|
+
end
|
24
|
+
|
25
|
+
class TELVisitor < SuperTELVisitor
|
26
|
+
def enter_Mock(obj); @calls << :enterM; end
|
27
|
+
def visit_Mock(obj); @calls << :visitM; end
|
28
|
+
def leave_Mock(obj); @calls << :leaveM; end
|
29
|
+
|
30
|
+
def enter_ELMock(obj); @calls << :enterELM; end
|
31
|
+
def visit_ELMock(obj); @calls << :visitELM; end
|
32
|
+
def leave_ELMock(obj); @calls << :leaveELM; end
|
33
|
+
|
34
|
+
def enter_SMock(obj); @calls << :enterSM; end
|
35
|
+
def visit_SMock(obj); @calls << :visitSM; end
|
36
|
+
def leave_SMock(obj); @calls << :leaveSM; end
|
37
|
+
end
|
38
|
+
|
39
|
+
class SMock
|
40
|
+
def initialize(c1, c2)
|
41
|
+
@c1, @c2 = c1, c2
|
42
|
+
end
|
43
|
+
def accept_visitor(v)
|
44
|
+
v.visit_me_then_children self, [@c1, @c2]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class EmptyVisitor
|
49
|
+
include EnterLeaveVisitor
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_01_empty_visitor
|
53
|
+
visitor, m = EmptyVisitor.new, ELMock.new
|
54
|
+
assert_nothing_raised {m.accept_visitor(visitor)}
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_02_visit_std_visitable
|
58
|
+
visitor, m = TELVisitor.new, Mock.new
|
59
|
+
visitor.visit m
|
60
|
+
assert_equal([:enterM, :visitM, :leaveM], visitor.calls)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_03_visit_enterleavevisitable
|
64
|
+
visitor, m = TELVisitor.new, ELMock.new
|
65
|
+
visitor.visit m
|
66
|
+
assert_equal([:enterELM, :visitELM, :leaveELM], visitor.calls)
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_04_visit_nested_objects
|
70
|
+
visitor, sm = TELVisitor.new, SMock.new(c1 = ELMock.new, c2 = ELMock.new)
|
71
|
+
sm.accept_visitor(visitor)
|
72
|
+
assert_equal([:enterSM, :visitSM,
|
73
|
+
:enterELM, :visitELM, :leaveELM,
|
74
|
+
:enterELM, :visitELM, :leaveELM,
|
75
|
+
:leaveSM], visitor.calls)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_05_visit_superclass_visit_method
|
79
|
+
visitor, m1 = SuperTELVisitor.new, ELMock.new
|
80
|
+
m1.accept_visitor(visitor)
|
81
|
+
assert_equal([:enterSuperM, :visitSuperM, :leaveSuperM], visitor.calls)
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_06_visit_our_visitmethod_if_available_both_for_us_and_for_superclass
|
85
|
+
visitor, m1 = TELVisitor.new, ELMock.new
|
86
|
+
m1.accept_visitor(visitor)
|
87
|
+
assert_equal([:enterELM, :visitELM, :leaveELM], visitor.calls)
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'util/string_location'
|
4
|
+
|
5
|
+
class UTestStringLocation < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@sl = StringLocations.new "a\nb\nc\r\nd"
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_01_creation
|
11
|
+
assert_kind_of(StringLocations, @sl)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_02_line
|
15
|
+
assert_equal(1, @sl.line(0))
|
16
|
+
assert_equal(1, @sl.line(1))
|
17
|
+
assert_equal(2, @sl.line(2))
|
18
|
+
assert_equal(2, @sl.line(3))
|
19
|
+
assert_equal(3, @sl.line(4))
|
20
|
+
assert_equal(3, @sl.line(5))
|
21
|
+
assert_equal(3, @sl.line(6))
|
22
|
+
assert_equal(4, @sl.line(7))
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_03_column
|
26
|
+
assert_equal(0, @sl.column(0))
|
27
|
+
assert_equal(1, @sl.column(1))
|
28
|
+
assert_equal(0, @sl.column(2))
|
29
|
+
assert_equal(1, @sl.column(3))
|
30
|
+
assert_equal(0, @sl.column(4))
|
31
|
+
assert_equal(1, @sl.column(5))
|
32
|
+
assert_equal(2, @sl.column(6))
|
33
|
+
assert_equal(0, @sl.column(7))
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_04_location
|
37
|
+
assert_equal([1, 0], @sl.location(0))
|
38
|
+
assert_equal([1, 1], @sl.location(1))
|
39
|
+
assert_equal([2, 0], @sl.location(2))
|
40
|
+
assert_equal([2, 1], @sl.location(3))
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'util/visitor'
|
3
|
+
|
4
|
+
class TestVisitor < Test::Unit::TestCase
|
5
|
+
class SuperMock
|
6
|
+
include Visitable
|
7
|
+
end
|
8
|
+
|
9
|
+
class Mock < SuperMock
|
10
|
+
attr_reader :children, :visited
|
11
|
+
def initialize
|
12
|
+
@children = []
|
13
|
+
end
|
14
|
+
def accept_visitor(visitor)
|
15
|
+
@visited = true
|
16
|
+
visitor.visit_me_then_children self, @children
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class TVisitor
|
21
|
+
include Visitor
|
22
|
+
attr_reader :count
|
23
|
+
def initialize; @count = 0; end
|
24
|
+
def visit_Mock(obj); @count += 1; end
|
25
|
+
end
|
26
|
+
|
27
|
+
class EmptyVisitor
|
28
|
+
include Visitor
|
29
|
+
end
|
30
|
+
|
31
|
+
# To test whether super class visit method is used if there is no one
|
32
|
+
# for the actual class
|
33
|
+
class SuperMockVisitor
|
34
|
+
include Visitor
|
35
|
+
attr_reader :count
|
36
|
+
def initialize; @count = 0; end
|
37
|
+
def visit_SuperMock(obj); @count += 1; end
|
38
|
+
end
|
39
|
+
|
40
|
+
class MockAndSuperMockVisitor
|
41
|
+
include Visitor
|
42
|
+
attr_reader :countSM, :countM
|
43
|
+
def initialize; @countM = @countSM = 0; end
|
44
|
+
def visit_SuperMock(obj); @countSM += 1; end
|
45
|
+
def visit_Mock(obj); @countM += 1; end
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_01_empty_visitor
|
49
|
+
visitor, m = EmptyVisitor.new, Mock.new
|
50
|
+
assert_nothing_raised {m.accept_visitor(visitor)}
|
51
|
+
assert(m.visited)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_02_visit
|
55
|
+
visitor, m = TVisitor.new, Mock.new
|
56
|
+
assert_equal(0, visitor.count)
|
57
|
+
visitor.visit(m)
|
58
|
+
assert_equal(1, visitor.count)
|
59
|
+
m.accept_visitor(visitor)
|
60
|
+
assert_equal(2, visitor.count)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_03_visit_nested
|
64
|
+
visitor, m1 = TVisitor.new, Mock.new
|
65
|
+
m1.children << (m2 = Mock.new)
|
66
|
+
m2.children << (m3 = Mock.new)
|
67
|
+
m1.accept_visitor(visitor)
|
68
|
+
assert_equal(3, visitor.count)
|
69
|
+
assert(m1.visited)
|
70
|
+
assert(m2.visited)
|
71
|
+
assert(m3.visited)
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_04_visit_superclass_visit_method
|
75
|
+
visitor, m1 = SuperMockVisitor.new, Mock.new
|
76
|
+
m1.accept_visitor(visitor)
|
77
|
+
assert_equal(1, visitor.count)
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_05_visit_our_visitmethod_if_available_both_for_us_and_for_superclass
|
81
|
+
visitor, m1 = MockAndSuperMockVisitor.new, Mock.new
|
82
|
+
m1.accept_visitor(visitor)
|
83
|
+
assert_equal(1, visitor.countM)
|
84
|
+
assert_equal(0, visitor.countSM)
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_06_visit_each
|
88
|
+
visitor, a = TVisitor.new, [Mock.new, Mock.new]
|
89
|
+
visitor.visit_each(a)
|
90
|
+
assert_equal(2, visitor.count)
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'util/visitor_combinators'
|
4
|
+
|
5
|
+
require 'util/visitor'
|
6
|
+
|
7
|
+
class UTestVisitorCombinators < Test::Unit::TestCase
|
8
|
+
class Tree
|
9
|
+
attr_reader :children, :visitors
|
10
|
+
def initialize(*children)
|
11
|
+
@children, @visitors = children, []
|
12
|
+
end
|
13
|
+
def accept_visitor(visitor)
|
14
|
+
@visitors << visitor.object_id
|
15
|
+
visitor.visit_me_and_my_children(self, @children)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Doesn't touch the visited nodes, just saves the fact that they have been
|
20
|
+
# visited
|
21
|
+
class TIdentityVisitor
|
22
|
+
include Visitor
|
23
|
+
attr_reader :visited
|
24
|
+
def initialize
|
25
|
+
@visited = []
|
26
|
+
end
|
27
|
+
def visit_Tree(tree)
|
28
|
+
@visited << tree
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def setup
|
33
|
+
@l1, @l2, @l3 = Tree.new, Tree.new, Tree.new
|
34
|
+
@i = Tree.new(@l2, @l3)
|
35
|
+
@r = Tree.new(@l1, @i)
|
36
|
+
@nodes = [@r, @l1, @i, @l2, @l3]
|
37
|
+
end
|
38
|
+
|
39
|
+
def assert_topdown_leftright_visited(visitor)
|
40
|
+
assert_equal(@r, visitor.visited[0])
|
41
|
+
assert_equal(@l1, visitor.visited[1])
|
42
|
+
assert_equal(@i, visitor.visited[2])
|
43
|
+
assert_equal(@l2, visitor.visited[3])
|
44
|
+
assert_equal(@l3, visitor.visited[4])
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_01_identity_visitor
|
48
|
+
@r.accept_visitor(iv = TIdentityVisitor.new)
|
49
|
+
assert_equal(5, iv.visited.length)
|
50
|
+
assert_topdown_leftright_visited(iv)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_02_sequence_visitor
|
54
|
+
sv = SequenceVisitor.new(iv1 = TIdentityVisitor.new, iv2 = TIdentityVisitor.new)
|
55
|
+
@r.accept_visitor(sv)
|
56
|
+
assert_topdown_leftright_visited(iv1)
|
57
|
+
assert_topdown_leftright_visited(iv2)
|
58
|
+
# Seems leaf nodes are visited many times by iv1 and iv2 so the assert
|
59
|
+
# does not hold.
|
60
|
+
# @nodes.each do |n|
|
61
|
+
# assert_equal([sv.id, iv1.id, iv2.id], n.visitors)
|
62
|
+
# end
|
63
|
+
end
|
64
|
+
end
|