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
|