rattler 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -14,7 +14,7 @@ A language syntax is specified in a grammar using the Rattler syntax. Parser
14
14
  classes and modules can be generated statically using the "rtlr" command or
15
15
  dynamically from strings.
16
16
 
17
- {RDoc}[http://rubydoc.info/gems/rattler/0.4.0/frames]
17
+ {RDoc}[http://rubydoc.info/gems/rattler/0.4.1/frames]
18
18
 
19
19
  == FEATURES:
20
20
 
@@ -4,7 +4,8 @@ Feature: Node Actions
4
4
  expression. A node type is an object (typically a class) that responds to
5
5
  the #parsed method. It means to pass the parse results to #parsed and use
6
6
  the value returned as the parse result. The parse results are passed as an
7
- Array and any attributes are included in a Hash.
7
+ Array and any attributes are included in a Hash. The action can optionally
8
+ include a name.
8
9
 
9
10
  In order to create node objects as parse results
10
11
  As a language designer
@@ -28,4 +29,16 @@ Feature: Node Actions
28
29
  integer <- @DIGIT+ <>
29
30
  """
30
31
  When I parse "42"
31
- Then the parse result should be Rattler::Runtime::ParseNode["42"]
32
+ Then the parse result should be Rattler::Runtime::ParseNode["42"]
33
+
34
+ Scenario: Class and node name
35
+ Given a grammar with:
36
+ """
37
+ expr <- @DIGIT+ ~'+' @DIGIT+ <Expr "sum">
38
+ """
39
+ And a class definition:
40
+ """
41
+ class Expr < Rattler::Runtime::ParseNode; end
42
+ """
43
+ When I parse "42+23"
44
+ Then the parse result should be Expr[["42", "23"], {:name => "sum"}]
@@ -14,5 +14,13 @@ module Rattler::BackEnd::ParserGenerator
14
14
  num_groups
15
15
  end
16
16
 
17
+ def parse(scanner, rules, scope={})
18
+ scanner.scan(re) && if num_groups == 1
19
+ scanner[1]
20
+ else
21
+ (1..num_groups).map {|_| scanner[_] }
22
+ end
23
+ end
24
+
17
25
  end
18
26
  end
@@ -218,8 +218,72 @@ module Rattler
218
218
  @scanner.skip(/(?>(?>(?>[[:space:]])+|(?>\#)(?>(?>[^\n])*))*)((?>(?>(?>(?>[[:space:]])+|(?>\#)(?>(?>[^\n])*))*)(?>(?>[[:lower:]])(?>(?>[[:alnum:]_])*))|(?>(?>(?>[[:space:]])+|(?>\#)(?>(?>[^\n])*))*)(?>(?>(?>(?>[[:upper:]])(?>(?>[[:alnum:]_])*)(?>::))*)(?>[[:upper:]])(?>(?>[[:alnum:]_])*)))(?>(?>(?>\.)(?>(?>(?>(?>[[:space:]])+|(?>\#)(?>(?>[^\n])*))*)(?>(?>[[:lower:]])(?>(?>[[:alnum:]_])*))))?))/) &&
219
219
  @scanner[1]
220
220
  end) ? [r] : [])) &&
221
+ (r0_2 = ((r = begin
222
+ begin
223
+ @scanner.skip(/(?>(?>(?>[[:space:]])+|(?>\#)(?>(?>[^\n])*))*)((?>")(?>(?>(?>\\)(?>.)|[^"])*)(?>"))/) &&
224
+ @scanner[1]
225
+ end ||
226
+ begin
227
+ @scanner.skip(/(?>(?>(?>[[:space:]])+|(?>\#)(?>(?>[^\n])*))*)((?>')(?>(?>(?>\\)(?>.)|[^'])*)(?>'))/) &&
228
+ @scanner[1]
229
+ end ||
230
+ begin
231
+ @scanner.skip(/(?>(?>(?>[[:space:]])+|(?>\#)(?>(?>[^\n])*))*)((?>%\()(?>(?>(?>\\)(?>.)|[^)])*)(?>\)))/) &&
232
+ @scanner[1]
233
+ end ||
234
+ begin
235
+ @scanner.skip(/(?>(?>(?>[[:space:]])+|(?>\#)(?>(?>[^\n])*))*)((?>%\{)(?>(?>(?>\\)(?>.)|[^}])*)(?>\}))/) &&
236
+ @scanner[1]
237
+ end ||
238
+ begin
239
+ @scanner.skip(/(?>(?>(?>[[:space:]])+|(?>\#)(?>(?>[^\n])*))*)((?>%\[)(?>(?>(?>\\)(?>.)|[^\]])*)(?>\]))/) &&
240
+ @scanner[1]
241
+ end ||
242
+ begin
243
+ @scanner.skip(/(?>(?>(?>[[:space:]])+|(?>\#)(?>(?>[^\n])*))*)((?>%<)(?>(?>(?>\\)(?>.)|[^>])*)(?>>))/) &&
244
+ @scanner[1]
245
+ end ||
246
+ begin
247
+ p1 = @scanner.pos
248
+ begin
249
+ @scanner.skip(/(?>(?>[[:space:]])+|(?>\#)(?>(?>[^\n])*))*/) &&
250
+ begin
251
+ p2 = @scanner.pos
252
+ begin
253
+ @scanner.skip(/%/) &&
254
+ (r2_0 = @scanner.scan(/[[:punct:]]/)) &&
255
+ begin
256
+ while begin
257
+ @scanner.skip(/(?>\\)(?>.)/) ||
258
+ begin
259
+ p3 = @scanner.pos
260
+ begin
261
+ @scanner.skip(/(?!#{r2_0})/) &&
262
+ @scanner.skip(/./) &&
263
+ true
264
+ end || begin
265
+ @scanner.pos = p3
266
+ false
267
+ end
268
+ end
269
+ end; end
270
+ true
271
+ end &&
272
+ @scanner.skip(/#{r2_0}/) &&
273
+ @scanner.string[p2...(@scanner.pos)]
274
+ end || begin
275
+ @scanner.pos = p2
276
+ false
277
+ end
278
+ end
279
+ end || begin
280
+ @scanner.pos = p1
281
+ false
282
+ end
283
+ end
284
+ end) ? [r] : [])) &&
221
285
  @scanner.skip(/(?>(?>(?>[[:space:]])+|(?>\#)(?>(?>[^\n])*))*)(?>>)/) &&
222
- DispatchAction.parsed(select_captures([r0_0, r0_1]))
286
+ DispatchAction.parsed(select_captures([r0_0, r0_1, r0_2]))
223
287
  end || begin
224
288
  @scanner.pos = p0
225
289
  false
@@ -44,7 +44,7 @@ include Rattler::Parsers
44
44
  expression <- expression ~'/' attributed <Choice>
45
45
  / attributed
46
46
 
47
- attributed <- attributed ~'<' node_action? ~'>' <DispatchAction>
47
+ attributed <- attributed ~'<' node_action? literal? ~'>' <DispatchAction>
48
48
  / attributed ~'{' action ~'}' <DirectAction>
49
49
  / terms
50
50
 
@@ -25,8 +25,13 @@ module Rattler::Parsers
25
25
 
26
26
  # @private
27
27
  def self.parsed(results, *_) #:nodoc:
28
- attributed, optional_attribute = results
29
- self[attributed, optional_attribute.first || @@node_defaults[:target]]
28
+ attributed, optional_attribute, optional_name = results
29
+ a = self[attributed, optional_attribute.first || @@node_defaults[:target]]
30
+ unless optional_name.empty?
31
+ a.with_attrs(:target_attrs => {:name => eval(optional_name.first, TOPLEVEL_BINDING)})
32
+ else
33
+ a
34
+ end
30
35
  end
31
36
 
32
37
  # @private
@@ -59,10 +64,11 @@ module Rattler::Parsers
59
64
  super(children, self.class.parse_attrs_arg(attrs_arg))
60
65
  @@node_defaults.each {|k, v| attrs[k] ||= v } unless attrs[:code]
61
66
  @method_name = attrs[:method]
67
+ @target_attrs = attrs[:target_attrs] || {}
62
68
  end
63
69
 
64
70
  # the name of the method used as the symantic action
65
- attr_reader :method_name
71
+ attr_reader :method_name, :target_attrs
66
72
 
67
73
  # If the wrapped parser matches at the parse position, return the result
68
74
  # of applying the symantic action, otherwise return a false value.
@@ -84,7 +90,7 @@ module Rattler::Parsers
84
90
  end
85
91
 
86
92
  def bindable_code
87
- @bindable_code ||= NodeCode.new(target, method_name)
93
+ @bindable_code ||= NodeCode.new(target, method_name, target_attrs)
88
94
  end
89
95
 
90
96
  def bind(scope, bind_args)
@@ -15,12 +15,13 @@ module Rattler::Parsers
15
15
  self.new(action.target, action.method_name)
16
16
  end
17
17
 
18
- def initialize(target_name, method_name)
18
+ def initialize(target_name, method_name, target_attrs = {})
19
19
  @target_name = target_name
20
20
  @method_name = method_name
21
+ @target_attrs = target_attrs
21
22
  end
22
23
 
23
- attr_reader :target_name, :method_name
24
+ attr_reader :target_name, :method_name, :target_attrs
24
25
 
25
26
  def bind(scope, bind_args)
26
27
  args = [array_expr(bind_args)]
@@ -28,6 +29,7 @@ module Rattler::Parsers
28
29
  labeled = '{' + scope.map {|k, v| ":#{k} => #{v}"}.join(', ') + '}'
29
30
  args << ":labeled => #{labeled}"
30
31
  end
32
+ target_attrs.each {|k, v| args << ":#{k} => #{v.inspect}" }
31
33
  t = target_name == 'self' ? '' : "#{target_name}."
32
34
  "#{t}#{method_name}(#{args.join ', '})"
33
35
  end
@@ -18,7 +18,13 @@ module Rattler::Util::GraphViz
18
18
  # Yield any children of +o+ that should be represented as separate nodes in
19
19
  # the graph.
20
20
  def each_child_of(o)
21
- o.each {|_| yield _ } if array_like? o and not record_like? o
21
+ if array_like? o and not record_like? o
22
+ if o.respond_to? :to_hash
23
+ o.each {|k, v| yield Mapping.new(k, v) }
24
+ else
25
+ o.each {|_| yield _ }
26
+ end
27
+ end
22
28
  end
23
29
 
24
30
  # Return the options for a node representing +o+.
@@ -31,7 +37,7 @@ module Rattler::Util::GraphViz
31
37
  # @return the shape option for a node representing +o+.
32
38
  def node_shape(o)
33
39
  case o
34
- when Hash, Array
40
+ when Array, Hash, Mapping
35
41
  'circle'
36
42
  when String, Numeric, Symbol
37
43
  'plaintext'
@@ -49,6 +55,8 @@ module Rattler::Util::GraphViz
49
55
  record_label(o, o)
50
56
  elsif array_like? o
51
57
  type_label(o)
58
+ elsif o.respond_to? :to_str
59
+ "\"#{o}\""
52
60
  else
53
61
  o.inspect
54
62
  end
@@ -58,6 +66,7 @@ module Rattler::Util::GraphViz
58
66
  case o
59
67
  when Hash then '\\{\\}'
60
68
  when Array then '\\[\\]'
69
+ when Mapping then '-&gt;'
61
70
  else o.respond_to?(:name) ? o.name : o.class.name
62
71
  end
63
72
  end
@@ -73,12 +82,26 @@ module Rattler::Util::GraphViz
73
82
  end
74
83
 
75
84
  def record_label(o, h)
76
- '{' + ([type_label(o)] + hash_content_labels(h)).join('|') + '}'
85
+ fields = h.reject {|k,v| k == :name }
86
+ '{' + ([type_label(o)] + hash_content_labels(fields)).join('|') + '}'
77
87
  end
78
88
 
79
89
  def hash_content_labels(h)
80
90
  h.map {|pair| '{' + pair.map {|_| _.inspect }.join('|') + '}' }
81
91
  end
82
92
 
93
+ # @private
94
+ class Mapping #:nodoc:
95
+ def initialize(key, value)
96
+ @key = key
97
+ @value = value
98
+ end
99
+ attr_reader :key, :value
100
+ def each
101
+ yield key
102
+ yield value
103
+ end
104
+ end
105
+
83
106
  end
84
107
  end
@@ -5,6 +5,13 @@ describe Rattler::BackEnd::Compiler do
5
5
  include CompilerSpecHelper
6
6
 
7
7
  describe '.compile_parser result' do
8
+
9
+ let :compiled_parser do
10
+ described_class.compile_parser compiled_parser_base, grammar
11
+ end
12
+
13
+ let(:compiled_parser_base) { Rattler::Runtime::RecursiveDescentParser }
14
+
8
15
  it_behaves_like 'a compiled parser'
9
16
  end
10
17
 
@@ -0,0 +1,16 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/shared_compiler_examples')
3
+
4
+ describe Rattler::BackEnd::Optimizer do
5
+ include CompilerSpecHelper
6
+
7
+ describe '.optimize result' do
8
+
9
+ let :compiled_parser do
10
+ combinator_parser described_class.optimize(grammar)
11
+ end
12
+
13
+ it_behaves_like 'a compiled parser'
14
+
15
+ end
16
+ end
@@ -0,0 +1,51 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
2
+
3
+ include Rattler::BackEnd::ParserGenerator
4
+
5
+ describe GroupMatch do
6
+ include CombinatorParserSpecHelper
7
+
8
+ let(:single_group) { GroupMatch[Match[/\s*(\w+)/], {:num_groups => 1}] }
9
+ let(:multi_group) { GroupMatch[Match[/\s*(\w+)\s+(\w+)/], {:num_groups => 2}] }
10
+
11
+ describe '#parse' do
12
+
13
+ context 'with a single group' do
14
+
15
+ subject { single_group }
16
+
17
+ context 'when the regexp matches' do
18
+ it 'succeeds returning the matched group' do
19
+ parsing(' abc123 ').should result_in('abc123').at(8)
20
+ end
21
+ end
22
+
23
+ context 'when the regexp does not match' do
24
+ it 'fails' do
25
+ parsing('==').should fail
26
+ end
27
+ end
28
+ end
29
+
30
+ context 'with multiple groups' do
31
+
32
+ subject { multi_group }
33
+
34
+ context 'when the regexp matches' do
35
+ it 'succeeds returning the matched groups in an array' do
36
+ parsing(' abc 123 ').should result_in(['abc', '123']).at(8)
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ describe '#capturing?' do
43
+
44
+ subject { single_group }
45
+
46
+ it 'is true' do
47
+ subject.should be_capturing
48
+ end
49
+ end
50
+
51
+ end
@@ -1,15 +1,9 @@
1
1
  shared_examples_for 'a compiled parser' do
2
2
  include CompilerSpecHelper
3
3
 
4
- subject do
5
- described_class.compile_parser(compiled_parser_base, grammar)
6
- end
7
-
8
- let :reference_parser do
9
- Rattler::Parsers::CombinatorParser.as_class(grammar.rules.first, grammar.rules)
10
- end
4
+ subject { compiled_parser }
11
5
 
12
- let(:compiled_parser_base) { Rattler::Runtime::RecursiveDescentParser }
6
+ let(:reference_parser) { combinator_parser grammar }
13
7
 
14
8
  ########## match ##########
15
9
  context 'with a match rule' do
@@ -167,20 +167,90 @@ describe Rattler::Grammar::GrammarParser do
167
167
  end
168
168
  end
169
169
 
170
- it 'parses dispatch-action-attributed expressions' do
171
- matching(' expr <Expr> ').as(:expression).
172
- should result_in(DispatchAction[Apply[:expr], {:target => 'Expr', :method => 'parsed'}]).
173
- at(12)
170
+ context 'given a dispatch-action-attributed expression' do
171
+
172
+ context 'given an action with a class name' do
173
+ it 'parses as a DispatchAction with the default method' do
174
+ matching(' expr <Expr> ').as(:expression).
175
+ should result_in(DispatchAction[Apply[:expr],
176
+ {:target => 'Expr', :method => 'parsed'}
177
+ ]).at(12)
178
+ end
179
+
180
+ context 'with a literal' do
181
+ it 'uses the literal as the name' do
182
+ matching(' expr <Expr "expression"> ').as(:expression).
183
+ should result_in(DispatchAction[Apply[:expr],
184
+ {:target => 'Expr', :method => 'parsed',
185
+ :target_attrs => {:name => 'expression'} }
186
+ ]).at(25)
187
+ end
188
+ end
189
+ end
190
+
191
+ context 'given an action with a class and method names' do
192
+ it 'parses as a DispatchAction with the default method' do
193
+ matching(' expr <Expr.eval> ').as(:expression).
194
+ should result_in(DispatchAction[Apply[:expr],
195
+ {:target => 'Expr', :method => 'eval'}
196
+ ]).at(17)
197
+ end
198
+
199
+ context 'with a literal' do
200
+ it 'uses the literal as the name' do
201
+ matching(' expr <Expr.eval "expression"> ').as(:expression).
202
+ should result_in(DispatchAction[Apply[:expr],
203
+ { :target => 'Expr', :method => 'eval',
204
+ :target_attrs => {:name => 'expression'} }
205
+ ]).at(30)
206
+ end
207
+ end
208
+ end
209
+
210
+ context 'given an empty action' do
211
+ it 'parses as a DispatchAction with the default target and method' do
212
+ matching(' expr <> ').as(:expression).
213
+ should result_in(DispatchAction[Apply[:expr],
214
+ {:target => 'Rattler::Runtime::ParseNode', :method => 'parsed'}
215
+ ]).at(8)
216
+ end
217
+ end
218
+
219
+ context 'given just a literal' do
220
+ it 'parses as a default node with the literal as the name' do
221
+ matching(' expr <"expression"> ').as(:expression).
222
+ should result_in(DispatchAction[Apply[:expr],
223
+ { :target => 'Rattler::Runtime::ParseNode',
224
+ :method => 'parsed',
225
+ :target_attrs => {:name => 'expression'} }
226
+ ]).at(20)
227
+ end
228
+ end
174
229
  end
175
230
 
176
- it 'parses direct-action-attributed expressions' do
177
- matching(' digits {|_| _.to_i} ').as(:expression).
178
- should result_in(DirectAction[Apply[:digits], '|_| _.to_i']).at(20)
231
+ context 'given direct-action-attributed expression' do
232
+ it 'parses as a DirectAction' do
233
+ matching(' digits {|_| _.to_i} ').as(:expression).
234
+ should result_in(DirectAction[Apply[:digits], '|_| _.to_i']).at(20)
235
+ end
179
236
  end
180
237
 
181
- it 'parses sequence expressions' do
182
- matching(' name "=" value ').as(:expression).
183
- should result_in(Sequence[Apply[:name], Match[%r{=}], Apply[:value]]).at(15)
238
+ context 'given a sequence expression' do
239
+ it 'parses as a Sequence' do
240
+ matching(' name "=" value ').as(:expression).
241
+ should result_in(Sequence[Apply[:name], Match[%r{=}], Apply[:value]]).at(15)
242
+ end
243
+
244
+ context 'with a nested sequence expression' do
245
+ it 'parses as a nested Sequence' do
246
+ matching(' a (b c) d ').as(:expression).
247
+ should result_in(Sequence[
248
+ Apply[:a],
249
+ Sequence[Apply[:b], Apply[:c]],
250
+ Apply[:d]
251
+ ]).at(10)
252
+ end
253
+ end
184
254
  end
185
255
 
186
256
  it 'parses attributed sequence expressions' do
@@ -3,14 +3,15 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
3
3
  describe DispatchAction do
4
4
  include CombinatorParserSpecHelper
5
5
 
6
+ subject { DispatchAction[nested_parser] }
7
+
6
8
  describe '#parse' do
7
9
 
8
10
  context 'with a capturing parser' do
9
- subject do
10
- DispatchAction[
11
- Sequence[Match[/[[:alpha:]]+/], Match[/\=/], Match[/[[:digit:]]+/]]
12
- ]
13
- end
11
+
12
+ let (:nested_parser) { Sequence[
13
+ Match[/[[:alpha:]]+/], Match[/\=/], Match[/[[:digit:]]+/]
14
+ ] }
14
15
 
15
16
  context 'when the parser matches' do
16
17
  it 'applies the action to the result' do
@@ -26,6 +27,18 @@ describe DispatchAction do
26
27
  end
27
28
  end
28
29
 
30
+ context 'with a non-capturing parser' do
31
+
32
+ let (:nested_parser) { Skip[Match[/,/]] }
33
+
34
+ context 'when the parser matches' do
35
+ it 'applies the action to an empty array' do
36
+ parsing(', ').
37
+ should result_in(Rattler::Runtime::ParseNode.parsed([])).at(1)
38
+ end
39
+ end
40
+ end
41
+
29
42
  context 'with a token parser' do
30
43
 
31
44
  subject { DispatchAction[Token[Match[/\w+/]]] }
@@ -2,10 +2,11 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
2
 
3
3
  describe Rattler::Parsers::NodeCode do
4
4
 
5
- subject { described_class.new(target_name, method_name) }
5
+ subject { described_class.new(target_name, method_name, target_attrs) }
6
6
 
7
7
  let(:target_name) { 'Expr' }
8
8
  let(:method_name) { 'parsed' }
9
+ let(:target_attrs) { {} }
9
10
 
10
11
  describe '#bind' do
11
12
 
@@ -44,5 +45,15 @@ describe Rattler::Parsers::NodeCode do
44
45
  should == 'Expr.parsed([a, b], :labeled => {:word => w})'
45
46
  end
46
47
  end
48
+
49
+ context 'with target_attrs' do
50
+
51
+ let(:target_attrs) { {:name => 'expression'} }
52
+
53
+ it '' do
54
+ subject.bind(scope, ['a', 'b']).
55
+ should == 'Expr.parsed([a, b], :name => "expression")'
56
+ end
57
+ end
47
58
  end
48
59
  end
@@ -3,6 +3,46 @@ require 'set'
3
3
 
4
4
  describe Rattler::Util::GraphViz::NodeBuilder do
5
5
 
6
+ describe '#node_label' do
7
+
8
+ context 'given a number' do
9
+ it 'returns a number as a string' do
10
+ subject.node_label(42).should == '42'
11
+ end
12
+ end
13
+
14
+ context 'given a string' do
15
+ it 'returns the string surrounded by escaped quotes' do
16
+ subject.node_label('abc').should == '"abc"'
17
+ end
18
+ end
19
+
20
+ context 'given an unnamed record-like object' do
21
+ it 'returns a record label with the class name' do
22
+ subject.node_label(Rattler::Util::Node[]).should == '{Rattler::Util::Node}'
23
+ end
24
+ end
25
+
26
+ context 'given a named record-like object' do
27
+ it 'returns a record label with a name' do
28
+ subject.node_label(Rattler::Util::Node[{:name => 'IDENT'}]).
29
+ should == '{IDENT}'
30
+ end
31
+ end
32
+
33
+ context 'given an array-like object' do
34
+ it 'returns "[]" escaped' do
35
+ subject.node_label(['let', 'x', '=', '1']).should == '\\[\\]'
36
+ end
37
+ end
38
+
39
+ context 'given a hash with compound values' do
40
+ it 'returns "{}" escaped' do
41
+ subject.node_label({:a => 'a', :b => ['a1', 'a2']}).should == '\\{\\}'
42
+ end
43
+ end
44
+ end
45
+
6
46
  describe '#array_like?' do
7
47
 
8
48
  context 'given an array' do
@@ -11,7 +51,7 @@ describe Rattler::Util::GraphViz::NodeBuilder do
11
51
  end
12
52
  end
13
53
 
14
- context 'given a hash' do
54
+ context 'given a simple hash' do
15
55
  it 'returns true' do
16
56
  subject.array_like?({:a => 'a'}).should be_true
17
57
  end
@@ -62,10 +102,10 @@ describe Rattler::Util::GraphViz::NodeBuilder do
62
102
 
63
103
  let(:object) { {:a => ['a1', 'a2'], :b => 'b'} }
64
104
 
65
- it 'iterates over the pairs' do
105
+ it 'iterates over the pairs yielding Mappings' do
66
106
  children = Set[]
67
107
  subject.each_child_of(object) {|_| children << _ }
68
- children.should == Set[[:a, ['a1', 'a2']], [:b, 'b']]
108
+ children.should have(2).mappings
69
109
  end
70
110
  end
71
111
 
@@ -6,6 +6,10 @@ module CompilerSpecHelper
6
6
  Rattler::Grammar::Grammar.new(Rattler::Parsers.define(&block))
7
7
  end
8
8
 
9
+ def combinator_parser(g)
10
+ Rattler::Parsers::CombinatorParser.as_class(g.rules.first, g.rules)
11
+ end
12
+
9
13
  RSpec::Matchers.define :parse do |source|
10
14
  match do |parser_class|
11
15
  parser = parser_class.new(source)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rattler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,12 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-03-12 00:00:00.000000000 -08:00
12
+ date: 2011-03-15 00:00:00.000000000 -07:00
13
13
  default_executable: rtlr
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
17
- requirement: &74294690 !ruby/object:Gem::Requirement
17
+ requirement: &72971210 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ~>
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: 1.0.0
23
23
  type: :development
24
24
  prerelease: false
25
- version_requirements: *74294690
25
+ version_requirements: *72971210
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: jeweler
28
- requirement: &74294440 !ruby/object:Gem::Requirement
28
+ requirement: &72970960 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ~>
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: 1.5.2
34
34
  type: :development
35
35
  prerelease: false
36
- version_requirements: *74294440
36
+ version_requirements: *72970960
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: rspec
39
- requirement: &74268930 !ruby/object:Gem::Requirement
39
+ requirement: &72970700 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: 2.3.0
45
45
  type: :development
46
46
  prerelease: false
47
- version_requirements: *74268930
47
+ version_requirements: *72970700
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: cucumber
50
- requirement: &74268690 !ruby/object:Gem::Requirement
50
+ requirement: &72970430 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ! '>='
@@ -55,10 +55,10 @@ dependencies:
55
55
  version: 0.8.0
56
56
  type: :development
57
57
  prerelease: false
58
- version_requirements: *74268690
58
+ version_requirements: *72970430
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: aruba
61
- requirement: &74268420 !ruby/object:Gem::Requirement
61
+ requirement: &72970180 !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
64
64
  - - ! '>='
@@ -66,10 +66,10 @@ dependencies:
66
66
  version: 0.3.0
67
67
  type: :development
68
68
  prerelease: false
69
- version_requirements: *74268420
69
+ version_requirements: *72970180
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: yard
72
- requirement: &74268160 !ruby/object:Gem::Requirement
72
+ requirement: &72969930 !ruby/object:Gem::Requirement
73
73
  none: false
74
74
  requirements:
75
75
  - - ! '>='
@@ -77,10 +77,10 @@ dependencies:
77
77
  version: 0.6.0
78
78
  type: :development
79
79
  prerelease: false
80
- version_requirements: *74268160
80
+ version_requirements: *72969930
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: watchr
83
- requirement: &74267920 !ruby/object:Gem::Requirement
83
+ requirement: &72969680 !ruby/object:Gem::Requirement
84
84
  none: false
85
85
  requirements:
86
86
  - - ! '>='
@@ -88,10 +88,10 @@ dependencies:
88
88
  version: 0.5.5
89
89
  type: :development
90
90
  prerelease: false
91
- version_requirements: *74267920
91
+ version_requirements: *72969680
92
92
  - !ruby/object:Gem::Dependency
93
93
  name: ruby-graphviz
94
- requirement: &74267680 !ruby/object:Gem::Requirement
94
+ requirement: &72969430 !ruby/object:Gem::Requirement
95
95
  none: false
96
96
  requirements:
97
97
  - - ! '>='
@@ -99,7 +99,7 @@ dependencies:
99
99
  version: 0.9.6
100
100
  type: :development
101
101
  prerelease: false
102
- version_requirements: *74267680
102
+ version_requirements: *72969430
103
103
  description: Simple language recognition tool for Ruby based on packrat parsing
104
104
  email: jarhart@gmail.com
105
105
  executables:
@@ -274,6 +274,7 @@ files:
274
274
  - spec/rattler/back_end/optimizer/reduce_repeat_match_spec.rb
275
275
  - spec/rattler/back_end/optimizer/simplify_redundant_repeat_spec.rb
276
276
  - spec/rattler/back_end/optimizer/simplify_token_match_spec.rb
277
+ - spec/rattler/back_end/optimizer_spec.rb
277
278
  - spec/rattler/back_end/parser_generator/apply_generator_spec.rb
278
279
  - spec/rattler/back_end/parser_generator/assert_generator_spec.rb
279
280
  - spec/rattler/back_end/parser_generator/back_reference_generator_spec.rb
@@ -283,6 +284,7 @@ files:
283
284
  - spec/rattler/back_end/parser_generator/dispatch_action_generator_spec.rb
284
285
  - spec/rattler/back_end/parser_generator/fail_generator_spec.rb
285
286
  - spec/rattler/back_end/parser_generator/group_match_generator_spec.rb
287
+ - spec/rattler/back_end/parser_generator/group_match_spec.rb
286
288
  - spec/rattler/back_end/parser_generator/label_generator_spec.rb
287
289
  - spec/rattler/back_end/parser_generator/list1_generator_spec.rb
288
290
  - spec/rattler/back_end/parser_generator/list_generator_spec.rb
@@ -356,7 +358,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
356
358
  version: '0'
357
359
  segments:
358
360
  - 0
359
- hash: -463546417
361
+ hash: 156917203
360
362
  required_rubygems_version: !ruby/object:Gem::Requirement
361
363
  none: false
362
364
  requirements:
@@ -416,6 +418,7 @@ test_files:
416
418
  - spec/rattler/back_end/optimizer/reduce_repeat_match_spec.rb
417
419
  - spec/rattler/back_end/optimizer/simplify_redundant_repeat_spec.rb
418
420
  - spec/rattler/back_end/optimizer/simplify_token_match_spec.rb
421
+ - spec/rattler/back_end/optimizer_spec.rb
419
422
  - spec/rattler/back_end/parser_generator/apply_generator_spec.rb
420
423
  - spec/rattler/back_end/parser_generator/assert_generator_spec.rb
421
424
  - spec/rattler/back_end/parser_generator/back_reference_generator_spec.rb
@@ -425,6 +428,7 @@ test_files:
425
428
  - spec/rattler/back_end/parser_generator/dispatch_action_generator_spec.rb
426
429
  - spec/rattler/back_end/parser_generator/fail_generator_spec.rb
427
430
  - spec/rattler/back_end/parser_generator/group_match_generator_spec.rb
431
+ - spec/rattler/back_end/parser_generator/group_match_spec.rb
428
432
  - spec/rattler/back_end/parser_generator/label_generator_spec.rb
429
433
  - spec/rattler/back_end/parser_generator/list1_generator_spec.rb
430
434
  - spec/rattler/back_end/parser_generator/list_generator_spec.rb