citrus 2.2.2 → 2.3.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/calc_test.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  require File.expand_path('../helper', __FILE__)
2
2
 
3
- if defined?(Calc)
4
- Object.__send__(:remove_const, :Calc)
5
- end
6
-
7
3
  require File.expand_path('../../examples/calc', __FILE__)
8
4
 
9
5
  class CalcTest < Test::Unit::TestCase
10
6
  include CalcTestMethods
7
+
8
+ def do_test(expr)
9
+ super(expr, Calc)
10
+ end
11
11
  end
data/test/choice_test.rb CHANGED
@@ -7,8 +7,8 @@ class ChoiceTest < Test::Unit::TestCase
7
7
  end
8
8
 
9
9
  def test_exec
10
- a = Rule.new('a')
11
- b = Rule.new('b')
10
+ a = Rule.for('a')
11
+ b = Rule.for('b')
12
12
  rule = Choice.new([ a, b ])
13
13
 
14
14
  events = rule.exec(Input.new(''))
@@ -16,11 +16,11 @@ class ChoiceTest < Test::Unit::TestCase
16
16
 
17
17
  events = rule.exec(Input.new('a'))
18
18
  assert(events)
19
- assert_equal([rule.id, a.id, CLOSE, 1, CLOSE, 1], events)
19
+ assert_equal([rule, a, CLOSE, 1, CLOSE, 1], events)
20
20
 
21
21
  events = rule.exec(Input.new('b'))
22
22
  assert(events)
23
- assert_equal([rule.id, b.id, CLOSE, 1, CLOSE, 1], events)
23
+ assert_equal([rule, b, CLOSE, 1, CLOSE, 1], events)
24
24
  end
25
25
 
26
26
  def test_to_s
@@ -28,10 +28,16 @@ class ChoiceTest < Test::Unit::TestCase
28
28
  assert_equal('"a" | "b"', rule.to_s)
29
29
  end
30
30
 
31
- def test_to_s_embed
31
+ def test_to_embedded_s
32
32
  rule1 = Choice.new(%w<a b>)
33
33
  rule2 = Choice.new(%w<c d>)
34
34
  rule = Choice.new([rule1, rule2])
35
35
  assert_equal('("a" | "b") | ("c" | "d")', rule.to_s)
36
36
  end
37
+
38
+ def test_to_s_with_label
39
+ rule = Choice.new(%w<a b>)
40
+ rule.label = 'a_label'
41
+ assert_equal('a_label:("a" | "b")', rule.to_s)
42
+ end
37
43
  end
@@ -7,13 +7,11 @@ class ExtensionTest < Test::Unit::TestCase
7
7
  end
8
8
  end
9
9
 
10
- NumericProc = Proc.new {
10
+ module NumericModule
11
11
  def add_one
12
12
  to_i + 1
13
13
  end
14
- }
15
-
16
- NumericModule = Module.new(&NumericProc)
14
+ end
17
15
 
18
16
  NumericProcBare = Proc.new {
19
17
  to_i + 1
@@ -27,14 +25,6 @@ class ExtensionTest < Test::Unit::TestCase
27
25
  assert_equal(:test, match.a_test)
28
26
  end
29
27
 
30
- def test_numeric_proc
31
- rule = StringTerminal.new('1')
32
- rule.extension = NumericProc
33
- match = rule.parse('1')
34
- assert(match)
35
- assert_equal(2, match.add_one)
36
- end
37
-
38
28
  def test_numeric_module
39
29
  rule = StringTerminal.new('1')
40
30
  rule.extension = NumericModule
data/test/file_test.rb CHANGED
@@ -5,14 +5,14 @@ class CitrusFileTest < Test::Unit::TestCase
5
5
  ## File tests
6
6
 
7
7
  def run_file_test(file, root)
8
- match = File.parse(F.read(file), :root => root)
8
+ match = File.parse(::File.read(file), :root => root)
9
9
  assert(match)
10
10
  end
11
11
 
12
12
  %w<rule grammar>.each do |type|
13
- Dir[F.dirname(__FILE__) + "/_files/#{type}*.citrus"].each do |path|
13
+ Dir[::File.dirname(__FILE__) + "/_files/#{type}*.citrus"].each do |path|
14
14
  module_eval(<<-CODE.gsub(/^ /, ''), __FILE__, __LINE__ + 1)
15
- def test_#{F.basename(path, '.citrus')}
15
+ def test_#{::File.basename(path, '.citrus')}
16
16
  run_file_test("#{path}", :#{type})
17
17
  end
18
18
  CODE
@@ -24,173 +24,171 @@ class CitrusFileTest < Test::Unit::TestCase
24
24
  def test_rule_body_alias
25
25
  match = File.parse('rule_name', :root => :rule_body)
26
26
  assert(match)
27
- assert_kind_of(Rule, match.value)
28
27
  assert_instance_of(Alias, match.value)
29
28
  end
30
29
 
31
- def test_rule_body_terminal
30
+ def test_rule_body_dot
32
31
  match = File.parse('.', :root => :rule_body)
33
32
  assert(match)
34
- assert_kind_of(Rule, match.value)
35
33
  assert_instance_of(Terminal, match.value)
34
+ end
36
35
 
36
+ def test_rule_body_character_range
37
37
  match = File.parse('[a-z]', :root => :rule_body)
38
38
  assert(match)
39
- assert_kind_of(Rule, match.value)
40
39
  assert_instance_of(Terminal, match.value)
40
+ end
41
41
 
42
+ def test_rule_body_terminal
42
43
  match = File.parse('/./', :root => :rule_body)
43
44
  assert(match)
44
- assert_kind_of(Rule, match.value)
45
- assert_instance_of(Terminal, match.value)
46
-
47
- match = File.parse("[0-9] {\n def value\n text.to_i\n end\n}\n", :root => :rule_body)
48
- assert(match)
49
- assert_kind_of(Rule, match.value)
50
45
  assert_instance_of(Terminal, match.value)
51
46
  end
52
47
 
53
- def test_rule_body_string_terminal
48
+ def test_rule_body_string_terminal_empty
54
49
  match = File.parse('""', :root => :rule_body)
55
50
  assert(match)
56
- assert_kind_of(Rule, match.value)
57
51
  assert_instance_of(StringTerminal, match.value)
52
+ end
58
53
 
54
+ def test_rule_body_string_terminal
59
55
  match = File.parse('"a"', :root => :rule_body)
60
56
  assert(match)
61
- assert_kind_of(Rule, match.value)
62
57
  assert_instance_of(StringTerminal, match.value)
58
+ end
63
59
 
60
+ def test_rule_body_string_terminal_empty_block
64
61
  match = File.parse('"" {}', :root => :rule_body)
65
62
  assert(match)
66
- assert_kind_of(Rule, match.value)
67
63
  assert_instance_of(StringTerminal, match.value)
68
64
  end
69
65
 
70
- def test_rule_body_repeat
66
+ def test_rule_body_repeat_string_terminal
71
67
  match = File.parse('"a"*', :root => :rule_body)
72
68
  assert(match)
73
- assert_kind_of(Rule, match.value)
74
69
  assert_instance_of(Repeat, match.value)
75
- assert_equal(0, match.value.min)
76
- assert_equal(Infinity, match.value.max)
70
+ end
77
71
 
72
+ def test_rule_body_repeat_empty_string_terminal_block
78
73
  match = File.parse('""* {}', :root => :rule_body)
79
74
  assert(match)
80
- assert_kind_of(Rule, match.value)
81
75
  assert_instance_of(Repeat, match.value)
76
+ end
82
77
 
78
+ def test_rule_body_repeat_sequence
83
79
  match = File.parse('("a" "b")*', :root => :rule_body)
84
80
  assert(match)
85
- assert_kind_of(Rule, match.value)
86
81
  assert_instance_of(Repeat, match.value)
82
+ end
87
83
 
84
+ def test_rule_body_repeat_choice
88
85
  match = File.parse('("a" | "b")*', :root => :rule_body)
89
86
  assert(match)
90
- assert_kind_of(Rule, match.value)
91
87
  assert_instance_of(Repeat, match.value)
88
+ end
92
89
 
90
+ def test_rule_body_repeat_sequence_block
93
91
  match = File.parse('("a" "b")* {}', :root => :rule_body)
94
92
  assert(match)
95
- assert_kind_of(Rule, match.value)
96
93
  assert_instance_of(Repeat, match.value)
94
+ end
97
95
 
96
+ def test_rule_body_repeat_choice_block
98
97
  match = File.parse('("a" | "b")* {}', :root => :rule_body)
99
98
  assert(match)
100
- assert_kind_of(Rule, match.value)
101
99
  assert_instance_of(Repeat, match.value)
100
+ end
102
101
 
102
+ def test_rule_body_repeat_sequence_extension
103
103
  match = File.parse('("a" "b")* <Module>', :root => :rule_body)
104
104
  assert(match)
105
- assert_kind_of(Rule, match.value)
106
105
  assert_instance_of(Repeat, match.value)
106
+ end
107
107
 
108
+ def test_rule_body_repeat_sequence_extension_spaced
108
109
  match = File.parse('( "a" "b" )* <Module>', :root => :rule_body)
109
110
  assert(match)
110
- assert_kind_of(Rule, match.value)
111
111
  assert_instance_of(Repeat, match.value)
112
+ end
112
113
 
114
+ def test_rule_body_repeat_choice_extension
113
115
  match = File.parse('("a" | "b")* <Module>', :root => :rule_body)
114
116
  assert(match)
115
- assert_kind_of(Rule, match.value)
116
- assert_instance_of(Repeat, match.value)
117
-
118
- match = File.parse("[0-9]+ {\n def value\n text.to_i\n end\n}\n", :root => :rule_body)
119
- assert(match)
120
- assert_kind_of(Rule, match.value)
121
117
  assert_instance_of(Repeat, match.value)
122
118
  end
123
119
 
124
- def test_rule_body_choice
125
- match = File.parse('"a" | "b"', :root => :rule_body)
120
+ def test_rule_body_choice_terminal
121
+ match = File.parse('/./ | /./', :root => :rule_body)
126
122
  assert(match)
127
- assert_kind_of(Rule, match.value)
128
123
  assert_instance_of(Choice, match.value)
124
+ end
129
125
 
130
- match = File.parse('/./ | /./', :root => :rule_body)
126
+ def test_rule_body_choice_string_terminal
127
+ match = File.parse('"a" | "b"', :root => :rule_body)
131
128
  assert(match)
132
- assert_kind_of(Rule, match.value)
133
129
  assert_instance_of(Choice, match.value)
134
- assert_equal(1, match.find(:bar).length)
135
- assert_equal(2, match.find(:regular_expression).length)
136
- assert_equal(0, match.find(:dot).length)
130
+ end
137
131
 
132
+ def test_rule_body_choice_mixed
138
133
  match = File.parse('("a" | /./)', :root => :rule_body)
139
134
  assert(match)
140
- assert_kind_of(Rule, match.value)
141
135
  assert_instance_of(Choice, match.value)
136
+ end
142
137
 
138
+ def test_rule_body_choice_extended
143
139
  match = File.parse('("a" | "b") <Module>', :root => :rule_body)
144
140
  assert(match)
145
- assert_kind_of(Rule, match.value)
146
141
  assert_instance_of(Choice, match.value)
147
142
  end
148
143
 
149
- def test_rule_body_sequence
150
- match = File.parse('"a" "b"', :root => :rule_body)
144
+ def test_rule_body_sequence_terminal
145
+ match = File.parse('/./ /./', :root => :rule_body)
151
146
  assert(match)
152
- assert_kind_of(Rule, match.value)
153
147
  assert_instance_of(Sequence, match.value)
148
+ end
154
149
 
155
- match = File.parse('/./ /./', :root => :rule_body)
150
+ def test_rule_body_sequence_string_terminal
151
+ match = File.parse('"a" "b"', :root => :rule_body)
156
152
  assert(match)
157
- assert_kind_of(Rule, match.value)
158
153
  assert_instance_of(Sequence, match.value)
159
- assert_equal(2, match.find(:regular_expression).length)
154
+ end
160
155
 
156
+ def test_rule_body_sequence_extension
161
157
  match = File.parse('( "a" "b" ) <Module>', :root => :rule_body)
162
158
  assert(match)
163
- assert_kind_of(Rule, match.value)
164
159
  assert_instance_of(Sequence, match.value)
160
+ end
165
161
 
162
+ def test_rule_body_sequence_mixed
166
163
  match = File.parse('"a" ("b" | /./)* <Module>', :root => :rule_body)
167
164
  assert(match)
168
- assert_kind_of(Rule, match.value)
169
165
  assert_instance_of(Sequence, match.value)
166
+ end
170
167
 
168
+ def test_rule_body_sequence_block
171
169
  match = File.parse('"a" ("b" | /./)* {}', :root => :rule_body)
172
170
  assert(match)
173
- assert_kind_of(Rule, match.value)
174
171
  assert_instance_of(Sequence, match.value)
175
172
  end
176
173
 
177
- def test_precedence
174
+ def test_precedence_sequence_before_choice
178
175
  # Sequence should bind more tightly than Choice.
179
176
  match = File.parse('"a" "b" | "c"', :root => :rule_body)
180
177
  assert(match)
181
- assert_kind_of(Rule, match.value)
182
178
  assert_instance_of(Choice, match.value)
179
+ end
183
180
 
181
+ def test_precedence_parentheses
184
182
  # Parentheses should change binding precedence.
185
183
  match = File.parse('"a" ("b" | "c")', :root => :rule_body)
186
184
  assert(match)
187
- assert_kind_of(Rule, match.value)
188
185
  assert_instance_of(Sequence, match.value)
186
+ end
189
187
 
188
+ def test_precedence_repeat_before_predicate
190
189
  # Repeat should bind more tightly than AndPredicate.
191
190
  match = File.parse("&'a'+", :root => :rule_body)
192
191
  assert(match)
193
- assert_kind_of(Rule, match.value)
194
192
  assert_instance_of(AndPredicate, match.value)
195
193
  end
196
194
 
@@ -202,31 +200,39 @@ class CitrusFileTest < Test::Unit::TestCase
202
200
  def test_choice
203
201
  match = File.parse('"a" | "b"', :root => :choice)
204
202
  assert(match)
205
- assert_equal(2, match.rules.length)
206
203
  assert_instance_of(Choice, match.value)
207
204
  end
208
205
 
209
206
  def test_choice_embedded_sequence
210
207
  match = File.parse('"a" | ("b" "c")', :root => :choice)
211
208
  assert(match)
212
- assert_equal(2, match.rules.length)
213
209
  assert_instance_of(Choice, match.value)
214
210
  end
215
211
 
216
212
  def test_sequence
217
213
  match = File.parse('"" ""', :root => :sequence)
218
214
  assert(match)
219
- assert_equal(2, match.rules.length)
220
215
  assert_instance_of(Sequence, match.value)
221
216
  end
222
217
 
223
218
  def test_sequence_embedded_choice
224
219
  match = File.parse('"a" ("b" | "c")', :root => :sequence)
225
220
  assert(match)
226
- assert_equal(2, match.rules.length)
227
221
  assert_instance_of(Sequence, match.value)
228
222
  end
229
223
 
224
+ def test_label_expression
225
+ match = File.parse('label:""', :root => :label_expression)
226
+ assert(match)
227
+ assert_instance_of(StringTerminal, match.value)
228
+ end
229
+
230
+ def test_label_expression_space
231
+ match = File.parse('label :"" ', :root => :label_expression)
232
+ assert(match)
233
+ assert_instance_of(StringTerminal, match.value)
234
+ end
235
+
230
236
  def test_expression_tag
231
237
  match = File.parse('"" <Module>', :root => :expression)
232
238
  assert(match)
@@ -251,84 +257,66 @@ class CitrusFileTest < Test::Unit::TestCase
251
257
  def test_prefix_and
252
258
  match = File.parse('&""', :root => :prefix)
253
259
  assert(match)
254
- assert_kind_of(Rule, match.value)
255
260
  assert_instance_of(AndPredicate, match.value)
256
261
  end
257
262
 
258
263
  def test_prefix_not
259
264
  match = File.parse('!""', :root => :prefix)
260
265
  assert(match)
261
- assert_kind_of(Rule, match.value)
262
266
  assert_instance_of(NotPredicate, match.value)
263
267
  end
264
268
 
265
- def test_prefix_label
266
- match = File.parse('label:""', :root => :prefix)
269
+ def test_prefix_but
270
+ match = File.parse('~""', :root => :prefix)
267
271
  assert(match)
268
- assert_kind_of(Rule, match.value)
269
- assert_instance_of(Label, match.value)
270
- end
271
-
272
- def test_prefix_label_space
273
- match = File.parse('label :"" ', :root => :prefix)
274
- assert(match)
275
- assert_kind_of(Rule, match.value)
276
- assert_instance_of(Label, match.value)
272
+ assert_instance_of(ButPredicate, match.value)
277
273
  end
278
274
 
279
275
  def test_suffix_plus
280
276
  match = File.parse('""+', :root => :suffix)
281
277
  assert(match)
282
- assert_kind_of(Rule, match.value)
283
278
  assert_instance_of(Repeat, match.value)
284
279
  end
285
280
 
286
281
  def test_suffix_question
287
- match = File.parse('""? ', :root => :suffix)
282
+ match = File.parse('""?', :root => :suffix)
288
283
  assert(match)
289
- assert_kind_of(Rule, match.value)
290
284
  assert_instance_of(Repeat, match.value)
291
285
  end
292
286
 
293
287
  def test_suffix_star
294
288
  match = File.parse('""*', :root => :suffix)
295
289
  assert(match)
296
- assert_kind_of(Rule, match.value)
297
290
  assert_instance_of(Repeat, match.value)
298
291
  end
299
292
 
300
293
  def test_suffix_n_star
301
294
  match = File.parse('""1*', :root => :suffix)
302
295
  assert(match)
303
- assert_kind_of(Rule, match.value)
304
296
  assert_instance_of(Repeat, match.value)
305
297
  end
306
298
 
307
299
  def test_suffix_star_n
308
300
  match = File.parse('""*2', :root => :suffix)
309
301
  assert(match)
310
- assert_kind_of(Rule, match.value)
311
302
  assert_instance_of(Repeat, match.value)
312
303
  end
313
304
 
314
305
  def test_suffix_n_star_n
315
306
  match = File.parse('""1*2', :root => :suffix)
316
307
  assert(match)
317
- assert_kind_of(Rule, match.value)
318
308
  assert_instance_of(Repeat, match.value)
319
309
  end
320
310
 
321
311
  def test_primary_alias
322
312
  match = File.parse('rule_name', :root => :primary)
323
313
  assert(match)
324
- assert_kind_of(Rule, match.value)
325
314
  assert_instance_of(Alias, match.value)
326
315
  end
327
316
 
328
317
  def test_primary_string_terminal
329
318
  match = File.parse('"a"', :root => :primary)
330
319
  assert(match)
331
- assert_kind_of(Rule, match.value)
332
320
  assert_instance_of(StringTerminal, match.value)
333
321
  end
334
322
 
@@ -393,42 +381,36 @@ class CitrusFileTest < Test::Unit::TestCase
393
381
  def test_terminal_character_class
394
382
  match = File.parse('[a-z]', :root => :terminal)
395
383
  assert(match)
396
- assert_kind_of(Rule, match.value)
397
384
  assert_instance_of(Terminal, match.value)
398
385
  end
399
386
 
400
387
  def test_terminal_dot
401
388
  match = File.parse('.', :root => :terminal)
402
389
  assert(match)
403
- assert_kind_of(Rule, match.value)
404
390
  assert_instance_of(Terminal, match.value)
405
391
  end
406
392
 
407
393
  def test_terminal_regular_expression
408
394
  match = File.parse('/./', :root => :terminal)
409
395
  assert(match)
410
- assert_kind_of(Rule, match.value)
411
396
  assert_instance_of(Terminal, match.value)
412
397
  end
413
398
 
414
399
  def test_string_terminal_single_quoted
415
400
  match = File.parse("'a'", :root => :string_terminal)
416
401
  assert(match)
417
- assert_kind_of(Rule, match.value)
418
402
  assert_instance_of(StringTerminal, match.value)
419
403
  end
420
404
 
421
405
  def test_string_terminal_double_quoted
422
406
  match = File.parse('"a"', :root => :string_terminal)
423
407
  assert(match)
424
- assert_kind_of(Rule, match.value)
425
408
  assert_instance_of(StringTerminal, match.value)
426
409
  end
427
410
 
428
411
  def test_string_terminal_case_insensitive
429
412
  match = File.parse('`a`', :root => :string_terminal)
430
413
  assert(match)
431
- assert_kind_of(Rule, match.value)
432
414
  assert_instance_of(StringTerminal, match.value)
433
415
  end
434
416
 
@@ -498,122 +480,96 @@ class CitrusFileTest < Test::Unit::TestCase
498
480
  assert_equal('&', match.value)
499
481
  end
500
482
 
501
- def test_character_class
502
- match = File.parse('[_]', :root => :character_class)
503
- assert(match)
504
- assert_equal(/\A[_]/, match.value)
505
- end
506
-
507
- def test_character_class_a_z
508
- match = File.parse('[a-z]', :root => :character_class)
509
- assert(match)
510
- assert_equal(/\A[a-z]/, match.value)
511
- end
512
-
513
- def test_character_class_a_z_0_9
514
- match = File.parse('[a-z0-9]', :root => :character_class)
515
- assert(match)
516
- assert_equal(/\A[a-z0-9]/, match.value)
517
- end
518
-
519
- def test_character_class_nested_square_brackets
520
- match = File.parse('[\[-\]]', :root => :character_class)
521
- assert(match)
522
- assert_equal(/\A[\[-\]]/, match.value)
523
- end
524
-
525
- def test_character_class_hex_range
526
- match = File.parse('[\\x26-\\x29]', :root => :character_class)
527
- assert(match)
528
- assert_equal(/\A[\x26-\x29]/, match.value)
529
- end
530
-
531
- def test_dot
532
- match = File.parse('.', :root => :dot)
533
- assert(match)
534
- assert_equal(DOT, match.value)
535
- end
536
-
537
483
  def test_regular_expression
538
484
  match = File.parse('/./', :root => :regular_expression)
539
485
  assert(match)
540
- assert_equal(/./, match.value)
486
+ rule = match.value
487
+ assert_instance_of(Terminal, rule)
488
+ assert_equal(/./, rule.regexp)
541
489
  end
542
490
 
543
491
  def test_regular_expression_escaped_forward_slash
544
492
  match = File.parse('/\\//', :root => :regular_expression)
545
493
  assert(match)
546
- assert_equal(/\//, match.value)
494
+ rule = match.value
495
+ assert_instance_of(Terminal, rule)
496
+ assert_equal(/\//, rule.regexp)
547
497
  end
548
498
 
549
499
  def test_regular_expression_escaped_backslash
550
500
  match = File.parse('/\\\\/', :root => :regular_expression)
551
501
  assert(match)
552
- assert_equal(/\\/, match.value)
502
+ rule = match.value
503
+ assert_instance_of(Terminal, rule)
504
+ assert_equal(/\\/, rule.regexp)
553
505
  end
554
506
 
555
507
  def test_regular_expression_hex
556
508
  match = File.parse('/\\x26/', :root => :regular_expression)
557
509
  assert(match)
558
- assert_equal(/\x26/, match.value)
510
+ rule = match.value
511
+ assert_instance_of(Terminal, rule)
512
+ assert_equal(/\x26/, rule.regexp)
559
513
  end
560
514
 
561
515
  def test_regular_expression_with_flag
562
516
  match = File.parse('/a/i', :root => :regular_expression)
563
517
  assert(match)
564
- assert_equal(/a/i, match.value)
518
+ rule = match.value
519
+ assert_instance_of(Terminal, rule)
520
+ assert_equal(/a/i, rule.regexp)
565
521
  end
566
522
 
567
- def test_predicate_and
568
- match = File.parse('&', :root => :predicate)
569
- assert(match)
570
- assert_kind_of(Rule, match.value(''))
571
- end
572
-
573
- def test_predicate_not
574
- match = File.parse('!', :root => :predicate)
523
+ def test_character_class
524
+ match = File.parse('[_]', :root => :character_class)
575
525
  assert(match)
576
- assert_kind_of(Rule, match.value(''))
526
+ rule = match.value
527
+ assert_instance_of(Terminal, rule)
528
+ assert_equal(/[_]/n, rule.regexp)
577
529
  end
578
530
 
579
- def test_and
580
- match = File.parse('&', :root => :and)
531
+ def test_character_class_a_z
532
+ match = File.parse('[a-z]', :root => :character_class)
581
533
  assert(match)
582
- assert_instance_of(AndPredicate, match.value(''))
534
+ rule = match.value
535
+ assert_instance_of(Terminal, rule)
536
+ assert_equal(/[a-z]/n, rule.regexp)
583
537
  end
584
538
 
585
- def test_and_space
586
- match = File.parse('& ', :root => :and)
539
+ def test_character_class_nested_square_brackets
540
+ match = File.parse('[\[-\]]', :root => :character_class)
587
541
  assert(match)
588
- assert_instance_of(AndPredicate, match.value(''))
542
+ rule = match.value
543
+ assert_instance_of(Terminal, rule)
544
+ assert_equal(/[\[-\]]/n, rule.regexp)
589
545
  end
590
546
 
591
- def test_not
592
- match = File.parse('!', :root => :not)
547
+ def test_character_class_hex_range
548
+ match = File.parse('[\\x26-\\x29]', :root => :character_class)
593
549
  assert(match)
594
- assert_instance_of(NotPredicate, match.value(''))
550
+ rule = match.value
551
+ assert_instance_of(Terminal, rule)
552
+ assert_equal(/[\x26-\x29]/, rule.regexp)
595
553
  end
596
554
 
597
- def test_not_space
598
- match = File.parse('! ', :root => :not)
555
+ def test_dot
556
+ match = File.parse('.', :root => :dot)
599
557
  assert(match)
600
- assert_instance_of(NotPredicate, match.value(''))
558
+ rule = match.value
559
+ assert_instance_of(Terminal, rule)
560
+ assert_equal(DOT, rule.regexp)
601
561
  end
602
562
 
603
563
  def test_label
604
564
  match = File.parse('label:', :root => :label)
605
565
  assert(match)
606
- v = match.value('')
607
- assert_instance_of(Label, v)
608
- assert_equal(:label, v.label)
566
+ assert_equal(:label, match.value)
609
567
  end
610
568
 
611
569
  def test_label_spaced
612
570
  match = File.parse('a_label : ', :root => :label)
613
571
  assert(match)
614
- v = match.value('')
615
- assert_instance_of(Label, v)
616
- assert_equal(:a_label, v.label)
572
+ assert_equal(:a_label, match.value)
617
573
  end
618
574
 
619
575
  def test_tag
@@ -672,9 +628,21 @@ class CitrusFileTest < Test::Unit::TestCase
672
628
  end
673
629
 
674
630
  def test_block_def
631
+ match = File.parse("{def value; 'a' end}", :root => :block)
632
+ assert(match)
633
+ assert(match.value)
634
+ assert_instance_of(Module, match.value)
635
+ method_names = match.value.instance_methods.map {|m| m.to_sym }
636
+ assert_equal([:value], method_names)
637
+ end
638
+
639
+ def test_block_def_multiline
675
640
  match = File.parse("{\n def value\n 'a'\n end\n} ", :root => :block)
676
641
  assert(match)
677
642
  assert(match.value)
643
+ assert_instance_of(Module, match.value)
644
+ method_names = match.value.instance_methods.map {|m| m.to_sym }
645
+ assert_equal([:value], method_names)
678
646
  end
679
647
 
680
648
  def test_block_with_interpolation
@@ -683,6 +651,60 @@ class CitrusFileTest < Test::Unit::TestCase
683
651
  assert(match.value)
684
652
  end
685
653
 
654
+ def test_predicate_and
655
+ match = File.parse('&', :root => :predicate)
656
+ assert(match)
657
+ assert_instance_of(AndPredicate, match.value(''))
658
+ end
659
+
660
+ def test_predicate_not
661
+ match = File.parse('!', :root => :predicate)
662
+ assert(match)
663
+ assert_instance_of(NotPredicate, match.value(''))
664
+ end
665
+
666
+ def test_predicate_but
667
+ match = File.parse('~', :root => :predicate)
668
+ assert(match)
669
+ assert_instance_of(ButPredicate, match.value(''))
670
+ end
671
+
672
+ def test_and
673
+ match = File.parse('&', :root => :and)
674
+ assert(match)
675
+ assert_instance_of(AndPredicate, match.value(''))
676
+ end
677
+
678
+ def test_and_space
679
+ match = File.parse('& ', :root => :and)
680
+ assert(match)
681
+ assert_instance_of(AndPredicate, match.value(''))
682
+ end
683
+
684
+ def test_not
685
+ match = File.parse('!', :root => :not)
686
+ assert(match)
687
+ assert_instance_of(NotPredicate, match.value(''))
688
+ end
689
+
690
+ def test_not_space
691
+ match = File.parse('! ', :root => :not)
692
+ assert(match)
693
+ assert_instance_of(NotPredicate, match.value(''))
694
+ end
695
+
696
+ def test_but
697
+ match = File.parse('~', :root => :but)
698
+ assert(match)
699
+ assert_instance_of(ButPredicate, match.value(''))
700
+ end
701
+
702
+ def test_but_space
703
+ match = File.parse('~ ', :root => :but)
704
+ assert(match)
705
+ assert_instance_of(ButPredicate, match.value(''))
706
+ end
707
+
686
708
  def test_repeat_question
687
709
  match = File.parse('?', :root => :repeat)
688
710
  assert(match)
@@ -722,64 +744,82 @@ class CitrusFileTest < Test::Unit::TestCase
722
744
  def test_question
723
745
  match = File.parse('?', :root => :question)
724
746
  assert(match)
725
- assert_equal(0, match.min)
726
- assert_equal(1, match.max)
747
+ rule = match.value('')
748
+ assert_instance_of(Repeat, rule)
749
+ assert_equal(0, rule.min)
750
+ assert_equal(1, rule.max)
727
751
  end
728
752
 
729
753
  def test_question_space
730
754
  match = File.parse('? ', :root => :question)
731
755
  assert(match)
732
- assert_equal(0, match.min)
733
- assert_equal(1, match.max)
756
+ rule = match.value('')
757
+ assert_instance_of(Repeat, rule)
758
+ assert_equal(0, rule.min)
759
+ assert_equal(1, rule.max)
734
760
  end
735
761
 
736
762
  def test_plus
737
763
  match = File.parse('+', :root => :plus)
738
764
  assert(match)
739
- assert_equal(1, match.min)
740
- assert_equal(Infinity, match.max)
765
+ rule = match.value('')
766
+ assert_instance_of(Repeat, rule)
767
+ assert_equal(1, rule.min)
768
+ assert_equal(Infinity, rule.max)
741
769
  end
742
770
 
743
771
  def test_plus_space
744
772
  match = File.parse('+ ', :root => :plus)
745
773
  assert(match)
746
- assert_equal(1, match.min)
747
- assert_equal(Infinity, match.max)
774
+ rule = match.value('')
775
+ assert_instance_of(Repeat, rule)
776
+ assert_equal(1, rule.min)
777
+ assert_equal(Infinity, rule.max)
748
778
  end
749
779
 
750
780
  def test_star
751
781
  match = File.parse('*', :root => :star)
752
782
  assert(match)
753
- assert_equal(0, match.min)
754
- assert_equal(Infinity, match.max)
783
+ rule = match.value('')
784
+ assert_instance_of(Repeat, rule)
785
+ assert_equal(0, rule.min)
786
+ assert_equal(Infinity, rule.max)
755
787
  end
756
788
 
757
789
  def test_n_star
758
790
  match = File.parse('1*', :root => :star)
759
791
  assert(match)
760
- assert_equal(1, match.min)
761
- assert_equal(Infinity, match.max)
792
+ rule = match.value('')
793
+ assert_instance_of(Repeat, rule)
794
+ assert_equal(1, rule.min)
795
+ assert_equal(Infinity, rule.max)
762
796
  end
763
797
 
764
798
  def test_star_n
765
799
  match = File.parse('*2', :root => :star)
766
800
  assert(match)
767
- assert_equal(0, match.min)
768
- assert_equal(2, match.max)
801
+ rule = match.value('')
802
+ assert_instance_of(Repeat, rule)
803
+ assert_equal(0, rule.min)
804
+ assert_equal(2, rule.max)
769
805
  end
770
806
 
771
807
  def test_n_star_n
772
808
  match = File.parse('1*2', :root => :star)
773
809
  assert(match)
774
- assert_equal(1, match.min)
775
- assert_equal(2, match.max)
810
+ rule = match.value('')
811
+ assert_instance_of(Repeat, rule)
812
+ assert_equal(1, rule.min)
813
+ assert_equal(2, rule.max)
776
814
  end
777
815
 
778
816
  def test_n_star_n_space
779
817
  match = File.parse('1*2 ', :root => :star)
780
818
  assert(match)
781
- assert_equal(1, match.min)
782
- assert_equal(2, match.max)
819
+ rule = match.value('')
820
+ assert_instance_of(Repeat, rule)
821
+ assert_equal(1, rule.min)
822
+ assert_equal(2, rule.max)
783
823
  end
784
824
 
785
825
  def test_module_name