treetop 1.6.8 → 1.6.9
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.
- checksums.yaml +4 -4
- data/Gemfile +18 -0
- data/History.txt +18 -0
- data/Rakefile +3 -28
- data/Treetop.tmbundle/Preferences/Comments.tmPreferences +28 -0
- data/Treetop.tmbundle/Snippets/grammar ___ end.tmSnippet +20 -0
- data/Treetop.tmbundle/Snippets/rule ___ end.tmSnippet +18 -0
- data/Treetop.tmbundle/Support/nibs/SyntaxTreeViewer.nib/designable.nib +1524 -0
- data/Treetop.tmbundle/Support/nibs/SyntaxTreeViewer.nib/keyedobjects.nib +0 -0
- data/Treetop.tmbundle/Support/syntax_tree_viewer.rb +117 -0
- data/Treetop.tmbundle/Syntaxes/Treetop Grammar.tmLanguage +358 -0
- data/Treetop.tmbundle/info.plist +10 -0
- data/lib/treetop/runtime/compiled_parser.rb +15 -2
- data/lib/treetop/version.rb +1 -1
- data/treetop.gemspec +25 -157
- metadata +12 -56
- data/spec/compiler/and_predicate_spec.rb +0 -36
- data/spec/compiler/anything_symbol_spec.rb +0 -47
- data/spec/compiler/character_class_spec.rb +0 -304
- data/spec/compiler/choice_spec.rb +0 -89
- data/spec/compiler/circular_compilation_spec.rb +0 -30
- data/spec/compiler/failure_propagation_functional_spec.rb +0 -21
- data/spec/compiler/grammar_compiler_spec.rb +0 -113
- data/spec/compiler/grammar_spec.rb +0 -44
- data/spec/compiler/multibyte_chars_spec.rb +0 -38
- data/spec/compiler/namespace_spec.rb +0 -42
- data/spec/compiler/nonterminal_symbol_spec.rb +0 -40
- data/spec/compiler/not_predicate_spec.rb +0 -52
- data/spec/compiler/occurrence_range_spec.rb +0 -186
- data/spec/compiler/one_or_more_spec.rb +0 -35
- data/spec/compiler/optional_spec.rb +0 -37
- data/spec/compiler/parenthesized_expression_spec.rb +0 -34
- data/spec/compiler/parsing_rule_spec.rb +0 -61
- data/spec/compiler/repeated_subrule_spec.rb +0 -29
- data/spec/compiler/semantic_predicate_spec.rb +0 -176
- data/spec/compiler/sequence_spec.rb +0 -129
- data/spec/compiler/terminal_spec.rb +0 -177
- data/spec/compiler/terminal_symbol_spec.rb +0 -40
- data/spec/compiler/test_grammar.treetop +0 -7
- data/spec/compiler/test_grammar.tt +0 -7
- data/spec/compiler/test_grammar_do.treetop +0 -7
- data/spec/compiler/test_grammar_magic_coding.treetop +0 -8
- data/spec/compiler/test_grammar_magic_encoding.treetop +0 -8
- data/spec/compiler/tt_compiler_spec.rb +0 -224
- data/spec/compiler/zero_or_more_spec.rb +0 -58
- data/spec/composition/a.treetop +0 -11
- data/spec/composition/b.treetop +0 -11
- data/spec/composition/c.treetop +0 -10
- data/spec/composition/d.treetop +0 -10
- data/spec/composition/f.treetop +0 -17
- data/spec/composition/grammar_composition_spec.rb +0 -40
- data/spec/composition/subfolder/e_includes_c.treetop +0 -15
- data/spec/ruby_extensions/string_spec.rb +0 -32
- data/spec/runtime/compiled_parser_spec.rb +0 -153
- data/spec/runtime/syntax_node_spec.rb +0 -77
- data/spec/spec_helper.rb +0 -123
@@ -1,89 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module ChoiceSpec
|
4
|
-
describe "A choice between terminal symbols" do
|
5
|
-
testing_expression '("foo" { def foo_method; end } / "bar" { def bar_method; end } / "baz" { def baz_method; end }) {def bat_method; end}'
|
6
|
-
|
7
|
-
it "successfully parses input matching any of the alternatives, returning a node that responds to methods defined in its respective inline module" do
|
8
|
-
result = parse('foo')
|
9
|
-
result.should_not be_nil
|
10
|
-
result.should respond_to(:foo_method)
|
11
|
-
result.should_not respond_to(:bar_method)
|
12
|
-
result.should_not respond_to(:baz_method)
|
13
|
-
result.should respond_to(:bat_method)
|
14
|
-
|
15
|
-
result = parse('bar')
|
16
|
-
result.should_not be_nil
|
17
|
-
result.should_not respond_to(:foo_method)
|
18
|
-
result.should respond_to(:bar_method)
|
19
|
-
result.should_not respond_to(:baz_method)
|
20
|
-
result.should respond_to(:bat_method)
|
21
|
-
|
22
|
-
result = parse('baz')
|
23
|
-
result.should_not be_nil
|
24
|
-
result.should_not respond_to(:foo_method)
|
25
|
-
result.should_not respond_to(:bar_method)
|
26
|
-
result.should respond_to(:baz_method)
|
27
|
-
result.should respond_to(:bat_method)
|
28
|
-
end
|
29
|
-
|
30
|
-
it "upon parsing a string matching the second alternative, records the failure of the first terminal" do
|
31
|
-
result = parse('bar')
|
32
|
-
terminal_failures = parser.terminal_failures
|
33
|
-
terminal_failures.size.should == 1
|
34
|
-
failure = terminal_failures[0]
|
35
|
-
failure.expected_string.should == '"foo"'
|
36
|
-
failure.index.should == 0
|
37
|
-
end
|
38
|
-
|
39
|
-
it "upon parsing a string matching the third alternative, records the failure of the first two terminals" do
|
40
|
-
result = parse('baz')
|
41
|
-
|
42
|
-
terminal_failures = parser.terminal_failures
|
43
|
-
|
44
|
-
terminal_failures.size.should == 2
|
45
|
-
|
46
|
-
failure_1 = terminal_failures[0]
|
47
|
-
failure_1.expected_string == 'foo'
|
48
|
-
failure_1.index.should == 0
|
49
|
-
|
50
|
-
failure_2 = terminal_failures[1]
|
51
|
-
failure_2.expected_string == 'bar'
|
52
|
-
failure_2.index.should == 0
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
describe "A choice between sequences" do
|
57
|
-
testing_expression "'foo' 'bar' 'baz'\n/\n'bing' 'bang' 'boom'"
|
58
|
-
|
59
|
-
it "successfully parses input matching any of the alternatives" do
|
60
|
-
parse('foobarbaz').should_not be_nil
|
61
|
-
parse('bingbangboom').should_not be_nil
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
describe "A choice between terminals followed by a block" do
|
66
|
-
testing_expression "('a'/ 'bb' / [c]) { def a_method; end }"
|
67
|
-
|
68
|
-
it "extends a match of any of its subexpressions with a module created from the block" do
|
69
|
-
['a', 'bb', 'c'].each do |letter|
|
70
|
-
parse(letter).should respond_to(:a_method)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
module TestModule
|
76
|
-
def a_method
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
describe "a choice followed by a declared module" do
|
81
|
-
testing_expression "('a'/ 'bb' / [c]) <ChoiceSpec::TestModule>"
|
82
|
-
|
83
|
-
it "extends a match of any of its subexpressions with a module created from the block" do
|
84
|
-
['a', 'bb', 'c'].each do |letter|
|
85
|
-
parse(letter).should respond_to(:a_method)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
BENCHMARK = false
|
4
|
-
METAGRAMMAR_PATH = File.expand_path('../../../lib/treetop/compiler/metagrammar.treetop', __FILE__)
|
5
|
-
|
6
|
-
module CircularCompilationSpec
|
7
|
-
describe "a parser for the metagrammar" do
|
8
|
-
attr_reader :parser
|
9
|
-
|
10
|
-
before do
|
11
|
-
@parser = Treetop::Compiler::MetagrammarParser.new
|
12
|
-
end
|
13
|
-
|
14
|
-
it "can parse the metagrammar.treetop whence it was generated" do
|
15
|
-
File.open(METAGRAMMAR_PATH, 'r') do |f|
|
16
|
-
metagrammar_source = f.read
|
17
|
-
result = parser.parse(metagrammar_source)
|
18
|
-
result.should_not be_nil
|
19
|
-
|
20
|
-
# generated_parser = result.compile
|
21
|
-
# Object.class_eval(generated_parser)
|
22
|
-
# parser_2 = Treetop::Compiler::MetagrammarParser.new
|
23
|
-
# optionally_benchmark do
|
24
|
-
# result = parser_2.parse(metagrammar_source)
|
25
|
-
# result.should_not be_nil
|
26
|
-
# end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe "An expression for braces surrounding zero or more letters followed by semicolons" do
|
4
|
-
testing_expression "'{' ([a-z] ';')* '}'"
|
5
|
-
|
6
|
-
it "parses matching input successfully" do
|
7
|
-
parse('{a;b;c;}').should_not be_nil
|
8
|
-
end
|
9
|
-
|
10
|
-
it "fails to parse input with an expression that is missing a semicolon, reporting the terminal failure occurring at the maximum index" do
|
11
|
-
parse('{a;b;c}') do |result|
|
12
|
-
result.should be_nil
|
13
|
-
|
14
|
-
terminal_failures = parser.terminal_failures
|
15
|
-
terminal_failures.size.should == 1
|
16
|
-
failure = terminal_failures[0]
|
17
|
-
failure.index.should == 6
|
18
|
-
failure.expected_string.should == "';'"
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,113 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'tmpdir'
|
3
|
-
|
4
|
-
describe Compiler::GrammarCompiler do
|
5
|
-
attr_reader :compiler, :source_path_with_treetop_extension, :source_path_with_tt_extension, :target_path, :alternate_target_path
|
6
|
-
before do
|
7
|
-
@compiler = Compiler::GrammarCompiler.new
|
8
|
-
|
9
|
-
dir = File.dirname(__FILE__)
|
10
|
-
@tmpdir = Dir.tmpdir
|
11
|
-
|
12
|
-
@source_path_with_treetop_extension = "#{dir}/test_grammar.treetop"
|
13
|
-
@source_path_with_do = "#{dir}/test_grammar_do.treetop"
|
14
|
-
@source_path_with_tt_extension = "#{dir}/test_grammar.tt"
|
15
|
-
@source_path_with_magic_coding = "#{dir}/test_grammar_magic_coding.treetop"
|
16
|
-
@source_path_with_magic_encoding = "#{dir}/test_grammar_magic_encoding.treetop"
|
17
|
-
@target_path = "#{@tmpdir}/test_grammar.rb"
|
18
|
-
@target_path_with_do = "#{@tmpdir}/test_grammar_do.rb"
|
19
|
-
@target_path_with_magic_coding = "#{@tmpdir}/test_grammar_magic_coding.rb"
|
20
|
-
@target_path_with_magic_encoding = "#{@tmpdir}/test_grammar_magic_encoding.rb"
|
21
|
-
@alternate_target_path = "#{@tmpdir}/test_grammar_alt.rb"
|
22
|
-
delete_target_files
|
23
|
-
end
|
24
|
-
|
25
|
-
after do
|
26
|
-
delete_target_files
|
27
|
-
Object.class_eval do
|
28
|
-
remove_const(:Test) if const_defined?(:Test)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
specify "compilation of a single file to a default file name" do
|
33
|
-
src_copy = "#{@tmpdir}/test_grammar.treetop"
|
34
|
-
File.open(source_path_with_treetop_extension) { |f| File.open(src_copy,'w'){|o|o.write(f.read)} }
|
35
|
-
File.exists?(target_path).should be_falsey
|
36
|
-
compiler.compile(src_copy)
|
37
|
-
File.exists?(target_path).should be_truthy
|
38
|
-
require target_path
|
39
|
-
Test::GrammarParser.new.parse('foo').should_not be_nil
|
40
|
-
end
|
41
|
-
|
42
|
-
specify "compilation of a single file to an explicit file name" do
|
43
|
-
File.exists?(alternate_target_path).should be_falsey
|
44
|
-
compiler.compile(source_path_with_treetop_extension, alternate_target_path)
|
45
|
-
File.exists?(alternate_target_path).should be_truthy
|
46
|
-
require alternate_target_path
|
47
|
-
Test::GrammarParser.new.parse('foo').should_not be_nil
|
48
|
-
end
|
49
|
-
|
50
|
-
specify "compilation of a single file without writing it to an output file" do
|
51
|
-
compiler.ruby_source(source_path_with_treetop_extension).should_not be_nil
|
52
|
-
end
|
53
|
-
|
54
|
-
specify "ruby_source_from_string compiles a grammar stored in string" do
|
55
|
-
compiler.ruby_source_from_string(File.read(source_path_with_treetop_extension)).should_not be_nil
|
56
|
-
end
|
57
|
-
|
58
|
-
specify "Treetop.load_from_string compiles and evaluates a source grammar stored in string" do
|
59
|
-
Treetop.load_from_string File.read(source_path_with_treetop_extension)
|
60
|
-
Test::GrammarParser.new.parse('foo').should_not be_nil
|
61
|
-
end
|
62
|
-
|
63
|
-
specify "Treetop.load compiles and evaluates a source grammar with a .treetop extension" do
|
64
|
-
Treetop.load source_path_with_treetop_extension
|
65
|
-
Test::GrammarParser.new.parse('foo').should_not be_nil
|
66
|
-
end
|
67
|
-
|
68
|
-
specify "Treetop.load compiles and evaluates a source grammar with a .tt extension" do
|
69
|
-
path_without_extension = source_path_with_tt_extension
|
70
|
-
Treetop.load path_without_extension
|
71
|
-
Test::GrammarParser.new.parse('foo').should_not be_nil
|
72
|
-
end
|
73
|
-
|
74
|
-
|
75
|
-
specify "Treetop.load compiles and evaluates source grammar with no extension" do
|
76
|
-
path_without_extension = source_path_with_treetop_extension.gsub(/\.treetop\Z/, '')
|
77
|
-
Treetop.load path_without_extension
|
78
|
-
Test::GrammarParser.new.parse('foo').should_not be_nil
|
79
|
-
end
|
80
|
-
|
81
|
-
specify "grammars with 'do' compile" do
|
82
|
-
src_copy = "#{@tmpdir}/test_grammar_do.treetop"
|
83
|
-
File.open(@source_path_with_do) { |f| File.open(src_copy,'w'){|o|o.write(f.read)} }
|
84
|
-
compiler.compile(src_copy)
|
85
|
-
require @target_path_with_do
|
86
|
-
Test::GrammarParser.new.parse('foo').should_not be_nil
|
87
|
-
end
|
88
|
-
|
89
|
-
specify "grammars with magic 'encoding' comments keep those comments at the top" do
|
90
|
-
src_copy = "#{@tmpdir}/test_grammar_magic_encoding.treetop"
|
91
|
-
File.open(@source_path_with_magic_encoding) do |f|
|
92
|
-
File.open(src_copy,'w'){|o|o.write(f.read)}
|
93
|
-
end
|
94
|
-
compiler.compile(src_copy)
|
95
|
-
File.open(@target_path_with_magic_encoding).readline.should == "# encoding: UTF-8\n"
|
96
|
-
end
|
97
|
-
|
98
|
-
specify "grammars with magic 'coding' comments keep those comments at the top" do
|
99
|
-
src_copy = "#{@tmpdir}/test_grammar_magic_coding.treetop"
|
100
|
-
File.open(@source_path_with_magic_coding) do |f|
|
101
|
-
File.open(src_copy,'w'){|o|o.write(f.read)}
|
102
|
-
end
|
103
|
-
compiler.compile(src_copy)
|
104
|
-
File.open(@target_path_with_magic_coding).readline.should == "# coding: UTF-8\n"
|
105
|
-
end
|
106
|
-
|
107
|
-
def delete_target_files
|
108
|
-
File.delete(target_path) if File.exists?(target_path)
|
109
|
-
File.delete(@target_path_with_do) if File.exists?(@target_path_with_do)
|
110
|
-
File.delete(alternate_target_path) if File.exists?(alternate_target_path)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
@@ -1,44 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module GrammarSpec
|
4
|
-
module Bar
|
5
|
-
end
|
6
|
-
|
7
|
-
describe "a grammar" do
|
8
|
-
testing_grammar %{
|
9
|
-
grammar Foo
|
10
|
-
# This comment should not cause a syntax error, nor should the following empty one
|
11
|
-
#
|
12
|
-
include GrammarSpec::Bar
|
13
|
-
|
14
|
-
rule foo
|
15
|
-
bar / baz
|
16
|
-
end
|
17
|
-
|
18
|
-
rule bar
|
19
|
-
'bar' 'bar'
|
20
|
-
end
|
21
|
-
|
22
|
-
rule baz
|
23
|
-
'baz' 'baz'
|
24
|
-
end
|
25
|
-
end
|
26
|
-
}
|
27
|
-
|
28
|
-
it "parses matching input" do
|
29
|
-
parse('barbar').should_not be_nil
|
30
|
-
parse('bazbaz').should_not be_nil
|
31
|
-
end
|
32
|
-
|
33
|
-
it "fails if it does not parse all input" do
|
34
|
-
parse('barbarbazbaz') do |result|
|
35
|
-
result.should be_nil
|
36
|
-
parser.terminal_failures.size.should == 1
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
it "mixes in included modules" do
|
41
|
-
self.class.const_get(:Foo).ancestors.should include(GrammarSpec::Bar)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
module MultibyteCharsSpec
|
6
|
-
describe "an anything symbol", :multibyte => true do
|
7
|
-
testing_expression '.'
|
8
|
-
it "matches an UTF-8 character" do
|
9
|
-
parse_multibyte("ø").should_not be_nil
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
describe "A character class containing UTF-8 characters", :multibyte => true do
|
14
|
-
testing_expression "[æøå]"
|
15
|
-
it "recognizes the UTF-8 characters" do
|
16
|
-
parse_multibyte("ø").should_not be_nil
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
describe( "a character class repetition containing UTF-8 characters mixed with other expressions",
|
21
|
-
:multibyte => true
|
22
|
-
) do
|
23
|
-
testing_expression '[æøå]+ "a"'
|
24
|
-
it "lazily instantiates a node for the character" do
|
25
|
-
result = parse_multibyte('æøåa')
|
26
|
-
pending "Multibyte support is not supported in Ruby 1.8.6" if RUBY_VERSION =~ /^1\.8.6/
|
27
|
-
result.elements[0].instance_variable_get("@elements").should include(true)
|
28
|
-
result.elements[0].elements.should_not include(true)
|
29
|
-
result.elements[0].elements.size.should == 3
|
30
|
-
result.elements.size.should == 2
|
31
|
-
result.elements[0].text_value.should == "æøå"
|
32
|
-
result.elements[0].elements[0].text_value.should == "æ"
|
33
|
-
result.elements[0].elements[1].text_value.should == "ø"
|
34
|
-
result.elements[0].elements[2].text_value.should == "å"
|
35
|
-
result.elements[1].text_value == "a"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module NamespaceSpec
|
4
|
-
|
5
|
-
describe "a grammar" do
|
6
|
-
class_eval("module Foo; end")
|
7
|
-
testing_grammar %{
|
8
|
-
module Foo::Bar
|
9
|
-
module Baz
|
10
|
-
grammar Bat
|
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
|
-
end
|
24
|
-
end
|
25
|
-
}
|
26
|
-
|
27
|
-
it "parses matching input" do
|
28
|
-
parse('barbar').should_not be_nil
|
29
|
-
parse('bazbaz').should_not be_nil
|
30
|
-
end
|
31
|
-
|
32
|
-
it "mixes in included modules" do
|
33
|
-
foo = self.class.const_get(:Foo)
|
34
|
-
bar = foo.const_get(:Bar)
|
35
|
-
baz = bar.const_get(:Baz)
|
36
|
-
baz.class.should == Module
|
37
|
-
bat = baz.const_get(:Bat)
|
38
|
-
bat.class.should == Module
|
39
|
-
baz.const_get(:BatParser).class.should == Class
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module NonterminalSymbolSpec
|
4
|
-
describe "A nonterminal symbol followed by a block" do
|
5
|
-
testing_expression 'foo { def a_method; end }'
|
6
|
-
|
7
|
-
parser_class_under_test.class_eval do
|
8
|
-
def _nt_foo
|
9
|
-
'_nt_foo called'
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
it "compiles to a method call, extending its results with the anonymous module for the block" do
|
14
|
-
result = parse('')
|
15
|
-
result.should == '_nt_foo called'
|
16
|
-
result.should respond_to(:a_method)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
module TestModule
|
21
|
-
def a_method
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
describe "a non-terminal followed by a module declaration" do
|
26
|
-
testing_expression 'foo <NonterminalSymbolSpec::TestModule>'
|
27
|
-
|
28
|
-
parser_class_under_test.class_eval do
|
29
|
-
def _nt_foo
|
30
|
-
'_nt_foo called'
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
it "compiles to a method call, extending its results with the anonymous module for the block" do
|
35
|
-
result = parse('')
|
36
|
-
result.should == '_nt_foo called'
|
37
|
-
result.should respond_to(:a_method)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module NotPredicateSpec
|
4
|
-
describe "A !-predicated terminal symbol" do
|
5
|
-
testing_expression '!"foo"'
|
6
|
-
|
7
|
-
it "fails to parse input matching the terminal symbol" do
|
8
|
-
parse('foo') do |result|
|
9
|
-
result.should be_nil
|
10
|
-
parser.terminal_failures.size.should == 1
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
describe "A !-predicated character class symbol" do
|
16
|
-
testing_expression '![aeiou]'
|
17
|
-
|
18
|
-
it "fails to parse input matching the terminal symbol" do
|
19
|
-
parse('e') do |result|
|
20
|
-
result.should be_nil
|
21
|
-
parser.terminal_failures.size.should == 1
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
describe "A sequence of a terminal and an and another !-predicated terminal" do
|
27
|
-
testing_expression '"foo" !"bar"'
|
28
|
-
|
29
|
-
it "fails to match input matching both terminals" do
|
30
|
-
parse('foobar').should be_nil
|
31
|
-
end
|
32
|
-
|
33
|
-
it "successfully parses input matching the first terminal and not the second, reporting the parse failure of the second terminal" do
|
34
|
-
parse('foo') do |result|
|
35
|
-
result.should_not be_nil
|
36
|
-
terminal_failures = parser.terminal_failures
|
37
|
-
terminal_failures.size.should == 0
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
describe "A !-predicated sequence" do
|
43
|
-
testing_expression '!("a" "b" "cc")'
|
44
|
-
|
45
|
-
it "fails to parse matching input" do
|
46
|
-
parse('abcc') do |result|
|
47
|
-
result.should be_nil
|
48
|
-
parser.terminal_failures.size.should == 1
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|