treetop 0.1.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +3 -0
- data/Rakefile +35 -0
- data/bin/tt +25 -0
- data/lib/treetop.rb +10 -6
- data/lib/treetop/compiler.rb +7 -0
- data/lib/treetop/compiler/grammar_compiler.rb +21 -0
- data/lib/treetop/compiler/lexical_address_space.rb +17 -0
- data/lib/treetop/compiler/load_grammar.rb +7 -0
- data/lib/treetop/compiler/metagrammar.rb +2441 -0
- data/lib/treetop/compiler/metagrammar.treetop +384 -0
- data/lib/treetop/compiler/node_classes.rb +18 -0
- data/lib/treetop/compiler/node_classes/anything_symbol.rb +10 -0
- data/lib/treetop/compiler/node_classes/atomic_expression.rb +9 -0
- data/lib/treetop/compiler/node_classes/character_class.rb +10 -0
- data/lib/treetop/compiler/node_classes/choice.rb +31 -0
- data/lib/treetop/compiler/node_classes/declaration_sequence.rb +24 -0
- data/lib/treetop/compiler/node_classes/grammar.rb +28 -0
- data/lib/treetop/compiler/node_classes/inline_module.rb +27 -0
- data/lib/treetop/compiler/node_classes/nonterminal.rb +11 -0
- data/lib/treetop/compiler/node_classes/optional.rb +19 -0
- data/lib/treetop/compiler/node_classes/parenthesized_expression.rb +9 -0
- data/lib/treetop/compiler/node_classes/parsing_expression.rb +132 -0
- data/lib/treetop/compiler/node_classes/parsing_rule.rb +55 -0
- data/lib/treetop/compiler/node_classes/predicate.rb +45 -0
- data/lib/treetop/compiler/node_classes/repetition.rb +56 -0
- data/lib/treetop/compiler/node_classes/sequence.rb +64 -0
- data/lib/treetop/compiler/node_classes/terminal.rb +10 -0
- data/lib/treetop/compiler/node_classes/treetop_file.rb +9 -0
- data/lib/treetop/compiler/ruby_builder.rb +109 -0
- data/lib/treetop/ruby_extensions.rb +2 -0
- data/lib/treetop/ruby_extensions/string.rb +19 -0
- data/lib/treetop/runtime.rb +9 -0
- data/lib/treetop/runtime/compiled_parser.rb +66 -0
- data/lib/treetop/runtime/node_cache.rb +27 -0
- data/lib/treetop/runtime/parse_cache.rb +19 -0
- data/lib/treetop/runtime/parse_failure.rb +32 -0
- data/lib/treetop/runtime/parse_result.rb +30 -0
- data/lib/treetop/runtime/syntax_node.rb +53 -0
- data/lib/treetop/runtime/terminal_parse_failure.rb +33 -0
- data/lib/treetop/runtime/terminal_syntax_node.rb +12 -0
- data/test/compilation_target/target.rb +143 -0
- data/test/compilation_target/target.treetop +15 -0
- data/test/compilation_target/target_test.rb +56 -0
- data/test/compiler/and_predicate_test.rb +33 -0
- data/test/compiler/anything_symbol_test.rb +24 -0
- data/test/compiler/character_class_test.rb +45 -0
- data/test/compiler/choice_test.rb +49 -0
- data/test/compiler/circular_compilation_test.rb +20 -0
- data/test/compiler/failure_propagation_functional_test.rb +20 -0
- data/test/compiler/grammar_compiler_test.rb +58 -0
- data/test/compiler/grammar_test.rb +33 -0
- data/test/compiler/nonterminal_symbol_test.rb +15 -0
- data/test/compiler/not_predicate_test.rb +35 -0
- data/test/compiler/one_or_more_test.rb +30 -0
- data/test/compiler/optional_test.rb +32 -0
- data/test/compiler/parsing_rule_test.rb +30 -0
- data/test/compiler/sequence_test.rb +68 -0
- data/test/compiler/terminal_symbol_test.rb +35 -0
- data/test/compiler/test_grammar.treetop +7 -0
- data/test/compiler/zero_or_more_test.rb +51 -0
- data/test/composition/a.treetop +11 -0
- data/test/composition/b.treetop +11 -0
- data/test/composition/c.treetop +10 -0
- data/test/composition/d.treetop +10 -0
- data/test/composition/grammar_composition_test.rb +23 -0
- data/test/parser/syntax_node_test.rb +53 -0
- data/test/parser/terminal_parse_failure_test.rb +22 -0
- data/test/ruby_extensions/string_test.rb +33 -0
- data/test/screw/Rakefile +16 -0
- data/test/screw/unit.rb +37 -0
- data/test/screw/unit/assertion_failed_error.rb +14 -0
- data/test/screw/unit/assertions.rb +615 -0
- data/test/screw/unit/auto_runner.rb +227 -0
- data/test/screw/unit/collector.rb +45 -0
- data/test/screw/unit/collector/dir.rb +107 -0
- data/test/screw/unit/collector/objectspace.rb +28 -0
- data/test/screw/unit/error.rb +48 -0
- data/test/screw/unit/failure.rb +45 -0
- data/test/screw/unit/sugar.rb +25 -0
- data/test/screw/unit/test_case.rb +176 -0
- data/test/screw/unit/test_result.rb +73 -0
- data/test/screw/unit/test_suite.rb +70 -0
- data/test/screw/unit/ui.rb +4 -0
- data/test/screw/unit/ui/console/test_runner.rb +118 -0
- data/test/screw/unit/ui/fox/test_runner.rb +268 -0
- data/test/screw/unit/ui/gtk/test_runner.rb +416 -0
- data/test/screw/unit/ui/gtk2/testrunner.rb +465 -0
- data/test/screw/unit/ui/test_runner_mediator.rb +58 -0
- data/test/screw/unit/ui/test_runner_utilities.rb +46 -0
- data/test/screw/unit/ui/tk/test_runner.rb +260 -0
- data/test/screw/unit/util.rb +4 -0
- data/test/screw/unit/util/backtrace_filter.rb +40 -0
- data/test/screw/unit/util/observable.rb +82 -0
- data/test/screw/unit/util/proc_wrapper.rb +48 -0
- data/test/test_helper.rb +89 -0
- metadata +127 -69
- data/lib/treetop/api.rb +0 -3
- data/lib/treetop/api/load_grammar.rb +0 -16
- data/lib/treetop/api/malformed_grammar_exception.rb +0 -9
- data/lib/treetop/grammar.rb +0 -7
- data/lib/treetop/grammar/grammar.rb +0 -48
- data/lib/treetop/grammar/grammar_builder.rb +0 -35
- data/lib/treetop/grammar/parsing_expression_builder.rb +0 -5
- data/lib/treetop/grammar/parsing_expression_builder_helper.rb +0 -121
- data/lib/treetop/grammar/parsing_expressions.rb +0 -18
- data/lib/treetop/grammar/parsing_expressions/and_predicate.rb +0 -17
- data/lib/treetop/grammar/parsing_expressions/anything_symbol.rb +0 -20
- data/lib/treetop/grammar/parsing_expressions/character_class.rb +0 -24
- data/lib/treetop/grammar/parsing_expressions/node_instantiating_parsing_expression.rb +0 -14
- data/lib/treetop/grammar/parsing_expressions/node_propagating_parsing_expression.rb +0 -4
- data/lib/treetop/grammar/parsing_expressions/nonterminal_symbol.rb +0 -42
- data/lib/treetop/grammar/parsing_expressions/not_predicate.rb +0 -18
- data/lib/treetop/grammar/parsing_expressions/one_or_more.rb +0 -12
- data/lib/treetop/grammar/parsing_expressions/optional.rb +0 -14
- data/lib/treetop/grammar/parsing_expressions/ordered_choice.rb +0 -27
- data/lib/treetop/grammar/parsing_expressions/parsing_expression.rb +0 -36
- data/lib/treetop/grammar/parsing_expressions/predicate.rb +0 -25
- data/lib/treetop/grammar/parsing_expressions/repeating_parsing_expression.rb +0 -29
- data/lib/treetop/grammar/parsing_expressions/sequence.rb +0 -41
- data/lib/treetop/grammar/parsing_expressions/terminal_parsing_expression.rb +0 -11
- data/lib/treetop/grammar/parsing_expressions/terminal_symbol.rb +0 -31
- data/lib/treetop/grammar/parsing_expressions/zero_or_more.rb +0 -11
- data/lib/treetop/grammar/parsing_rule.rb +0 -10
- data/lib/treetop/metagrammar.rb +0 -2
- data/lib/treetop/metagrammar/metagrammar.rb +0 -14
- data/lib/treetop/metagrammar/metagrammar.treetop +0 -320
- data/lib/treetop/parser.rb +0 -11
- data/lib/treetop/parser/node_cache.rb +0 -25
- data/lib/treetop/parser/parse_cache.rb +0 -17
- data/lib/treetop/parser/parse_failure.rb +0 -22
- data/lib/treetop/parser/parse_result.rb +0 -26
- data/lib/treetop/parser/parser.rb +0 -24
- data/lib/treetop/parser/sequence_syntax_node.rb +0 -14
- data/lib/treetop/parser/syntax_node.rb +0 -31
- data/lib/treetop/parser/terminal_parse_failure.rb +0 -18
- data/lib/treetop/parser/terminal_syntax_node.rb +0 -7
- data/lib/treetop/protometagrammar.rb +0 -16
- data/lib/treetop/protometagrammar/anything_symbol_expression_builder.rb +0 -13
- data/lib/treetop/protometagrammar/block_expression_builder.rb +0 -17
- data/lib/treetop/protometagrammar/character_class_expression_builder.rb +0 -25
- data/lib/treetop/protometagrammar/grammar_expression_builder.rb +0 -38
- data/lib/treetop/protometagrammar/nonterminal_symbol_expression_builder.rb +0 -45
- data/lib/treetop/protometagrammar/ordered_choice_expression_builder.rb +0 -21
- data/lib/treetop/protometagrammar/parsing_rule_expression_builder.rb +0 -23
- data/lib/treetop/protometagrammar/parsing_rule_sequence_expression_builder.rb +0 -14
- data/lib/treetop/protometagrammar/prefix_expression_builder.rb +0 -25
- data/lib/treetop/protometagrammar/primary_expression_builder.rb +0 -71
- data/lib/treetop/protometagrammar/protometagrammar.rb +0 -25
- data/lib/treetop/protometagrammar/sequence_expression_builder.rb +0 -37
- data/lib/treetop/protometagrammar/suffix_expression_builder.rb +0 -33
- data/lib/treetop/protometagrammar/terminal_symbol_expression_builder.rb +0 -52
- data/lib/treetop/protometagrammar/trailing_block_expression_builder.rb +0 -30
- data/lib/treetop/ruby_extension.rb +0 -11
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
class GrammarTest < CompilerTestCase
|
4
|
+
module Bar
|
5
|
+
end
|
6
|
+
|
7
|
+
testing_grammar %{
|
8
|
+
grammar Foo
|
9
|
+
include Bar
|
10
|
+
|
11
|
+
rule foo
|
12
|
+
bar / baz
|
13
|
+
end
|
14
|
+
|
15
|
+
rule bar
|
16
|
+
'bar' 'bar'
|
17
|
+
end
|
18
|
+
|
19
|
+
rule baz
|
20
|
+
'baz' 'baz'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
}
|
24
|
+
|
25
|
+
it "parses matching input" do
|
26
|
+
parse('barbar').should be_success
|
27
|
+
parse('bazbaz').should be_success
|
28
|
+
end
|
29
|
+
|
30
|
+
it "mixes in included modules" do
|
31
|
+
Foo.ancestors.should include(Bar)
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
describe "A nonterminal symbol", :extend => CompilerTestCase do
|
4
|
+
testing_expression 'foo'
|
5
|
+
|
6
|
+
parser_class_under_test.class_eval do
|
7
|
+
def _nt_foo
|
8
|
+
'_nt_foo called'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it "compiles to a message send" do
|
13
|
+
parse('').should == '_nt_foo called'
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
describe "A !-predicated terminal symbol", :extend => CompilerTestCase do
|
4
|
+
testing_expression '!"foo"'
|
5
|
+
|
6
|
+
it "fails to parse input matching the terminal symbol" do
|
7
|
+
parse('foo').should be_failure
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "A sequence of a terminal and an and another !-predicated terminal", :extend => CompilerTestCase do
|
12
|
+
testing_expression '"foo" !"bar"'
|
13
|
+
|
14
|
+
it "fails to match input matching both terminals" do
|
15
|
+
parse('foobar').should be_failure
|
16
|
+
end
|
17
|
+
|
18
|
+
it "successfully parses input matching the first terminal and not the second, with the failure of the second as a nested failure" do
|
19
|
+
parse('foo') do |result|
|
20
|
+
result.should be_success
|
21
|
+
result.nested_failures.size.should == 1
|
22
|
+
nested_failure = result.nested_failures[0]
|
23
|
+
nested_failure.index.should == 3
|
24
|
+
nested_failure.expected_string.should == 'bar'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "A !-predicated sequence", :extend => CompilerTestCase do
|
30
|
+
testing_expression '!("a" "b" "c")'
|
31
|
+
|
32
|
+
it "fails to parse matching input" do
|
33
|
+
parse('abc').should be_failure
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
class OneOrMoreOfTerminalTest < CompilerTestCase
|
4
|
+
testing_expression '"foo"+ <Foo> { def a_method; end }'
|
5
|
+
|
6
|
+
class Foo < Treetop::Runtime::SyntaxNode
|
7
|
+
end
|
8
|
+
|
9
|
+
it "fails to parse epsilon with a nested failure" do
|
10
|
+
parse('') do |result|
|
11
|
+
result.should be_failure
|
12
|
+
result.nested_failures.size.should == 1
|
13
|
+
nested_failure = result.nested_failures.first
|
14
|
+
nested_failure.index.should == 0
|
15
|
+
nested_failure.expected_string.should == 'foo'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it "successfully parses two of that terminal in a row, returning an instance of the declared node class with a nested failure representing the third attempt" do
|
20
|
+
parse("foofoo") do |result|
|
21
|
+
result.should be_success
|
22
|
+
result.should be_an_instance_of(Foo)
|
23
|
+
result.should respond_to(:a_method)
|
24
|
+
result.nested_failures.size.should == 1
|
25
|
+
nested_failure = result.nested_failures.first
|
26
|
+
nested_failure.index.should == 6
|
27
|
+
nested_failure.expected_string.should == 'foo'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
describe "An optional terminal symbol", :extend => CompilerTestCase do
|
4
|
+
testing_expression '"foo"?'
|
5
|
+
|
6
|
+
it "parses input matching the terminal" do
|
7
|
+
parse('foo').should be_success
|
8
|
+
end
|
9
|
+
|
10
|
+
it "parses epsilon, with a nested failure" do
|
11
|
+
parse('') do |result|
|
12
|
+
result.should be_success
|
13
|
+
result.interval.should == (0...0)
|
14
|
+
result.nested_failures.size.should == 1
|
15
|
+
nested_failure = result.nested_failures.first
|
16
|
+
nested_failure.index.should == 0
|
17
|
+
nested_failure.expected_string.should == 'foo'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "parses input not matching the terminal, returning an epsilon result with a nested failure" do
|
22
|
+
parse('bar') do |result|
|
23
|
+
result.should be_success
|
24
|
+
result.interval.should == (0...0)
|
25
|
+
result.nested_failures.size.should == 1
|
26
|
+
nested_failure = result.nested_failures.first
|
27
|
+
nested_failure.index.should == 0
|
28
|
+
nested_failure.expected_string.should == 'foo'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
class ParsingRuleTest < CompilerTestCase
|
4
|
+
|
5
|
+
testing_grammar %{
|
6
|
+
grammar Foo
|
7
|
+
rule bar
|
8
|
+
"baz"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
}
|
12
|
+
|
13
|
+
test "node cache storage and retrieval" do
|
14
|
+
parser = FooParser.new
|
15
|
+
parser.send(:prepare_to_parse, 'baz')
|
16
|
+
node_cache = parser.send(:node_cache)
|
17
|
+
|
18
|
+
node_cache[:bar][0].should be_nil
|
19
|
+
|
20
|
+
parser._nt_bar
|
21
|
+
|
22
|
+
cached_node = node_cache[:bar][0]
|
23
|
+
cached_node.should be_an_instance_of(Runtime::SyntaxNode)
|
24
|
+
cached_node.text_value.should == 'baz'
|
25
|
+
|
26
|
+
parser.instance_eval { @index = 0 }
|
27
|
+
parser._nt_bar.should equal(cached_node)
|
28
|
+
parser.index.should == cached_node.interval.end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
class SequenceOfTerminalsTest < CompilerTestCase
|
4
|
+
|
5
|
+
class Foo < Treetop::Runtime::SyntaxNode
|
6
|
+
end
|
7
|
+
|
8
|
+
testing_expression 'foo:"foo" bar:"bar" baz:"baz" <Foo> { def a_method; end }'
|
9
|
+
|
10
|
+
test "successful result is an instance of the declared node class with element accessor methods and the method from the inline module" do
|
11
|
+
parse('foobarbaz') do |result|
|
12
|
+
result.should be_success
|
13
|
+
result.should be_an_instance_of(Foo)
|
14
|
+
result.should respond_to(:a_method)
|
15
|
+
result.foo.text_value.should == 'foo'
|
16
|
+
result.bar.text_value.should == 'bar'
|
17
|
+
result.baz.text_value.should == 'baz'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
test "matching at a non-zero index" do
|
22
|
+
parse('---foobarbaz', :at_index => 3) do |result|
|
23
|
+
result.should be_success
|
24
|
+
result.should be_nonterminal
|
25
|
+
(result.elements.map {|elt| elt.text_value}).join.should == 'foobarbaz'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
test "non-matching input fails with a nested failure at the first terminal that did not match" do
|
30
|
+
parse('---foobazbaz', :at_index => 3) do |result|
|
31
|
+
result.should be_failure
|
32
|
+
result.index.should == 3
|
33
|
+
result.nested_failures.size.should == 1
|
34
|
+
nested_failure = result.nested_failures.first
|
35
|
+
nested_failure.index.should == 6
|
36
|
+
nested_failure.expected_string.should == 'bar'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class SequenceOfNonterminalsTest < CompilerTestCase
|
42
|
+
|
43
|
+
testing_grammar %{
|
44
|
+
grammar TestGrammar
|
45
|
+
rule sequence
|
46
|
+
foo bar baz {
|
47
|
+
def baz
|
48
|
+
'override' + super.text_value
|
49
|
+
end
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
rule foo 'foo' end
|
54
|
+
rule bar 'bar' end
|
55
|
+
rule baz 'baz' end
|
56
|
+
end
|
57
|
+
}
|
58
|
+
|
59
|
+
test "accessors for nonterminals are automatically defined and can be overridden in the inline block" do
|
60
|
+
parse('foobarbaz') do |result|
|
61
|
+
result.foo.text_value.should == 'foo'
|
62
|
+
result.bar.text_value.should == 'bar'
|
63
|
+
result.baz.should == 'overridebaz'
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
class TerminalSymbolTest < CompilerTestCase
|
4
|
+
class Foo < Treetop::Runtime::SyntaxNode
|
5
|
+
end
|
6
|
+
|
7
|
+
testing_expression "'foo' <Foo> { def a_method; end }"
|
8
|
+
|
9
|
+
it "correctly parses matching input prefixes at various indices, returning an instance of the declared class that can respond to methods defined in the inline module" do
|
10
|
+
parse "foo", :at_index => 0 do |result|
|
11
|
+
result.should be_an_instance_of(Foo)
|
12
|
+
result.should respond_to(:a_method)
|
13
|
+
result.interval.should == (0...3)
|
14
|
+
result.text_value.should == 'foo'
|
15
|
+
end
|
16
|
+
|
17
|
+
parse "xfoo", :at_index => 1 do |result|
|
18
|
+
result.should be_an_instance_of(Foo)
|
19
|
+
result.should respond_to(:a_method)
|
20
|
+
result.interval.should == (1...4)
|
21
|
+
result.text_value.should == 'foo'
|
22
|
+
end
|
23
|
+
|
24
|
+
parse "---foo", :at_index => 3 do |result|
|
25
|
+
result.should be_an_instance_of(Foo)
|
26
|
+
result.should respond_to(:a_method)
|
27
|
+
result.interval.should == (3...6)
|
28
|
+
result.text_value.should == 'foo'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "fails to parse nonmatching input at the index even if a match occurs later" do
|
33
|
+
parse(" foo", :at_index => 0).should be_failure
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
class ZeroOrMoreOfATerminalWithNodeClassDeclarationTest < CompilerTestCase
|
4
|
+
|
5
|
+
class Foo < Treetop::Runtime::SyntaxNode
|
6
|
+
end
|
7
|
+
|
8
|
+
testing_expression '"foo"* <Foo> { def a_method; end }'
|
9
|
+
|
10
|
+
it "successfully parses epsilon, returning an instance declared node class with a nested failure" do
|
11
|
+
parse('') do |result|
|
12
|
+
result.should be_success
|
13
|
+
result.should be_an_instance_of(Foo)
|
14
|
+
result.should respond_to(:a_method)
|
15
|
+
result.nested_failures.size.should == 1
|
16
|
+
nested_failure = result.nested_failures.first
|
17
|
+
nested_failure.index.should == 0
|
18
|
+
nested_failure.expected_string.should == 'foo'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "successfully parses two of that terminal in a row, returning an instance of the declared node class with a nested failure representing the third attempt " do
|
23
|
+
parse("foofoo") do |result|
|
24
|
+
result.should be_success
|
25
|
+
result.should be_an_instance_of(Foo)
|
26
|
+
result.nested_failures.size.should == 1
|
27
|
+
nested_failure = result.nested_failures.first
|
28
|
+
nested_failure.index.should == 6
|
29
|
+
nested_failure.expected_string.should == 'foo'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "Zero or more of a sequence", :extend => CompilerTestCase do
|
35
|
+
testing_expression '("foo" "bar")*'
|
36
|
+
|
37
|
+
it "resets the index appropriately following partially matcing input" do
|
38
|
+
parse('foobarfoo') do |result|
|
39
|
+
result.should be_success
|
40
|
+
result.interval.should == (0...6)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "Zero or more of a choice", :extend => CompilerTestCase do
|
46
|
+
testing_expression '("a" / "b")*'
|
47
|
+
|
48
|
+
it "successfully parses matching input" do
|
49
|
+
parse('abba').should be_success
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
dir = File.dirname(__FILE__)
|
2
|
+
require File.join(dir, '..', 'test_helper')
|
3
|
+
|
4
|
+
class GrammarCompositionTest < Screw::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
dir = File.dirname(__FILE__)
|
7
|
+
load_grammar File.join(dir, 'a')
|
8
|
+
load_grammar File.join(dir, 'b')
|
9
|
+
load_grammar File.join(dir, 'c')
|
10
|
+
load_grammar File.join(dir, 'd')
|
11
|
+
|
12
|
+
@c = ::Test::CParser.new
|
13
|
+
@d = ::Test::DParser.new
|
14
|
+
end
|
15
|
+
|
16
|
+
test "rules in C have access to rules defined in A and B" do
|
17
|
+
@c.parse('abc').should be_success
|
18
|
+
end
|
19
|
+
|
20
|
+
test "rules in C can override rules in A and B with super semantics" do
|
21
|
+
@d.parse('superkeywordworks').should be_success
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
dir = File.dirname(__FILE__)
|
2
|
+
require "#{dir}/../test_helper"
|
3
|
+
|
4
|
+
describe "A new terminal syntax node" do
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@node = Runtime::SyntaxNode.new("input", 0...3)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "reports itself as terminal" do
|
11
|
+
@node.should be_terminal
|
12
|
+
@node.should_not be_nonterminal
|
13
|
+
end
|
14
|
+
|
15
|
+
it "has a text value based on the input and the interval" do
|
16
|
+
@node.text_value.should == "inp"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "has no nested failures" do
|
20
|
+
@node.nested_failures.should be_empty
|
21
|
+
end
|
22
|
+
|
23
|
+
it "has itself as its only element" do
|
24
|
+
@node.elements.should == [@node]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "A new nonterminal syntax node" do
|
29
|
+
def setup
|
30
|
+
@input = 'test input'
|
31
|
+
@nested_results = [Runtime::TerminalParseFailure.new(@input, 1, 'foo')]
|
32
|
+
@elements = Runtime::SyntaxNode.new('input', 0...3)
|
33
|
+
@node = Runtime::SyntaxNode.new('input', 0...3, @elements, @nested_results)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "reports itself as nonterminal" do
|
37
|
+
@node.should be_nonterminal
|
38
|
+
@node.should_not be_terminal
|
39
|
+
end
|
40
|
+
|
41
|
+
it "has a text value based on the input and the interval" do
|
42
|
+
@node.text_value.should == "inp"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "has the elements with which it was instantiated" do
|
46
|
+
@node.elements.should == @elements
|
47
|
+
end
|
48
|
+
|
49
|
+
it "has nested failures frow within the nested results with which it was instantiated" do
|
50
|
+
@node.nested_failures.should == @nested_results
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|