citrus 2.1.2 → 2.2.0

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.
data/test/grammar_test.rb CHANGED
@@ -1,17 +1,10 @@
1
1
  require File.expand_path('../helper', __FILE__)
2
2
 
3
3
  class GrammarTest < Test::Unit::TestCase
4
-
5
4
  def test_new
6
- g = Grammar.new
7
- assert_kind_of(Module, g)
8
- assert(g.include?(Grammar))
9
- end
10
-
11
- def test_non_module_fail
12
- assert_raise ArgumentError do
13
- ''.extend(GrammarMethods)
14
- end
5
+ grammar = Grammar.new
6
+ assert_kind_of(Module, grammar)
7
+ assert(grammar.include?(Grammar))
15
8
  end
16
9
 
17
10
  def test_name
@@ -72,6 +65,8 @@ class GrammarTest < Test::Unit::TestCase
72
65
  }
73
66
  match = grammar.parse('1234')
74
67
  assert(match)
68
+ assert_equal('123', match)
69
+ assert_equal(3, match.length)
75
70
  end
76
71
 
77
72
  def test_parse_sequence_short
@@ -135,5 +130,4 @@ class GrammarTest < Test::Unit::TestCase
135
130
  grammar(:abc)
136
131
  end
137
132
  end
138
-
139
133
  end
data/test/helper.rb CHANGED
@@ -2,15 +2,11 @@ lib = File.expand_path('../../lib', __FILE__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  require 'test/unit'
5
- require 'citrus/debug'
5
+ require 'citrus'
6
6
 
7
7
  class Test::Unit::TestCase
8
8
  include Citrus
9
9
 
10
- def input(str='')
11
- Input.new(str)
12
- end
13
-
14
10
  TestGrammar = Grammar.new do
15
11
  rule :alpha do
16
12
  /[a-zA-Z]/
@@ -49,18 +45,6 @@ class Test::Unit::TestCase
49
45
  end
50
46
  end
51
47
 
52
- class EqualRule
53
- include Citrus::Rule
54
-
55
- def initialize(value)
56
- @value = value
57
- end
58
-
59
- def match(input)
60
- create_match(@value.to_s.dup) if @value.to_s == input.string
61
- end
62
- end
63
-
64
48
  module CalcTestMethods
65
49
  # A helper method that tests the successful parsing and evaluation of the
66
50
  # given mathematical expression.
data/test/input_test.rb CHANGED
@@ -1,8 +1,13 @@
1
1
  require File.expand_path('../helper', __FILE__)
2
2
 
3
3
  class InputTest < Test::Unit::TestCase
4
+ def test_memoized?
5
+ input = Input.new('')
6
+ input.memoize!
7
+ assert(input.memoized?)
8
+ end
4
9
 
5
- def test_new_input
10
+ def test_offsets_new
6
11
  input = Input.new("abc\ndef\nghi")
7
12
  assert_equal(0, input.line_offset)
8
13
  assert_equal(0, input.line_index)
@@ -10,7 +15,7 @@ class InputTest < Test::Unit::TestCase
10
15
  assert_equal("abc\n", input.line)
11
16
  end
12
17
 
13
- def test_advanced_input
18
+ def test_offsets_advanced
14
19
  input = Input.new("abc\ndef\nghi")
15
20
  input.pos = 6
16
21
  assert_equal(2, input.line_offset)
@@ -19,4 +24,169 @@ class InputTest < Test::Unit::TestCase
19
24
  assert_equal("def\n", input.line)
20
25
  end
21
26
 
27
+ def test_events
28
+ a = Rule.new('a')
29
+ b = Rule.new('b')
30
+ c = Rule.new('c')
31
+ s = Rule.new([ a, b, c ])
32
+ r = Repeat.new(s, 0, Infinity)
33
+
34
+ input = Input.new("abcabcabc")
35
+ events = input.exec(r)
36
+
37
+ expected_events = [
38
+ r.id,
39
+ s.id,
40
+ a.id, CLOSE, 1,
41
+ b.id, CLOSE, 1,
42
+ c.id, CLOSE, 1,
43
+ CLOSE, 3,
44
+ s.id,
45
+ a.id, CLOSE, 1,
46
+ b.id, CLOSE, 1,
47
+ c.id, CLOSE, 1,
48
+ CLOSE, 3,
49
+ s.id,
50
+ a.id, CLOSE, 1,
51
+ b.id, CLOSE, 1,
52
+ c.id, CLOSE, 1,
53
+ CLOSE, 3,
54
+ CLOSE, 9
55
+ ]
56
+
57
+ assert_equal(expected_events, events)
58
+ end
59
+
60
+ def test_events2
61
+ a = Rule.new('a')
62
+ b = Rule.new('b')
63
+ c = Choice.new([ a, b ])
64
+ r = Repeat.new(c, 0, Infinity)
65
+ s = Rule.new([ a, r ])
66
+
67
+ input = Input.new('abbababba')
68
+ events = input.exec(s)
69
+
70
+ expected_events = [
71
+ s.id,
72
+ a.id, CLOSE, 1,
73
+ r.id,
74
+ c.id,
75
+ b.id, CLOSE, 1,
76
+ CLOSE, 1,
77
+ c.id,
78
+ b.id, CLOSE, 1,
79
+ CLOSE, 1,
80
+ c.id,
81
+ a.id, CLOSE, 1,
82
+ CLOSE, 1,
83
+ c.id,
84
+ b.id, CLOSE, 1,
85
+ CLOSE, 1,
86
+ c.id,
87
+ a.id, CLOSE, 1,
88
+ CLOSE, 1,
89
+ c.id,
90
+ b.id, CLOSE, 1,
91
+ CLOSE, 1,
92
+ c.id,
93
+ b.id, CLOSE, 1,
94
+ CLOSE, 1,
95
+ c.id,
96
+ a.id, CLOSE, 1,
97
+ CLOSE, 1,
98
+ CLOSE, 8,
99
+ CLOSE, 9
100
+ ]
101
+
102
+ assert_equal(expected_events, events)
103
+ end
104
+
105
+ grammar :LetterA do
106
+ rule :top do
107
+ any(:three_as, :two_as, :one_a)
108
+ end
109
+
110
+ rule :three_as do
111
+ rep(:one_a, 3, 3)
112
+ end
113
+
114
+ rule :two_as do
115
+ rep(:one_a, 2, 2)
116
+ end
117
+
118
+ rule :one_a do
119
+ "a"
120
+ end
121
+ end
122
+
123
+ def test_cache_hits1
124
+ input = Input.new('a')
125
+ input.memoize!
126
+ input.exec(LetterA.rule(:top))
127
+ assert_equal(3, input.cache_hits)
128
+ end
129
+
130
+ def test_cache_hits2
131
+ input = Input.new('aa')
132
+ input.memoize!
133
+ input.exec(LetterA.rule(:top))
134
+ assert_equal(2, input.cache_hits)
135
+ end
136
+
137
+ def test_cache_hits3
138
+ input = Input.new('aaa')
139
+ input.memoize!
140
+ input.exec(LetterA.rule(:top))
141
+ assert_equal(0, input.cache_hits)
142
+ end
143
+
144
+ grammar :Addition do
145
+ rule :additive do
146
+ all(:number, :plus, label(any(:additive, :number), 'term')) {
147
+ number.value + term.value
148
+ }
149
+ end
150
+
151
+ rule :number do
152
+ all(/[0-9]+/, :space) {
153
+ strip.to_i
154
+ }
155
+ end
156
+
157
+ rule :plus do
158
+ all('+', :space)
159
+ end
160
+
161
+ rule :space do
162
+ /[ \t]*/
163
+ end
164
+ end
165
+
166
+ def test_match
167
+ match = Addition.parse('+', :root => :plus)
168
+ assert(match)
169
+ assert(match.matches)
170
+ assert_equal(2, match.matches.length)
171
+
172
+ match = Addition.parse('+ ', :root => :plus)
173
+ assert(match)
174
+ assert(match.matches)
175
+ assert_equal(2, match.matches.length)
176
+
177
+ match = Addition.parse('99', :root => :number)
178
+ assert(match)
179
+ assert(match.matches)
180
+ assert_equal(2, match.matches.length)
181
+
182
+ match = Addition.parse('99 ', :root => :number)
183
+ assert(match)
184
+ assert(match.matches)
185
+ assert_equal(2, match.matches.length)
186
+
187
+ match = Addition.parse('1+2')
188
+ assert(match)
189
+ assert(match.matches)
190
+ assert_equal(3, match.matches.length)
191
+ end
22
192
  end
data/test/label_test.rb CHANGED
@@ -1,20 +1,11 @@
1
1
  require File.expand_path('../helper', __FILE__)
2
2
 
3
3
  class LabelTest < Test::Unit::TestCase
4
-
5
4
  def test_terminal?
6
5
  rule = Label.new
7
6
  assert_equal(false, rule.terminal?)
8
7
  end
9
8
 
10
- def test_match
11
- rule = Label.new('a', 'label')
12
-
13
- match = rule.match(input('a'))
14
- assert(match)
15
- assert_equal(:label, match.name)
16
- end
17
-
18
9
  def test_to_s
19
10
  rule = Label.new('a', 'label')
20
11
  assert_equal('label:"a"', rule.to_s)
@@ -22,5 +13,4 @@ class LabelTest < Test::Unit::TestCase
22
13
  rule = Label.new(Sequence.new(%w< a b >), 'label')
23
14
  assert_equal('label:("a" "b")', rule.to_s)
24
15
  end
25
-
26
16
  end
data/test/match_test.rb CHANGED
@@ -1,56 +1,112 @@
1
1
  require File.expand_path('../helper', __FILE__)
2
2
 
3
3
  class MatchTest < Test::Unit::TestCase
4
-
5
- def test_string
4
+ def test_string_equality
6
5
  match = Match.new('hello')
7
6
  assert_equal('hello', match)
8
- assert_equal(5, match.length)
9
- end
10
-
11
- def test_array_string
12
- match1 = Match.new('a')
13
- match2 = Match.new('b')
14
- match = Match.new([match1, match2])
15
- assert_equal('ab', match)
16
- assert_equal(2, match.length)
17
- assert_equal(2, match.matches.length)
18
7
  end
19
8
 
20
- def test_equality
9
+ def test_match_equality
21
10
  match1 = Match.new('a')
22
11
  match2 = Match.new('a')
23
- assert(match1 == 'a')
24
12
  assert(match1 == match2)
25
13
  assert(match2 == match1)
14
+ end
26
15
 
27
- match3 = Match.new('b')
28
- assert_equal(false, match1 == match3)
29
- assert_equal(false, match3 == match1)
16
+ def test_match_inequality
17
+ match1 = Match.new('a')
18
+ match2 = Match.new('b')
19
+ assert_equal(false, match1 == match2)
20
+ assert_equal(false, match2 == match1)
30
21
  end
31
22
 
32
- def test_matches
33
- match = Double.parse('123')
34
- assert(match)
35
- assert_equal(3, match.matches.length)
36
- assert_equal(3, match.find(:num).length)
23
+ def test_names
24
+ a = Rule.new('a')
25
+ a.name = 'a'
26
+ b = Rule.new('b')
27
+ b.name = 'b'
28
+ c = Rule.new('c')
29
+ c.name = 'c'
30
+ s = Rule.new([ a, b, c ])
31
+ s.name = 's'
32
+ r = Repeat.new(s, 0, Infinity)
33
+ r.name = 'r'
34
+
35
+ events = [
36
+ r.id,
37
+ s.id,
38
+ a.id, CLOSE, 1,
39
+ b.id, CLOSE, 1,
40
+ c.id, CLOSE, 1,
41
+ CLOSE, 3,
42
+ s.id,
43
+ a.id, CLOSE, 1,
44
+ b.id, CLOSE, 1,
45
+ c.id, CLOSE, 1,
46
+ CLOSE, 3,
47
+ s.id,
48
+ a.id, CLOSE, 1,
49
+ b.id, CLOSE, 1,
50
+ c.id, CLOSE, 1,
51
+ CLOSE, 3,
52
+ CLOSE, 9
53
+ ]
54
+
55
+ match = Match.new("abcabcabc", events)
56
+ assert(match.names)
57
+ assert_equal([:r], match.names)
58
+
59
+ match.matches.each do |m|
60
+ assert_equal([:s], m.names)
61
+ end
37
62
  end
38
63
 
39
- def test_match
40
- match = Double.parse('456')
41
- assert(match)
64
+ def test_matches
65
+ a = Rule.new('a')
66
+ b = Rule.new('b')
67
+ c = Rule.new('c')
68
+ s = Rule.new([ a, b, c ])
69
+ s.name = 's'
70
+ r = Repeat.new(s, 0, Infinity)
71
+
72
+ events = [
73
+ r.id,
74
+ s.id,
75
+ a.id, CLOSE, 1,
76
+ b.id, CLOSE, 1,
77
+ c.id, CLOSE, 1,
78
+ CLOSE, 3,
79
+ s.id,
80
+ a.id, CLOSE, 1,
81
+ b.id, CLOSE, 1,
82
+ c.id, CLOSE, 1,
83
+ CLOSE, 3,
84
+ s.id,
85
+ a.id, CLOSE, 1,
86
+ b.id, CLOSE, 1,
87
+ c.id, CLOSE, 1,
88
+ CLOSE, 3,
89
+ CLOSE, 9
90
+ ]
91
+
92
+ match = Match.new("abcabcabc", events)
93
+ assert(match.matches)
42
94
  assert_equal(3, match.matches.length)
43
95
 
44
- num = match.first(:num)
45
- assert(num)
46
- assert_equal('4', num)
47
- assert_equal(4, num.value)
48
- end
96
+ sub_events = [
97
+ s.id,
98
+ a.id, CLOSE, 1,
99
+ b.id, CLOSE, 1,
100
+ c.id, CLOSE, 1,
101
+ CLOSE, 3
102
+ ]
49
103
 
50
- def test_matches_deep
51
- match = Words.parse('one two three four')
52
- assert(match)
53
- assert_equal(15, match.find(:alpha).length)
104
+ match.matches.each do |m|
105
+ assert_equal(sub_events, m.events)
106
+ assert_equal(:s, m.name)
107
+ assert_equal("abc", m)
108
+ assert(m.matches)
109
+ assert_equal(3, m.matches.length)
110
+ end
54
111
  end
55
-
56
112
  end
@@ -2,7 +2,7 @@ require File.expand_path('../helper', __FILE__)
2
2
 
3
3
  class MultibyteTest < Test::Unit::TestCase
4
4
  Citrus.eval(<<-'CODE')
5
- grammar MultibyteTest::Grammar
5
+ grammar MultibyteTest::Multibyte
6
6
  rule string
7
7
  "\xFF"
8
8
  end
@@ -18,17 +18,17 @@ class MultibyteTest < Test::Unit::TestCase
18
18
  CODE
19
19
 
20
20
  def test_multibyte_string
21
- m = Grammar.parse("\xFF", :root => :string)
21
+ m = Multibyte.parse("\xFF", :root => :string)
22
22
  assert(m)
23
23
  end
24
24
 
25
25
  def test_multibyte_regexp
26
- m = Grammar.parse("\xFF", :root => :regexp)
26
+ m = Multibyte.parse("\xFF", :root => :regexp)
27
27
  assert(m)
28
28
  end
29
29
 
30
30
  def test_multibyte_character_class
31
- m = Grammar.parse("\xFF", :root => :character_class)
31
+ m = Multibyte.parse("\xFF", :root => :character_class)
32
32
  assert(m)
33
33
  end
34
34
  end