citrus 2.3.1 → 2.3.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.
@@ -8,23 +8,19 @@ require 'strscan'
8
8
  module Citrus
9
9
  autoload :File, 'citrus/file'
10
10
 
11
- VERSION = [2, 3, 1]
11
+ # The current version of Citrus as [major, minor, patch].
12
+ VERSION = [2, 3, 2]
12
13
 
13
- # Returns the current version of Citrus as a string.
14
- def self.version
15
- VERSION.join('.')
16
- end
17
-
18
- # A pattern to match any character, including \\n.
14
+ # A pattern to match any character, including newline.
19
15
  DOT = /./m
20
16
 
21
17
  Infinity = 1.0 / 0
22
18
 
23
19
  CLOSE = -1
24
20
 
25
- # Parses the given Citrus +code+ using +options+.
26
- def self.parse(code, options={})
27
- File.parse(code, options)
21
+ # Returns the current version of Citrus as a string.
22
+ def self.version
23
+ VERSION.join('.')
28
24
  end
29
25
 
30
26
  # Evaluates the given Citrus parsing expression grammar +code+ in the global
@@ -37,25 +33,31 @@ module Citrus
37
33
  # end
38
34
  # end
39
35
  # CITRUS
36
+ # # => [MyGrammar]
40
37
  #
41
- def self.eval(code)
42
- parse(code).value
38
+ def self.eval(code, options={})
39
+ File.parse(code, options).value
43
40
  end
44
41
 
45
42
  # Evaluates the given expression and creates a new Rule object from it.
46
43
  #
47
44
  # Citrus.rule('"a" | "b"')
45
+ # # => #<Citrus::Rule: ... >
48
46
  #
49
- def self.rule(expr)
50
- parse(expr, :root => :rule_body).value
47
+ def self.rule(expr, options={})
48
+ File.parse(expr, options.merge(:root => :rule_body)).value
51
49
  end
52
50
 
53
51
  # Loads the grammar from the given +file+ into the global scope using #eval.
54
- def self.load(file)
52
+ #
53
+ # Citrus.load('mygrammar')
54
+ # # => [MyGrammar]
55
+ #
56
+ def self.load(file, options={})
55
57
  file << '.citrus' unless ::File.file?(file)
56
- raise "Cannot find file #{file}" unless ::File.file?(file)
57
- raise "Cannot read file #{file}" unless ::File.readable?(file)
58
- eval(::File.read(file))
58
+ raise ArgumentError, "Cannot find file #{file}" unless ::File.file?(file)
59
+ raise ArgumentError, "Cannot read file #{file}" unless ::File.readable?(file)
60
+ eval(::File.read(file), options)
59
61
  end
60
62
 
61
63
  # A standard error class that all Citrus errors extend.
@@ -157,14 +159,19 @@ module Citrus
157
159
  lines[line_index(pos)]
158
160
  end
159
161
 
162
+ # Returns +true+ when using memoization to cache match results.
163
+ def memoized?
164
+ false
165
+ end
166
+
160
167
  # Returns an array of events for the given +rule+ at the current pointer
161
168
  # position. Objects in this array may be one of three types: a Rule,
162
169
  # Citrus::CLOSE, or a length (integer).
163
170
  def exec(rule, events=[])
164
- index = events.size
165
171
  position = pos
172
+ index = events.size
166
173
 
167
- if rule.exec(self, events).size > index
174
+ if apply_rule(rule, position, events).size > index
168
175
  position += events[-1]
169
176
  @max_offset = position if position > @max_offset
170
177
  end
@@ -177,25 +184,27 @@ module Citrus
177
184
  # Returns the length of a match for the given +rule+ at the current pointer
178
185
  # position, +nil+ if none can be made.
179
186
  def test(rule)
180
- start = pos
181
- events = rule.exec(self)
182
- self.pos = start
187
+ position = pos
188
+ events = apply_rule(rule, position, [])
189
+ self.pos = position
183
190
  events[-1]
184
191
  end
185
192
 
186
- # Returns +true+ when using memoization to cache match results.
187
- def memoized?
188
- false
193
+ private
194
+
195
+ # Appends all events for +rule+ at the given +position+ to +events+.
196
+ def apply_rule(rule, position, events)
197
+ rule.exec(self, events)
189
198
  end
190
199
  end
191
200
 
192
- # A MemoizingInput is an Input that caches segments of the event stream for
201
+ # A MemoizedInput is an Input that caches segments of the event stream for
193
202
  # particular rules in a parse. This technique (also known as "Packrat"
194
203
  # parsing) guarantees parsers will operate in linear time but costs
195
204
  # significantly more in terms of time and memory required to perform a parse.
196
205
  # For more information, please read the paper on Packrat parsing at
197
206
  # http://pdos.csail.mit.edu/~baford/packrat/icfp02/.
198
- class MemoizingInput < Input
207
+ class MemoizedInput < Input
199
208
  def initialize(string)
200
209
  super(string)
201
210
  @cache = {}
@@ -214,31 +223,30 @@ module Citrus
214
223
  super
215
224
  end
216
225
 
217
- def exec(rule, events=[]) # :nodoc:
218
- position = pos
226
+ # Returns +true+ when using memoization to cache match results.
227
+ def memoized?
228
+ true
229
+ end
230
+
231
+ private
232
+
233
+ def apply_rule(rule, position, events) # :nodoc:
219
234
  memo = @cache[rule] ||= {}
220
235
 
221
236
  if memo[position]
222
237
  @cache_hits += 1
238
+ events.concat(memo[position])
223
239
  else
224
- memo[position] = rule.exec(self)
225
- end
240
+ index = events.size
241
+ rule.exec(self, events)
226
242
 
227
- if memo[position].size > 0
228
- events.concat(memo[position])
229
- position += events[-1]
230
- @max_offset = position if position > @max_offset
243
+ # Memoize the result so we can use it next time this same rule is
244
+ # executed at this position.
245
+ memo[position] = events.slice(index, events.size)
231
246
  end
232
247
 
233
- self.pos = position
234
-
235
248
  events
236
249
  end
237
-
238
- # Returns +true+ when using memoization to cache match results.
239
- def memoized?
240
- true
241
- end
242
250
  end
243
251
 
244
252
  # Inclusion of this module into another extends the receiver with the grammar
@@ -281,8 +289,9 @@ module Citrus
281
289
  # option. Otherwise, all options are the same as in Rule#parse.
282
290
  def parse(string, options={})
283
291
  rule_name = options.delete(:root) || root
292
+ raise Error, "No root rule specified" unless rule_name
284
293
  rule = rule(rule_name)
285
- raise 'No rule named "%s"' % rule_name unless rule
294
+ raise Error, "No rule named \"#{rule_name}\"" unless rule
286
295
  rule.parse(string, options)
287
296
  end
288
297
 
@@ -511,7 +520,7 @@ module Citrus
511
520
  mod = Module.new { define_method(:value, &mod) }
512
521
  end
513
522
 
514
- raise ArgumentError unless Module === mod
523
+ raise ArgumentError, "Extension must be a Module" unless Module === mod
515
524
 
516
525
  @extension = mod
517
526
  end
@@ -519,22 +528,29 @@ module Citrus
519
528
  # The module this rule uses to extend new matches.
520
529
  attr_reader :extension
521
530
 
531
+ # The default set of options to use when calling #parse or #test.
532
+ def default_options # :nodoc:
533
+ { :consume => true,
534
+ :memoize => false,
535
+ :offset => 0
536
+ }
537
+ end
538
+
522
539
  # Attempts to parse the given +string+ and return a Match if any can be
523
- # made. The +options+ may contain any of the following keys:
540
+ # made. +options+ may contain any of the following keys:
524
541
  #
525
- # offset:: The offset in +string+ at which to start the parse. Defaults
526
- # to 0.
542
+ # consume:: If this is +true+ a ParseError will be raised unless the
543
+ # entire input string is consumed. Defaults to +true+.
527
544
  # memoize:: If this is +true+ the matches generated during a parse are
528
- # memoized. See Input#memoize! for more information. Defaults to
545
+ # memoized. See MemoizedInput for more information. Defaults to
529
546
  # +false+.
530
- # consume:: If this is +true+ a ParseError will be raised during a parse
531
- # unless the entire input string is consumed. Defaults to
532
- # +true+.
547
+ # offset:: The offset in +string+ at which to start parsing. Defaults
548
+ # to 0.
533
549
  def parse(string, options={})
534
- opts = default_parse_options.merge(options)
550
+ opts = default_options.merge(options)
535
551
 
536
552
  input = if opts[:memoize]
537
- MemoizingInput.new(string)
553
+ MemoizedInput.new(string)
538
554
  else
539
555
  Input.new(string)
540
556
  end
@@ -551,18 +567,13 @@ module Citrus
551
567
  Match.new(string.slice(opts[:offset], length), events)
552
568
  end
553
569
 
554
- # The default set of options to use when parsing.
555
- def default_parse_options # :nodoc:
556
- { :offset => 0,
557
- :memoize => false,
558
- :consume => true
559
- }
560
- end
561
-
562
570
  # Tests whether or not this rule matches on the given +string+. Returns the
563
- # length of the match if any can be made, +nil+ otherwise.
564
- def test(string)
565
- Input.new(string).test(self)
571
+ # length of the match if any can be made, +nil+ otherwise. Accepts the same
572
+ # +options+ as #parse.
573
+ def test(string, options={})
574
+ parse(string, options).length
575
+ rescue ParseError
576
+ nil
566
577
  end
567
578
 
568
579
  # Returns +true+ if this rule is a Terminal.
@@ -1027,7 +1038,7 @@ module Citrus
1027
1038
  events << CLOSE
1028
1039
  events << length
1029
1040
  else
1030
- events.slice!(start, events.size)
1041
+ events.slice!(start, index)
1031
1042
  end
1032
1043
 
1033
1044
  events
@@ -1088,7 +1099,7 @@ module Citrus
1088
1099
  events << CLOSE
1089
1100
  events << length
1090
1101
  else
1091
- events.slice!(start, events.size)
1102
+ events.slice!(start, index)
1092
1103
  end
1093
1104
 
1094
1105
  events
@@ -1380,6 +1391,6 @@ class Object
1380
1391
  namespace = respond_to?(:const_set) ? self : Object
1381
1392
  namespace.const_set(name, Citrus::Grammar.new(&block))
1382
1393
  rescue NameError
1383
- raise ArgumentError, 'Invalid grammar name: %s' % name
1394
+ raise ArgumentError, "Invalid grammar name: #{name}"
1384
1395
  end
1385
1396
  end
@@ -2,8 +2,7 @@ require File.expand_path('../helper', __FILE__)
2
2
 
3
3
  class InputTest < Test::Unit::TestCase
4
4
  def test_memoized?
5
- assert !Input.new('').memoized?
6
- assert MemoizingInput.new('').memoized?
5
+ assert_equal(false, Input.new('').memoized?)
7
6
  end
8
7
 
9
8
  def test_offsets_new
@@ -23,7 +22,7 @@ class InputTest < Test::Unit::TestCase
23
22
  assert_equal("def\n", input.line)
24
23
  end
25
24
 
26
- def test_events
25
+ def test_exec
27
26
  a = Rule.for('a')
28
27
  b = Rule.for('b')
29
28
  c = Rule.for('c')
@@ -56,7 +55,7 @@ class InputTest < Test::Unit::TestCase
56
55
  assert_equal(expected_events, events)
57
56
  end
58
57
 
59
- def test_events2
58
+ def test_exec2
60
59
  a = Rule.for('a')
61
60
  b = Rule.for('b')
62
61
  c = Choice.new([ a, b ])
@@ -100,89 +99,4 @@ class InputTest < Test::Unit::TestCase
100
99
 
101
100
  assert_equal(expected_events, events)
102
101
  end
103
-
104
- grammar :LetterA do
105
- rule :top do
106
- any(:three_as, :two_as, :one_a)
107
- end
108
-
109
- rule :three_as do
110
- rep(:one_a, 3, 3)
111
- end
112
-
113
- rule :two_as do
114
- rep(:one_a, 2, 2)
115
- end
116
-
117
- rule :one_a do
118
- "a"
119
- end
120
- end
121
-
122
- def test_cache_hits1
123
- input = MemoizingInput.new('a')
124
- input.exec(LetterA.rule(:top))
125
- assert_equal(3, input.cache_hits)
126
- end
127
-
128
- def test_cache_hits2
129
- input = MemoizingInput.new('aa')
130
- input.exec(LetterA.rule(:top))
131
- assert_equal(2, input.cache_hits)
132
- end
133
-
134
- def test_cache_hits3
135
- input = MemoizingInput.new('aaa')
136
- input.exec(LetterA.rule(:top))
137
- assert_equal(0, input.cache_hits)
138
- end
139
-
140
- grammar :Addition do
141
- rule :additive do
142
- all(:number, :plus, label(any(:additive, :number), 'term')) {
143
- number.value + term.value
144
- }
145
- end
146
-
147
- rule :number do
148
- all(/[0-9]+/, :space) {
149
- strip.to_i
150
- }
151
- end
152
-
153
- rule :plus do
154
- all('+', :space)
155
- end
156
-
157
- rule :space do
158
- /[ \t]*/
159
- end
160
- end
161
-
162
- def test_match
163
- match = Addition.parse('+', :root => :plus)
164
- assert(match)
165
- assert(match.matches)
166
- assert_equal(2, match.matches.length)
167
-
168
- match = Addition.parse('+ ', :root => :plus)
169
- assert(match)
170
- assert(match.matches)
171
- assert_equal(2, match.matches.length)
172
-
173
- match = Addition.parse('99', :root => :number)
174
- assert(match)
175
- assert(match.matches)
176
- assert_equal(2, match.matches.length)
177
-
178
- match = Addition.parse('99 ', :root => :number)
179
- assert(match)
180
- assert(match.matches)
181
- assert_equal(2, match.matches.length)
182
-
183
- match = Addition.parse('1+2')
184
- assert(match)
185
- assert(match.matches)
186
- assert_equal(3, match.matches.length)
187
- end
188
102
  end
@@ -67,4 +67,53 @@ class MatchTest < Test::Unit::TestCase
67
67
  assert_equal(3, m.matches.length)
68
68
  end
69
69
  end
70
+
71
+ grammar :Addition do
72
+ rule :additive do
73
+ all(:number, :plus, label(any(:additive, :number), 'term')) {
74
+ number.value + term.value
75
+ }
76
+ end
77
+
78
+ rule :number do
79
+ all(/[0-9]+/, :space) {
80
+ strip.to_i
81
+ }
82
+ end
83
+
84
+ rule :plus do
85
+ all('+', :space)
86
+ end
87
+
88
+ rule :space do
89
+ /[ \t]*/
90
+ end
91
+ end
92
+
93
+ def test_matches2
94
+ match = Addition.parse('+', :root => :plus)
95
+ assert(match)
96
+ assert(match.matches)
97
+ assert_equal(2, match.matches.length)
98
+
99
+ match = Addition.parse('+ ', :root => :plus)
100
+ assert(match)
101
+ assert(match.matches)
102
+ assert_equal(2, match.matches.length)
103
+
104
+ match = Addition.parse('99', :root => :number)
105
+ assert(match)
106
+ assert(match.matches)
107
+ assert_equal(2, match.matches.length)
108
+
109
+ match = Addition.parse('99 ', :root => :number)
110
+ assert(match)
111
+ assert(match.matches)
112
+ assert_equal(2, match.matches.length)
113
+
114
+ match = Addition.parse('1+2')
115
+ assert(match)
116
+ assert(match.matches)
117
+ assert_equal(3, match.matches.length)
118
+ end
70
119
  end
@@ -0,0 +1,43 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+
3
+ class MemoizedInputTest < Test::Unit::TestCase
4
+ def test_memoized?
5
+ assert MemoizedInput.new('').memoized?
6
+ end
7
+
8
+ grammar :LetterA do
9
+ rule :top do
10
+ any(:three_as, :two_as, :one_a)
11
+ end
12
+
13
+ rule :three_as do
14
+ rep(:one_a, 3, 3)
15
+ end
16
+
17
+ rule :two_as do
18
+ rep(:one_a, 2, 2)
19
+ end
20
+
21
+ rule :one_a do
22
+ "a"
23
+ end
24
+ end
25
+
26
+ def test_cache_hits1
27
+ input = MemoizedInput.new('a')
28
+ input.exec(LetterA.rule(:top))
29
+ assert_equal(3, input.cache_hits)
30
+ end
31
+
32
+ def test_cache_hits2
33
+ input = MemoizedInput.new('aa')
34
+ input.exec(LetterA.rule(:top))
35
+ assert_equal(2, input.cache_hits)
36
+ end
37
+
38
+ def test_cache_hits3
39
+ input = MemoizedInput.new('aaa')
40
+ input.exec(LetterA.rule(:top))
41
+ assert_equal(0, input.cache_hits)
42
+ end
43
+ end
metadata CHANGED
@@ -3,33 +3,32 @@ name: citrus
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
- - 2
7
- - 3
8
- - 1
9
- version: 2.3.1
6
+ - 2
7
+ - 3
8
+ - 2
9
+ version: 2.3.2
10
10
  platform: ruby
11
11
  authors:
12
- - Michael Jackson
12
+ - Michael Jackson
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-12-31 00:00:00 -08:00
17
+ date: 2011-01-02 00:00:00 -08:00
18
18
  default_executable:
19
19
  dependencies:
20
- - !ruby/object:Gem::Dependency
21
- name: rake
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 0
30
- version: "0"
31
- type: :development
32
- version_requirements: *id001
20
+ - !ruby/object:Gem::Dependency
21
+ name: rake
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :development
31
+ version_requirements: *id001
33
32
  description: Parsing Expressions for Ruby
34
33
  email: mjijackson@gmail.com
35
34
  executables: []
@@ -37,112 +36,112 @@ executables: []
37
36
  extensions: []
38
37
 
39
38
  extra_rdoc_files:
40
- - README
39
+ - README
41
40
  files:
42
- - benchmark/seqpar.citrus
43
- - benchmark/seqpar.gnuplot
44
- - benchmark/seqpar.rb
45
- - doc/background.markdown
46
- - doc/example.markdown
47
- - doc/extras.markdown
48
- - doc/index.markdown
49
- - doc/license.markdown
50
- - doc/links.markdown
51
- - doc/syntax.markdown
52
- - doc/testing.markdown
53
- - examples/calc.citrus
54
- - examples/calc.rb
55
- - examples/ip.citrus
56
- - examples/ip.rb
57
- - lib/citrus/file.rb
58
- - lib/citrus.rb
59
- - test/_files/alias.citrus
60
- - test/_files/grammar1.citrus
61
- - test/_files/grammar2.citrus
62
- - test/_files/rule1.citrus
63
- - test/_files/rule2.citrus
64
- - test/_files/rule3.citrus
65
- - test/_files/super.citrus
66
- - test/_files/super2.citrus
67
- - test/alias_test.rb
68
- - test/and_predicate_test.rb
69
- - test/but_predicate_test.rb
70
- - test/calc_file_test.rb
71
- - test/calc_test.rb
72
- - test/choice_test.rb
73
- - test/extension_test.rb
74
- - test/file_test.rb
75
- - test/grammar_test.rb
76
- - test/helper.rb
77
- - test/input_test.rb
78
- - test/label_test.rb
79
- - test/match_test.rb
80
- - test/multibyte_test.rb
81
- - test/not_predicate_test.rb
82
- - test/parse_error_test.rb
83
- - test/repeat_test.rb
84
- - test/sequence_test.rb
85
- - test/string_terminal_test.rb
86
- - test/super_test.rb
87
- - test/terminal_test.rb
88
- - citrus.gemspec
89
- - Rakefile
90
- - README
41
+ - benchmark/seqpar.citrus
42
+ - benchmark/seqpar.gnuplot
43
+ - benchmark/seqpar.rb
44
+ - doc/background.markdown
45
+ - doc/example.markdown
46
+ - doc/extras.markdown
47
+ - doc/index.markdown
48
+ - doc/license.markdown
49
+ - doc/links.markdown
50
+ - doc/syntax.markdown
51
+ - doc/testing.markdown
52
+ - examples/calc.citrus
53
+ - examples/calc.rb
54
+ - examples/ip.citrus
55
+ - examples/ip.rb
56
+ - lib/citrus.rb
57
+ - lib/citrus/file.rb
58
+ - test/alias_test.rb
59
+ - test/and_predicate_test.rb
60
+ - test/but_predicate_test.rb
61
+ - test/calc_file_test.rb
62
+ - test/calc_test.rb
63
+ - test/choice_test.rb
64
+ - test/extension_test.rb
65
+ - test/file_test.rb
66
+ - test/grammar_test.rb
67
+ - test/helper.rb
68
+ - test/input_test.rb
69
+ - test/label_test.rb
70
+ - test/match_test.rb
71
+ - test/memoized_input_test.rb
72
+ - test/multibyte_test.rb
73
+ - test/not_predicate_test.rb
74
+ - test/parse_error_test.rb
75
+ - test/repeat_test.rb
76
+ - test/sequence_test.rb
77
+ - test/string_terminal_test.rb
78
+ - test/super_test.rb
79
+ - test/terminal_test.rb
80
+ - test/_files/alias.citrus
81
+ - test/_files/grammar1.citrus
82
+ - test/_files/grammar2.citrus
83
+ - test/_files/rule1.citrus
84
+ - test/_files/rule2.citrus
85
+ - test/_files/rule3.citrus
86
+ - test/_files/super.citrus
87
+ - test/_files/super2.citrus
88
+ - citrus.gemspec
89
+ - Rakefile
90
+ - README
91
91
  has_rdoc: true
92
92
  homepage: http://mjijackson.com/citrus
93
93
  licenses: []
94
94
 
95
95
  post_install_message:
96
96
  rdoc_options:
97
- - --line-numbers
98
- - --inline-source
99
- - --title
100
- - Citrus
101
- - --main
102
- - Citrus
97
+ - --line-numbers
98
+ - --inline-source
99
+ - --title
100
+ - Citrus
101
+ - --main
102
+ - Citrus
103
103
  require_paths:
104
- - lib
104
+ - lib
105
105
  required_ruby_version: !ruby/object:Gem::Requirement
106
- none: false
107
106
  requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- segments:
111
- - 0
112
- version: "0"
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ segments:
110
+ - 0
111
+ version: "0"
113
112
  required_rubygems_version: !ruby/object:Gem::Requirement
114
- none: false
115
113
  requirements:
116
- - - ">="
117
- - !ruby/object:Gem::Version
118
- segments:
119
- - 0
120
- version: "0"
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ segments:
117
+ - 0
118
+ version: "0"
121
119
  requirements: []
122
120
 
123
121
  rubyforge_project:
124
- rubygems_version: 1.3.7
122
+ rubygems_version: 1.3.6
125
123
  signing_key:
126
124
  specification_version: 3
127
125
  summary: Parsing Expressions for Ruby
128
126
  test_files:
129
- - test/alias_test.rb
130
- - test/and_predicate_test.rb
131
- - test/but_predicate_test.rb
132
- - test/calc_file_test.rb
133
- - test/calc_test.rb
134
- - test/choice_test.rb
135
- - test/extension_test.rb
136
- - test/file_test.rb
137
- - test/grammar_test.rb
138
- - test/input_test.rb
139
- - test/label_test.rb
140
- - test/match_test.rb
141
- - test/multibyte_test.rb
142
- - test/not_predicate_test.rb
143
- - test/parse_error_test.rb
144
- - test/repeat_test.rb
145
- - test/sequence_test.rb
146
- - test/string_terminal_test.rb
147
- - test/super_test.rb
148
- - test/terminal_test.rb
127
+ - test/alias_test.rb
128
+ - test/and_predicate_test.rb
129
+ - test/but_predicate_test.rb
130
+ - test/calc_file_test.rb
131
+ - test/calc_test.rb
132
+ - test/choice_test.rb
133
+ - test/extension_test.rb
134
+ - test/file_test.rb
135
+ - test/grammar_test.rb
136
+ - test/input_test.rb
137
+ - test/label_test.rb
138
+ - test/match_test.rb
139
+ - test/memoized_input_test.rb
140
+ - test/multibyte_test.rb
141
+ - test/not_predicate_test.rb
142
+ - test/parse_error_test.rb
143
+ - test/repeat_test.rb
144
+ - test/sequence_test.rb
145
+ - test/string_terminal_test.rb
146
+ - test/super_test.rb
147
+ - test/terminal_test.rb