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,129 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module SequenceSpec
4
- class Foo < Treetop::Runtime::SyntaxNode
5
- end
6
-
7
- describe "a sequence of labeled terminal symbols followed by a node class declaration and a block" do
8
- testing_expression 'foo:"foo" bar:"bar" baz:"baz" <SequenceSpec::Foo> { def a_method; end }'
9
-
10
- it "upon successfully matching input, instantiates 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_not be_nil
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
- it "successfully matches at a non-zero index" do
22
- parse('---foobarbaz', :index => 3) do |result|
23
- result.should_not be_nil
24
- result.should be_nonterminal
25
- (result.elements.map {|elt| elt.text_value}).join.should == 'foobarbaz'
26
- end
27
- end
28
-
29
- it "fails to match non-matching input, recording the parse failure of first non-matching terminal" do
30
- parse('---foobazbaz', :index => 3) do |result|
31
- result.should be_nil
32
- parser.index.should == 3
33
- terminal_failures = parser.terminal_failures
34
- terminal_failures.size.should == 1
35
- failure = terminal_failures.first
36
- failure.index.should == 6
37
- failure.expected_string.should == '"bar"'
38
- end
39
- end
40
- end
41
-
42
- module ModFoo
43
- def mod_method; end
44
- end
45
-
46
- describe "a sequence of labeled terminal symbols followed by a node module declaration and a block" do
47
- testing_expression 'foo:"foo" bar:"bar" baz:"baz" <SequenceSpec::ModFoo> { def a_method; end }'
48
-
49
- it "upon successfully matching input, instantiates a syntax node and extends it with the declared module, element accessor methods, and the method from the inline module" do
50
- parse('foobarbaz') do |result|
51
- result.should_not be_nil
52
- result.should respond_to(:mod_method)
53
- result.should be_an_instance_of(Treetop::Runtime::SyntaxNode)
54
- result.should be_a_kind_of(ModFoo)
55
- result.should respond_to(:a_method)
56
- result.foo.text_value.should == 'foo'
57
- result.bar.text_value.should == 'bar'
58
- result.baz.text_value.should == 'baz'
59
- end
60
- end
61
- end
62
-
63
- describe "a labeled single element sequence followed by a node module declaration and a block" do
64
- testing_expression 'foo:"foo"+ <SequenceSpec::ModFoo> { def a_method; end }'
65
- it "upon successfully matching input, instantiates a syntax node and extends it with the declared module, element accessor methods, and the method from the inline module" do
66
- parse('foofoofoo') do |result|
67
- result.should_not be_nil
68
- result.should respond_to(:mod_method)
69
- result.should be_an_instance_of(Treetop::Runtime::SyntaxNode)
70
- result.should be_a_kind_of(ModFoo)
71
- result.should respond_to(:a_method)
72
- result.foo.text_value.should == 'foofoofoo'
73
- end
74
- end
75
- end
76
-
77
- describe "a sequence of non-terminals" do
78
- testing_grammar %{
79
- grammar TestGrammar
80
- rule sequence
81
- foo bar baz {
82
- def baz
83
- 'override' + super.text_value
84
- end
85
- }
86
- end
87
-
88
- rule foo 'foo' end
89
- rule bar 'bar' end
90
- rule baz 'baz' end
91
- end
92
- }
93
-
94
- it "defines accessors for non-terminals automatically that can be overridden in the inline block" do
95
- parse('foobarbaz') do |result|
96
- result.foo.text_value.should == 'foo'
97
- result.bar.text_value.should == 'bar'
98
- result.baz.should == 'overridebaz'
99
- end
100
- end
101
- end
102
-
103
- describe "Compiling a sequence containing various white-space errors" do
104
- it "should succeed on a valid sequence" do
105
- compiling_expression('foo:"foo" "bar" <SequenceSpec::Foo> { def a_method; end }').should_not raise_error
106
- end
107
-
108
- it "rejects space after a label" do
109
- compiling_expression('foo :"foo" "bar"').should raise_error(RuntimeError)
110
- end
111
-
112
- it "rejects space after label's colon" do
113
- compiling_expression('foo: "foo" "bar"').should raise_error(RuntimeError)
114
- end
115
-
116
- it "rejects missing space after a primary" do
117
- compiling_expression('foo:"foo""bar"').should raise_error(RuntimeError)
118
- end
119
-
120
- it "rejects missing space before node class declaration" do
121
- compiling_expression('foo:"foo" "bar"<SequenceSpec::Foo>').should raise_error(RuntimeError)
122
- end
123
-
124
- it "rejects missing space before inline module" do
125
- compiling_expression('foo:"foo" "bar" <SequenceSpec::Foo>{def a_method; end}').should raise_error(RuntimeError)
126
- end
127
- end
128
-
129
- end
@@ -1,177 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module TerminalSymbolSpec
4
- class Foo < Treetop::Runtime::SyntaxNode
5
- end
6
-
7
- describe "a terminal symbol" do
8
- testing_expression "'Foo'"
9
-
10
- it "matches the input string" do
11
- parse "Foo", :index => 0 do |result|
12
- result.should_not be_nil
13
- result.interval.should == (0...3)
14
- result.text_value.should == 'Foo'
15
- end
16
- end
17
-
18
- it "fails to match the input string other than at the start" do
19
- parse " Foo", :index => 0 do |result|
20
- result.should be_nil
21
- parser.terminal_failures.size.should == 1
22
- end
23
- end
24
-
25
- it "fails to match the input string in the wrong case" do
26
- parse "foo", :index => 0 do |result|
27
- result.should be_nil
28
- parser.terminal_failures.size.should == 1
29
- end
30
- end
31
- end
32
-
33
- describe "a terminal symbol with case-insensitive matching" do
34
- testing_expression "'Foo'i"
35
-
36
- it "matches the input string in the same case" do
37
- parse "Foo", :index => 0 do |result|
38
- result.should_not be_nil
39
- result.interval.should == (0...3)
40
- result.text_value.should == 'Foo'
41
- end
42
- end
43
-
44
- it "matches the input string in varied case" do
45
- parse "foO", :index => 0 do |result|
46
- result.should_not be_nil
47
- result.interval.should == (0...3)
48
- result.text_value.should == 'foO'
49
- end
50
- end
51
- end
52
-
53
- describe "a terminal symbol followed by a node class declaration and a block" do
54
- testing_expression "'foo' <TerminalSymbolSpec::Foo> { def a_method; end }"
55
-
56
- 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
57
- parse "foo", :index => 0 do |result|
58
- result.should be_an_instance_of(Foo)
59
- result.should respond_to(:a_method)
60
- result.interval.should == (0...3)
61
- result.text_value.should == 'foo'
62
- end
63
-
64
- parse "xfoo", :index => 1 do |result|
65
- result.should be_an_instance_of(Foo)
66
- result.should respond_to(:a_method)
67
- result.interval.should == (1...4)
68
- result.text_value.should == 'foo'
69
- end
70
-
71
- parse "---foo", :index => 3 do |result|
72
- result.should be_an_instance_of(Foo)
73
- result.should respond_to(:a_method)
74
- result.interval.should == (3...6)
75
- result.text_value.should == 'foo'
76
- end
77
- end
78
-
79
- it "fails to parse nonmatching input at the index even if a match occurs later" do
80
- parse(" foo", :index => 0) do |result|
81
- result.should be_nil
82
- parser.terminal_failures.size.should == 1
83
- end
84
- end
85
- end
86
-
87
- module ModFoo
88
- end
89
-
90
- describe "a terminal symbol followed by a node class declaration and a block" do
91
- testing_expression "'foo' <TerminalSymbolSpec::ModFoo> { def a_method; end }"
92
-
93
- it "correctly parses matching input prefixes at various indices, returning an instance of SyntaxNode extended with the declared module that can respond to methods defined in the inline module" do
94
- parse "foo", :index => 0 do |result|
95
- result.should be_an_instance_of(Treetop::Runtime::SyntaxNode)
96
- result.should be_a_kind_of(ModFoo)
97
- result.should respond_to(:a_method)
98
- result.interval.should == (0...3)
99
- result.text_value.should == 'foo'
100
- end
101
-
102
- parse "xfoo", :index => 1 do |result|
103
- result.should be_an_instance_of(Treetop::Runtime::SyntaxNode)
104
- result.should be_a_kind_of(ModFoo)
105
- result.should respond_to(:a_method)
106
- result.interval.should == (1...4)
107
- result.text_value.should == 'foo'
108
- end
109
-
110
- parse "---foo", :index => 3 do |result|
111
- result.should be_an_instance_of(Treetop::Runtime::SyntaxNode)
112
- result.should be_a_kind_of(ModFoo)
113
- result.should respond_to(:a_method)
114
- result.interval.should == (3...6)
115
- result.text_value.should == 'foo'
116
- end
117
- end
118
- end
119
-
120
- describe "a terminal regexp" do
121
- testing_expression "'Fo+'r"
122
-
123
- it "matches the input string" do
124
- parse "Fooo", :index => 0 do |result|
125
- result.should_not be_nil
126
- result.interval.should == (0...4)
127
- result.text_value.should == 'Fooo'
128
- end
129
- end
130
-
131
- it "fails to match the input string other than at the start" do
132
- parse " Foo", :index => 0 do |result|
133
- result.should be_nil
134
- parser.terminal_failures.size.should == 1
135
- end
136
- end
137
-
138
- it "fails to match the input string in the wrong case" do
139
- parse "foo", :index => 0 do |result|
140
- result.should be_nil
141
- parser.terminal_failures.size.should == 1
142
- end
143
- end
144
- end
145
-
146
- describe "a case-insensitive terminal regexp" do
147
- testing_expression "'Fo+'ri"
148
-
149
- it "matches the input string in the same case" do
150
- parse "Fooo", :index => 0 do |result|
151
- result.should_not be_nil
152
- result.interval.should == (0...4)
153
- result.text_value.should == 'Fooo'
154
- end
155
- end
156
-
157
- it "matches the input string in the same case" do
158
- parse "foOo", :index => 0 do |result|
159
- result.should_not be_nil
160
- result.interval.should == (0...4)
161
- result.text_value.should == 'foOo'
162
- end
163
- end
164
- end
165
-
166
- # Transient symbols were part of some idea of Nathan's that I no longer recall
167
- # describe "a transient terminal symbol" do
168
- # testing_expression "~'foo'"
169
- #
170
- # it "returns true upon parsing matching input prefixes at various indices" do
171
- # pending "transient terminal expressions"
172
- # parse("foo", :index => 0).should be_truthy
173
- # parse("-foo", :index => 1).should be_truthy
174
- # parse("---foo", :index => 3).should be_truthy
175
- # end
176
- # end
177
- end
@@ -1,40 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module TerminalSymbolSpec
4
- class Foo < Treetop::Runtime::SyntaxNode
5
- end
6
-
7
- describe "a terminal symbol followed by a node class declaration and a block" do
8
- testing_expression "'foo' <TerminalSymbolSpec::Foo> { def a_method; end }"
9
-
10
- 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
11
- parse "foo", :index => 0 do |result|
12
- result.should be_an_instance_of(Foo)
13
- result.should respond_to(:a_method)
14
- result.interval.should == (0...3)
15
- result.text_value.should == 'foo'
16
- end
17
-
18
- parse "xfoo", :index => 1 do |result|
19
- result.should be_an_instance_of(Foo)
20
- result.should respond_to(:a_method)
21
- result.interval.should == (1...4)
22
- result.text_value.should == 'foo'
23
- end
24
-
25
- parse "---foo", :index => 3 do |result|
26
- result.should be_an_instance_of(Foo)
27
- result.should respond_to(:a_method)
28
- result.interval.should == (3...6)
29
- result.text_value.should == 'foo'
30
- end
31
- end
32
-
33
- it "fails to parse nonmatching input at the index even if a match occurs later" do
34
- parse(" foo", :index => 0) do |result|
35
- result.should be_nil
36
- parser.terminal_failures.size.should == 1
37
- end
38
- end
39
- end
40
- end
@@ -1,7 +0,0 @@
1
- module Test
2
- grammar Grammar
3
- rule foo
4
- 'foo'
5
- end
6
- end
7
- end
@@ -1,7 +0,0 @@
1
- module Test
2
- grammar Grammar
3
- rule foo
4
- 'foo'
5
- end
6
- end
7
- end
@@ -1,7 +0,0 @@
1
- module Test
2
- grammar Grammar do
3
- rule foo do
4
- 'foo'
5
- end
6
- end
7
- end
@@ -1,8 +0,0 @@
1
- # coding: UTF-8
2
- module Test
3
- grammar Grammar do
4
- rule foo do
5
- 'foo'
6
- end
7
- end
8
- end
@@ -1,8 +0,0 @@
1
- # encoding: UTF-8
2
- module Test
3
- grammar Grammar do
4
- rule foo do
5
- 'foo'
6
- end
7
- end
8
- end
@@ -1,224 +0,0 @@
1
- require 'digest/sha1'
2
- require 'tmpdir'
3
-
4
- # ensure the Kernel.system and Kernel.open's always use the correct tt and
5
- # Treetop library versions, not a previously installed gem
6
- ENV['PATH'] = File.expand_path(File.dirname(__FILE__) + '../../../bin' +
7
- File::PATH_SEPARATOR + ENV['PATH'])
8
- $LOAD_PATH.unshift(File.expand_path('../../../../lib', __FILE__))
9
-
10
- describe "The 'tt' comand line compiler" do
11
- before(:each) do
12
- @tmpdir = Dir.tmpdir
13
- end
14
-
15
- context 'when processing a single grammar file' do
16
- before(:each) do
17
- # create a fresh but dumb grammar file for each example
18
- @test_base = "dumb-#{rand(1000)}"
19
- @test_path = "#{@tmpdir}/#{@test_base}"
20
- @test_grammar = "#{@test_path}.tt"
21
- @test_ruby = "#{@test_path}.rb"
22
- File.open(@test_grammar, 'w+') do |f|
23
- f.print("# Encoding: UTF-8\n")
24
- f.print("grammar Dumb\n")
25
- f.print("end\n")
26
- end unless File.exists?(@test_grammar)
27
- end
28
-
29
- after(:each) do
30
- # cleanup test grammar and parser output files
31
- File.delete(@test_grammar) if File.exists?(@test_grammar)
32
- File.delete(@test_ruby) if File.exists?(@test_ruby)
33
- end
34
-
35
- it 'can compile a grammar file' do
36
- # puts %q{emulate 'tt dumb.tt'}
37
- system("ruby -S tt #{@test_grammar}").should be_truthy
38
-
39
- File.exists?(@test_ruby).should be_truthy
40
- File.zero?(@test_ruby).should_not be_truthy
41
- end
42
-
43
- it 'can compile a relative pathed grammar file' do
44
- dir = File.basename(File.expand_path(File.dirname(@test_grammar)))
45
-
46
- # puts %q{emulate 'tt "../<current_dir>/dumb.tt"'}
47
- system("cd #{@tmpdir}/..; ruby -S tt \"./#{dir}/#{@test_base}.tt\"").should be_truthy
48
-
49
- File.exists?(@test_ruby).should be_truthy
50
- File.zero?(@test_ruby).should_not be_truthy
51
- end
52
-
53
- it 'can compile an absolute pathed grammar file' do
54
- # puts %q{emulate 'tt "/path/to/dumb.tt"'}
55
- system("ruby -S tt \"#{File.expand_path(@test_grammar)}\"").should be_truthy
56
-
57
- File.exists?(@test_ruby).should be_truthy
58
- File.zero?(@test_ruby).should_not be_truthy
59
- end
60
-
61
- it 'can compile without explicit file extensions' do
62
- # puts %q{emulate 'tt dumb'}
63
- system("ruby -S tt #{@test_path}").should be_truthy
64
-
65
- File.exists?(@test_ruby).should be_truthy
66
- File.zero?(@test_ruby).should_not be_truthy
67
- end
68
-
69
- it 'skips nonexistent grammar file without failing or creating bogus output' do
70
- # puts %q{emulate 'tt dumb.bad'}
71
- Kernel.open("|ruby -S tt #{@test_base}.bad") do |io|
72
- (io.read =~ /ERROR.*?not exist.*?continuing/).should_not be_nil
73
- end
74
-
75
- File.exists?("#{@test_base}.rb").should be_falsey
76
- end
77
-
78
- it 'can compile to a specified parser source file' do
79
- # puts %q{emulate 'tt -o my_dumb_test_parser.rb dumb'}
80
- pf = "#{@tmpdir}/my_dumb_test_parser.rb"
81
- begin
82
- system("ruby -S tt -o #{pf} #{@test_path}").should be_truthy
83
-
84
- File.exists?(pf).should be_truthy
85
- File.zero?(pf).should_not be_truthy
86
- ensure
87
- File.delete(pf) if File.exists?(pf)
88
- end
89
- end
90
-
91
- it 'by default, does not overwrite an existing file without an autogenerated header' do
92
- # puts %q{emulate 'tt -o must_save_parser.rb dumb'}
93
- pf = "#{@tmpdir}/must_save_parser.rb"
94
- begin
95
- system("ruby -S tt -o #{pf} #{@test_path}").should be_truthy
96
-
97
- File.exists?(pf).should be_truthy
98
- File.zero?(pf).should_not be_truthy
99
-
100
- # Check that the magic comment is preserved:
101
- written = File.open(pf, "r") { |f| s = f.read }
102
- written.should =~ /\A# Encoding: UTF-8/
103
-
104
- # Modify the file's auto-generated comment and make sure it doesn't get overwritten:
105
- written.sub!(/generated/, 'broken');
106
- File.open(pf, "w") { |f| f.write(written) }
107
- # File.open(pf, "r+") { |f| s = f.read; s.sub!(/generated/, 'broken'); f.rewind; f.write(s) }
108
- orig_file_hash = Digest::SHA1.hexdigest(File.read(pf))
109
-
110
- Kernel.open("|ruby -S tt -o #{pf} #{@test_path}") do |io|
111
- (io.read =~ /ERROR.*?already exists.*?skipping/).should_not be_nil
112
- end
113
-
114
- Digest::SHA1.hexdigest(File.read(pf)).should == orig_file_hash
115
- ensure
116
- File.delete(pf) if File.exists?(pf)
117
- end
118
- end
119
-
120
- it 'by default, overwrites a changed file with an intact autogenerated header' do
121
- # puts %q{emulate 'tt -o must_save_parser.rb dumb'}
122
- pf = "#{@tmpdir}/must_save_parser.rb"
123
- begin
124
- system("ruby -S tt -o #{pf} #{@test_path}").should be_truthy
125
-
126
- File.exists?(pf).should be_truthy
127
- File.zero?(pf).should_not be_truthy
128
- orig_file_hash = Digest::SHA1.hexdigest(File.read(pf))
129
-
130
- # Modify the file and make sure it gets reverted:
131
- File.open(pf, "r+") { |f| f.gets; f.write("#") }
132
-
133
- system("ruby -S tt -o #{pf} #{@test_path}").should be_truthy
134
- Digest::SHA1.hexdigest(File.read(pf)).should == orig_file_hash
135
- ensure
136
- File.delete(pf) if File.exists?(pf)
137
- end
138
- end
139
-
140
- it 'can be forced to overwrite existing file #{@test_path}' do
141
- pf = "#{@test_path}.rb"
142
- system("echo some junk >#{pf}").should be_truthy
143
-
144
- File.exists?(pf).should be_truthy
145
- File.zero?(pf).should_not be_truthy
146
- orig_file_hash = Digest::SHA1.hexdigest(File.read(pf))
147
-
148
- system("ruby -S tt -f #{@test_path}").should be_truthy
149
- Digest::SHA1.hexdigest(File.read(pf)).should_not == orig_file_hash
150
- end
151
-
152
- end
153
-
154
- context 'when processing multiple grammar files' do
155
-
156
- before(:each) do
157
- # provide fresh but dumb grammar files for each test
158
- @test_bases = []
159
- @test_grammars = []
160
-
161
- %w[dumb1 dumb2].each do |e|
162
- base = "#{@tmpdir}/#{e}-#{rand(1000)}"
163
- grammar_file = "#{base}.tt"
164
- @test_bases << base
165
- @test_grammars << grammar_file
166
-
167
- File.open(grammar_file, 'w+') do |f|
168
- f.print("grammar #{e.capitalize}\n")
169
- f.print("end\n")
170
- end unless File.exists?(grammar_file)
171
- end
172
- end
173
-
174
- after(:each) do
175
- # cleanup test grammar and output parser files
176
- @test_grammars.each { |f| File.delete(f) if File.exists?(f) }
177
- @test_bases.each { |f| File.delete("#{f}.rb") if File.exists?("#{f}.rb") }
178
- end
179
-
180
- it 'can compile them in one invocation' do
181
- # puts %q{emulate 'tt dumb1.tt dumb2.tt'}
182
- system("ruby -S tt #{@test_grammars.join(' ')}").should be_truthy
183
-
184
- @test_bases.each do |f|
185
- pf = "#{f}.rb"
186
- File.exists?(pf).should be_truthy
187
- File.zero?(pf).should_not be_truthy
188
- end
189
- end
190
-
191
- it 'can compile them without explicit file extenstions' do
192
- # puts %q{emulate 'tt dumb1 dumb2'}
193
- system("ruby -S tt #{@test_bases.join(' ')}").should be_truthy
194
-
195
- @test_bases.each do |f|
196
- pf = "#{f}.rb"
197
- File.exists?(pf).should be_truthy
198
- File.zero?(pf).should_not be_truthy
199
- end
200
- end
201
-
202
- it 'can skip nonexistent and invalid extension named grammar files' do
203
- # puts %q{emulate 'tt not_here bad_ext.ttg dumb1 dumb2'}
204
- system("ruby -S tt not_here bad_ext.ttg #{@test_bases.join(' ')} >/dev/null 2>&1").should be_truthy
205
-
206
- File.exists?('not_here.rb').should_not be_truthy
207
- File.exists?('bad_ext.rb').should_not be_truthy
208
-
209
- @test_bases.each do |f|
210
- pf = "#{f}.rb"
211
- File.exists?(pf).should be_truthy
212
- File.zero?(pf).should_not be_truthy
213
- end
214
- end
215
-
216
- it 'can not specify an output file' do
217
- # puts %q{emulate 'tt -o my_bogus_test_parser.rb dumb1 dumb2'}
218
- pf = 'my_bogus_test_parser.rb'
219
- system("ruby -S tt -o #{pf} #{@test_bases.join(' ')} >/dev/null 2>&1").should be_falsey
220
- File.exists?(pf).should be_falsey
221
- end
222
- end
223
-
224
- end