treetop 1.6.8 → 1.6.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +18 -0
  3. data/History.txt +18 -0
  4. data/Rakefile +3 -28
  5. data/Treetop.tmbundle/Preferences/Comments.tmPreferences +28 -0
  6. data/Treetop.tmbundle/Snippets/grammar ___ end.tmSnippet +20 -0
  7. data/Treetop.tmbundle/Snippets/rule ___ end.tmSnippet +18 -0
  8. data/Treetop.tmbundle/Support/nibs/SyntaxTreeViewer.nib/designable.nib +1524 -0
  9. data/Treetop.tmbundle/Support/nibs/SyntaxTreeViewer.nib/keyedobjects.nib +0 -0
  10. data/Treetop.tmbundle/Support/syntax_tree_viewer.rb +117 -0
  11. data/Treetop.tmbundle/Syntaxes/Treetop Grammar.tmLanguage +358 -0
  12. data/Treetop.tmbundle/info.plist +10 -0
  13. data/lib/treetop/runtime/compiled_parser.rb +15 -2
  14. data/lib/treetop/version.rb +1 -1
  15. data/treetop.gemspec +25 -157
  16. metadata +12 -56
  17. data/spec/compiler/and_predicate_spec.rb +0 -36
  18. data/spec/compiler/anything_symbol_spec.rb +0 -47
  19. data/spec/compiler/character_class_spec.rb +0 -304
  20. data/spec/compiler/choice_spec.rb +0 -89
  21. data/spec/compiler/circular_compilation_spec.rb +0 -30
  22. data/spec/compiler/failure_propagation_functional_spec.rb +0 -21
  23. data/spec/compiler/grammar_compiler_spec.rb +0 -113
  24. data/spec/compiler/grammar_spec.rb +0 -44
  25. data/spec/compiler/multibyte_chars_spec.rb +0 -38
  26. data/spec/compiler/namespace_spec.rb +0 -42
  27. data/spec/compiler/nonterminal_symbol_spec.rb +0 -40
  28. data/spec/compiler/not_predicate_spec.rb +0 -52
  29. data/spec/compiler/occurrence_range_spec.rb +0 -186
  30. data/spec/compiler/one_or_more_spec.rb +0 -35
  31. data/spec/compiler/optional_spec.rb +0 -37
  32. data/spec/compiler/parenthesized_expression_spec.rb +0 -34
  33. data/spec/compiler/parsing_rule_spec.rb +0 -61
  34. data/spec/compiler/repeated_subrule_spec.rb +0 -29
  35. data/spec/compiler/semantic_predicate_spec.rb +0 -176
  36. data/spec/compiler/sequence_spec.rb +0 -129
  37. data/spec/compiler/terminal_spec.rb +0 -177
  38. data/spec/compiler/terminal_symbol_spec.rb +0 -40
  39. data/spec/compiler/test_grammar.treetop +0 -7
  40. data/spec/compiler/test_grammar.tt +0 -7
  41. data/spec/compiler/test_grammar_do.treetop +0 -7
  42. data/spec/compiler/test_grammar_magic_coding.treetop +0 -8
  43. data/spec/compiler/test_grammar_magic_encoding.treetop +0 -8
  44. data/spec/compiler/tt_compiler_spec.rb +0 -224
  45. data/spec/compiler/zero_or_more_spec.rb +0 -58
  46. data/spec/composition/a.treetop +0 -11
  47. data/spec/composition/b.treetop +0 -11
  48. data/spec/composition/c.treetop +0 -10
  49. data/spec/composition/d.treetop +0 -10
  50. data/spec/composition/f.treetop +0 -17
  51. data/spec/composition/grammar_composition_spec.rb +0 -40
  52. data/spec/composition/subfolder/e_includes_c.treetop +0 -15
  53. data/spec/ruby_extensions/string_spec.rb +0 -32
  54. data/spec/runtime/compiled_parser_spec.rb +0 -153
  55. data/spec/runtime/syntax_node_spec.rb +0 -77
  56. 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