File: sequence_spec.rb

package info (click to toggle)
ruby-treetop 1.6.14-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 956 kB
  • sloc: ruby: 8,918; makefile: 5
file content (129 lines) | stat: -rw-r--r-- 4,748 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
require 'spec_helper'

module SequenceSpec
  class Foo < Treetop::Runtime::SyntaxNode
  end

  describe "a sequence of labeled terminal symbols followed by a node class declaration and a block" do
    testing_expression 'foo:"foo" bar:"bar" baz:"baz" <SequenceSpec::Foo> { def a_method; end }'

    it "upon successfully matching input, instantiates an instance of the declared node class with element accessor methods and the method from the inline module" do
      parse('foobarbaz') do |result|
        result.should_not be_nil
        result.should be_an_instance_of(Foo)
        result.should respond_to(:a_method)
        result.foo.text_value.should == 'foo'
        result.bar.text_value.should == 'bar'
        result.baz.text_value.should == 'baz'
      end
    end

    it "successfully matches at a non-zero index" do
      parse('---foobarbaz', :index => 3) do |result|
        result.should_not be_nil
        result.should be_nonterminal
        (result.elements.map {|elt| elt.text_value}).join.should == 'foobarbaz'
      end
    end

    it "fails to match non-matching input, recording the parse failure of first non-matching terminal" do
      parse('---foobazbaz', :index => 3) do |result|
        result.should be_nil
        parser.index.should == 3
        terminal_failures = parser.terminal_failures
        terminal_failures.size.should == 1
        failure = terminal_failures.first
        failure.index.should == 6
        failure.expected_string.should == '"bar"'
      end
    end
  end

  module ModFoo
  def mod_method; end
  end

  describe "a sequence of labeled terminal symbols followed by a node module declaration and a block" do
    testing_expression 'foo:"foo" bar:"bar" baz:"baz" <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('foobarbaz') 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 == 'foo'
        result.bar.text_value.should == 'bar'
        result.baz.text_value.should == 'baz'
      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
        rule sequence
          foo bar baz {
            def baz
              'override' + super.text_value
            end
          }
        end

        rule foo 'foo' end
        rule bar 'bar' end
        rule baz 'baz' end
      end
    }

    it "defines accessors for non-terminals automatically that can be overridden in the inline block" do
      parse('foobarbaz') do |result|
        result.foo.text_value.should == 'foo'
        result.bar.text_value.should == 'bar'
        result.baz.should == 'overridebaz'
      end
    end
  end

  describe "Compiling a sequence containing various white-space errors" do
    it "should succeed on a valid sequence" do
      compiling_expression('foo:"foo" "bar" <SequenceSpec::Foo> { def a_method; end }').should_not raise_error
    end

    it "rejects space after a label" do
      compiling_expression('foo :"foo" "bar"').should raise_error(RuntimeError)
    end

    it "rejects space after label's colon" do
      compiling_expression('foo: "foo" "bar"').should raise_error(RuntimeError)
    end

    it "rejects missing space after a primary" do
      compiling_expression('foo:"foo""bar"').should raise_error(RuntimeError)
    end

    it "rejects missing space before node class declaration" do
      compiling_expression('foo:"foo" "bar"<SequenceSpec::Foo>').should raise_error(RuntimeError)
    end
    
    it "rejects missing space before inline module" do
      compiling_expression('foo:"foo" "bar" <SequenceSpec::Foo>{def a_method; end}').should raise_error(RuntimeError)
    end
  end

end