treetop 0.1.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|