treetop 1.6.6 → 1.6.11

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