Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #4 from teleological/single_label_sequence

Single label sequence
  • Loading branch information...
commit 7ba87fba78740a0f0a8dbbba836a7656639c681f 2 parents 714df97 + f6b1898
@cjheath authored
View
401 lib/treetop/compiler/metagrammar.rb
@@ -1140,36 +1140,22 @@ def _nt_choice
end
module Sequence0
- def space
+ def sequence_body
elements[0]
end
- def labeled_sequence_primary
+ def node_class_declarations
elements[1]
end
end
module Sequence1
- def head
- elements[0]
- end
-
- def tail
- elements[1]
- end
-
- def node_class_declarations
- elements[2]
- end
- end
-
- module Sequence2
def sequence_elements
- [head] + tail
+ [sequence_body.head] + tail
end
def tail
- super.elements.map {|elt| elt.labeled_sequence_primary }
+ sequence_body.tail
end
def inline_modules
@@ -1195,7 +1181,95 @@ def _nt_sequence
end
i0, s0 = index, []
- r1 = _nt_labeled_sequence_primary
+ r1 = _nt_sequence_body
+ s0 << r1
+ if r1
+ r2 = _nt_node_class_declarations
+ s0 << r2
+ end
+ if s0.last
+ r0 = instantiate_node(Sequence,input, i0...index, s0)
+ r0.extend(Sequence0)
+ r0.extend(Sequence1)
+ else
+ @index = i0
+ r0 = nil
+ end
+
+ node_cache[:sequence][start_index] = r0
+
+ r0
+ end
+
+ def _nt_sequence_body
+ start_index = index
+ if node_cache[:sequence_body].has_key?(index)
+ cached = node_cache[:sequence_body][index]
+ if cached
+ cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
+ @index = cached.interval.end
+ end
+ return cached
+ end
+
+ i0 = index
+ r1 = _nt_variable_length_sequence_body
+ if r1
+ r0 = r1
+ else
+ r2 = _nt_labeled_expression_sequence_body
+ if r2
+ r0 = r2
+ else
+ @index = i0
+ r0 = nil
+ end
+ end
+
+ node_cache[:sequence_body][start_index] = r0
+
+ r0
+ end
+
+ module VariableLengthSequenceBody0
+ def space
+ elements[0]
+ end
+
+ def optionally_labeled_sequence_primary
+ elements[1]
+ end
+ end
+
+ module VariableLengthSequenceBody1
+ def head
+ elements[0]
+ end
+
+ def tail
+ elements[1]
+ end
+ end
+
+ module VariableLengthSequenceBody2
+ def tail
+ super.elements.map {|elt| elt.optionally_labeled_sequence_primary }
+ end
+ end
+
+ def _nt_variable_length_sequence_body
+ start_index = index
+ if node_cache[:variable_length_sequence_body].has_key?(index)
+ cached = node_cache[:variable_length_sequence_body][index]
+ if cached
+ cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
+ @index = cached.interval.end
+ end
+ return cached
+ end
+
+ i0, s0 = index, []
+ r1 = _nt_optionally_labeled_sequence_primary
s0 << r1
if r1
s2, i2 = [], index
@@ -1204,12 +1278,12 @@ def _nt_sequence
r4 = _nt_space
s3 << r4
if r4
- r5 = _nt_labeled_sequence_primary
+ r5 = _nt_optionally_labeled_sequence_primary
s3 << r5
end
if s3.last
r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
- r3.extend(Sequence0)
+ r3.extend(VariableLengthSequenceBody0)
else
@index = i3
r3 = nil
@@ -1227,21 +1301,46 @@ def _nt_sequence
r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
end
s0 << r2
- if r2
- r6 = _nt_node_class_declarations
- s0 << r6
- end
end
if s0.last
- r0 = instantiate_node(Sequence,input, i0...index, s0)
- r0.extend(Sequence1)
- r0.extend(Sequence2)
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
+ r0.extend(VariableLengthSequenceBody1)
+ r0.extend(VariableLengthSequenceBody2)
else
@index = i0
r0 = nil
end
- node_cache[:sequence][start_index] = r0
+ node_cache[:variable_length_sequence_body][start_index] = r0
+
+ r0
+ end
+
+ module LabeledExpressionSequenceBody0
+ def head
+ self
+ end
+
+ def tail
+ []
+ end
+ end
+
+ def _nt_labeled_expression_sequence_body
+ start_index = index
+ if node_cache[:labeled_expression_sequence_body].has_key?(index)
+ cached = node_cache[:labeled_expression_sequence_body][index]
+ if cached
+ cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
+ @index = cached.interval.end
+ end
+ return cached
+ end
+
+ r0 = _nt_labeled_sequence_primary
+ r0.extend(LabeledExpressionSequenceBody0)
+
+ node_cache[:labeled_expression_sequence_body][start_index] = r0
r0
end
@@ -1499,8 +1598,38 @@ def _nt_primary
r0
end
+ def _nt_optionally_labeled_sequence_primary
+ start_index = index
+ if node_cache[:optionally_labeled_sequence_primary].has_key?(index)
+ cached = node_cache[:optionally_labeled_sequence_primary][index]
+ if cached
+ cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
+ @index = cached.interval.end
+ end
+ return cached
+ end
+
+ i0 = index
+ r1 = _nt_labeled_sequence_primary
+ if r1
+ r0 = r1
+ else
+ r2 = _nt_unlabeled_sequence_primary
+ if r2
+ r0 = r2
+ else
+ @index = i0
+ r0 = nil
+ end
+ end
+
+ node_cache[:optionally_labeled_sequence_primary][start_index] = r0
+
+ r0
+ end
+
module LabeledSequencePrimary0
- def label
+ def named_label
elements[0]
end
@@ -1519,13 +1648,7 @@ def inline_modules
end
def label_name
- if label.name
- label.name
- elsif sequence_primary.instance_of?(Nonterminal)
- sequence_primary.text_value
- else
- nil
- end
+ named_label.name
end
end
@@ -1541,7 +1664,7 @@ def _nt_labeled_sequence_primary
end
i0, s0 = index, []
- r1 = _nt_label
+ r1 = _nt_named_label
s0 << r1
if r1
r2 = _nt_sequence_primary
@@ -1561,26 +1684,64 @@ def _nt_labeled_sequence_primary
r0
end
- module Label0
- def alpha_char
+ module UnlabeledSequencePrimary0
+ def null_label
elements[0]
end
+ def sequence_primary
+ elements[1]
+ end
end
- module Label1
- end
+ module UnlabeledSequencePrimary1
+ def compile(lexical_address, builder)
+ sequence_primary.compile(lexical_address, builder)
+ end
- module Label2
- def name
- elements[0].text_value
+ def inline_modules
+ sequence_primary.inline_modules
+ end
+
+ def label_name
+ if sequence_primary.instance_of?(Nonterminal)
+ sequence_primary.text_value
+ else
+ nil
+ end
end
end
- module Label3
- def name
- nil
+ def _nt_unlabeled_sequence_primary
+ start_index = index
+ if node_cache[:unlabeled_sequence_primary].has_key?(index)
+ cached = node_cache[:unlabeled_sequence_primary][index]
+ if cached
+ cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
+ @index = cached.interval.end
+ end
+ return cached
+ end
+
+ i0, s0 = index, []
+ r1 = _nt_null_label
+ s0 << r1
+ if r1
+ r2 = _nt_sequence_primary
+ s0 << r2
+ end
+ if s0.last
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
+ r0.extend(UnlabeledSequencePrimary0)
+ r0.extend(UnlabeledSequencePrimary1)
+ else
+ @index = i0
+ r0 = nil
end
+
+ node_cache[:unlabeled_sequence_primary][start_index] = r0
+
+ r0
end
def _nt_label
@@ -1595,69 +1756,127 @@ def _nt_label
end
i0 = index
+ r1 = _nt_named_label
+ if r1
+ r0 = r1
+ else
+ r2 = _nt_null_label
+ if r2
+ r0 = r2
+ else
+ @index = i0
+ r0 = nil
+ end
+ end
+
+ node_cache[:label][start_index] = r0
+
+ r0
+ end
+
+ module NamedLabel0
+ def alpha_char
+ elements[0]
+ end
+
+ end
+
+ module NamedLabel1
+ end
+
+ module NamedLabel2
+ def name
+ elements[0].text_value
+ end
+ end
+
+ def _nt_named_label
+ start_index = index
+ if node_cache[:named_label].has_key?(index)
+ cached = node_cache[:named_label][index]
+ if cached
+ cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
+ @index = cached.interval.end
+ end
+ return cached
+ end
+
+ i0, s0 = index, []
i1, s1 = index, []
- i2, s2 = index, []
- r3 = _nt_alpha_char
- s2 << r3
- if r3
- s4, i4 = [], index
+ r2 = _nt_alpha_char
+ s1 << r2
+ if r2
+ s3, i3 = [], index
loop do
- r5 = _nt_alphanumeric_char
- if r5
- s4 << r5
+ r4 = _nt_alphanumeric_char
+ if r4
+ s3 << r4
else
break
end
end
- r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
- s2 << r4
+ r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
+ s1 << r3
end
- if s2.last
- r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
- r2.extend(Label0)
+ if s1.last
+ r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
+ r1.extend(NamedLabel0)
else
- @index = i2
- r2 = nil
+ @index = i1
+ r1 = nil
end
- s1 << r2
- if r2
+ s0 << r1
+ if r1
if has_terminal?(':', false, index)
- r6 = instantiate_node(SyntaxNode,input, index...(index + 1))
+ r5 = instantiate_node(SyntaxNode,input, index...(index + 1))
@index += 1
else
terminal_parse_failure(':')
- r6 = nil
+ r5 = nil
end
- s1 << r6
+ s0 << r5
end
- if s1.last
- r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
- r1.extend(Label1)
- r1.extend(Label2)
+ if s0.last
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
+ r0.extend(NamedLabel1)
+ r0.extend(NamedLabel2)
else
- @index = i1
- r1 = nil
+ @index = i0
+ r0 = nil
end
- if r1
- r0 = r1
- else
- if has_terminal?('', false, index)
- r7 = instantiate_node(SyntaxNode,input, index...(index + 0))
- r7.extend(Label3)
- @index += 0
- else
- terminal_parse_failure('')
- r7 = nil
- end
- if r7
- r0 = r7
- else
- @index = i0
- r0 = nil
+
+ node_cache[:named_label][start_index] = r0
+
+ r0
+ end
+
+ module NullLabel0
+ def name
+ nil
+ end
+ end
+
+ def _nt_null_label
+ start_index = index
+ if node_cache[:null_label].has_key?(index)
+ cached = node_cache[:null_label][index]
+ if cached
+ cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
+ @index = cached.interval.end
end
+ return cached
end
- node_cache[:label][start_index] = r0
+ if has_terminal?('', false, index)
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 0))
+ r0.extend(NullLabel0)
+ @index += 0
+ else
+ terminal_parse_failure('')
+ r0 = nil
+ end
+
+ node_cache[:null_label][start_index] = r0
r0
end
View
64 lib/treetop/compiler/metagrammar.treetop
@@ -91,13 +91,13 @@ module Treetop
end
rule sequence
- head:labeled_sequence_primary tail:(space labeled_sequence_primary)+ node_class_declarations <Sequence> {
+ sequence_body node_class_declarations <Sequence> {
def sequence_elements
- [head] + tail
+ [sequence_body.head] + tail
end
def tail
- super.elements.map {|elt| elt.labeled_sequence_primary }
+ sequence_body.tail
end
def inline_modules
@@ -112,6 +112,30 @@ module Treetop
}
end
+ rule sequence_body
+ variable_length_sequence_body / labeled_expression_sequence_body
+ end
+
+ rule variable_length_sequence_body
+ head:optionally_labeled_sequence_primary tail:(space optionally_labeled_sequence_primary)+ {
+ def tail
+ super.elements.map {|elt| elt.optionally_labeled_sequence_primary }
+ end
+ }
+ end
+
+ rule labeled_expression_sequence_body
+ labeled_sequence_primary {
+ def head
+ self
+ end
+
+ def tail
+ []
+ end
+ }
+ end
+
rule alternative
sequence / primary
end
@@ -188,8 +212,12 @@ module Treetop
}
end
+ rule optionally_labeled_sequence_primary
+ labeled_sequence_primary / unlabeled_sequence_primary
+ end
+
rule labeled_sequence_primary
- label sequence_primary {
+ named_label sequence_primary {
def compile(lexical_address, builder)
sequence_primary.compile(lexical_address, builder)
end
@@ -199,9 +227,23 @@ module Treetop
end
def label_name
- if label.name
- label.name
- elsif sequence_primary.instance_of?(Nonterminal)
+ named_label.name
+ end
+ }
+ end
+
+ rule unlabeled_sequence_primary
+ null_label sequence_primary {
+ def compile(lexical_address, builder)
+ sequence_primary.compile(lexical_address, builder)
+ end
+
+ def inline_modules
+ sequence_primary.inline_modules
+ end
+
+ def label_name
+ if sequence_primary.instance_of?(Nonterminal)
sequence_primary.text_value
else
nil
@@ -211,12 +253,18 @@ module Treetop
end
rule label
+ named_label / null_label
+ end
+
+ rule named_label
(alpha_char alphanumeric_char*) ':' {
def name
elements[0].text_value
end
}
- /
+ end
+
+ rule null_label
'' {
def name
nil
View
14 spec/compiler/sequence_spec.rb
@@ -60,6 +60,20 @@ def mod_method; end
end
end
+ describe "a labeled single element sequence followed by a node module declaration and a block" do
+ testing_expression 'foo:"foo"+ <SequenceSpec::ModFoo> { def a_method; end }'
+ it "upon successfully matching input, instantiates a syntax node and extends it with the declared module, element accessor methods, and the method from the inline module" do
+ parse('foofoofoo') do |result|
+ result.should_not be_nil
+ result.should respond_to(:mod_method)
+ result.should be_an_instance_of(Treetop::Runtime::SyntaxNode)
+ result.should be_a_kind_of(ModFoo)
+ result.should respond_to(:a_method)
+ result.foo.text_value.should == 'foofoofoo'
+ end
+ end
+ end
+
describe "a sequence of non-terminals" do
testing_grammar %{
grammar TestGrammar
Please sign in to comment.
Something went wrong with that request. Please try again.