treetop 1.4.15 → 1.5.1

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.
@@ -389,19 +389,19 @@ module Treetop
389
389
  end
390
390
 
391
391
  rule quoted_string
392
- (single_quoted_string / double_quoted_string) {
392
+ qs:(single_quoted_string / double_quoted_string) insens:'i'? <Terminal> {
393
393
  def string
394
- super.text_value
394
+ qs.text_value
395
395
  end
396
396
  }
397
397
  end
398
398
 
399
399
  rule double_quoted_string
400
- '"' string:(!'"' ("\\\\" / '\"' / .))* '"' <Terminal>
400
+ '"' string:(!'"' ("\\\\" / '\"' / .))* '"'
401
401
  end
402
402
 
403
403
  rule single_quoted_string
404
- "'" string:(!"'" ("\\\\" / "\\'" / .))* "'" <Terminal>
404
+ "'" string:(!"'" ("\\\\" / "\\'" / .))* "'"
405
405
  end
406
406
 
407
407
  rule character_class
@@ -4,8 +4,12 @@ module Treetop
4
4
  def compile(address, builder, parent_expression = nil)
5
5
  super
6
6
  builder.if__ "index < input_length" do
7
- assign_result "instantiate_node(#{node_class_name},input, index...(index + 1))"
8
- extend_result_with_inline_module
7
+ if address == 0 || decorated?
8
+ assign_result "instantiate_node(#{node_class_name},input, index...(index + 1))"
9
+ extend_result_with_inline_module
10
+ else
11
+ assign_lazily_instantiated_node
12
+ end
9
13
  builder << "@index += 1"
10
14
  end
11
15
  builder.else_ do
@@ -15,4 +19,4 @@ module Treetop
15
19
  end
16
20
  end
17
21
  end
18
- end
22
+ end
@@ -3,8 +3,8 @@ module Treetop
3
3
  class CharacterClass < AtomicExpression
4
4
  def compile(address, builder, parent_expression = nil)
5
5
  super
6
-
7
- builder.if__ "has_terminal?(#{grounded_regexp(text_value)}, true, index)" do
6
+
7
+ builder.if__ "has_terminal?(@regexps[gr = #{grounded_regexp(text_value)}] ||= Regexp.new(gr), :regexp, index)" do
8
8
  if address == 0 || decorated?
9
9
  assign_result "instantiate_node(#{node_class_name},input, index...(index + 1))"
10
10
  extend_result_with_inline_module
@@ -13,6 +13,8 @@ module Treetop
13
13
  obtain_new_subexpression_address
14
14
  alternatives.first.compile(subexpression_address, builder)
15
15
  builder.if__ subexpression_success? do
16
+ # Undo lazy instantiation:
17
+ builder << "#{subexpression_result_var} = SyntaxNode.new(input, (index-1)...index) if #{subexpression_result_var} == true"
16
18
  assign_result subexpression_result_var
17
19
  extend_result_with_declared_module
18
20
  extend_result_with_inline_module
@@ -28,4 +30,4 @@ module Treetop
28
30
  end
29
31
  end
30
32
  end
31
- end
33
+ end
@@ -33,9 +33,11 @@ module Treetop
33
33
 
34
34
  def generate_cache_lookup(builder)
35
35
  builder.if_ "node_cache[:#{name}].has_key?(index)" do
36
- builder.assign 'cached', "node_cache[:#{name}][index]"
36
+ cache_address = "node_cache[:#{name}][index]"
37
+ builder.assign 'cached', cache_address
37
38
  builder.if_ "cached" do
38
- builder << 'cached = SyntaxNode.new(input, index...(index + 1)) if cached == true'
39
+ # Handle lazily instantiated nodes:
40
+ builder << "#{cache_address} = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true"
39
41
  builder << '@index = cached.interval.end'
40
42
  end
41
43
  builder << 'return cached'
@@ -3,15 +3,21 @@ module Treetop
3
3
  class Terminal < AtomicExpression
4
4
  def compile(address, builder, parent_expression = nil)
5
5
  super
6
- string_length = eval(text_value).length
7
-
8
- builder.if__ "has_terminal?(#{text_value}, false, index)" do
9
- assign_result "instantiate_node(#{node_class_name},input, index...(index + #{string_length}))"
10
- extend_result_with_inline_module
6
+ insensitive = insens.text_value.length > 0
7
+ str = insensitive ? string.downcase : string
8
+ string_length = eval(str).length
9
+
10
+ builder.if__ "has_terminal?(#{str}, #{insensitive ? ':insens' : false}, index)" do
11
+ if address == 0 || decorated? || string_length > 1
12
+ assign_result "instantiate_node(#{node_class_name},input, index...(index + #{string_length}))"
13
+ extend_result_with_inline_module
14
+ else
15
+ assign_lazily_instantiated_node
16
+ end
11
17
  builder << "@index += #{string_length}"
12
18
  end
13
19
  builder.else_ do
14
- builder << "terminal_parse_failure(#{text_value})"
20
+ builder << "terminal_parse_failure(#{str})"
15
21
  assign_result 'nil'
16
22
  end
17
23
  end
@@ -92,12 +92,17 @@ module Treetop
92
92
  end
93
93
  end
94
94
 
95
- def has_terminal?(terminal, regex, index)
96
- if regex
95
+ def has_terminal?(terminal, mode, index)
96
+ case mode
97
+ when :regexp # A Regexp has been passed in, probably a character class
98
+ input.index(terminal, index) == index
99
+ when false # The terminal is a string which must match exactly
100
+ input[index, terminal.size] == terminal
101
+ when :insens # The terminal is a downcased string which must match input downcased
102
+ input[index, terminal.size].downcase == terminal
103
+ when true # Only occurs with old compiled grammars, for character classes
97
104
  rx = @regexps[terminal] ||= Regexp.new(terminal)
98
105
  input.index(rx, index) == index
99
- else
100
- input[index, terminal.size] == terminal
101
106
  end
102
107
  end
103
108
 
@@ -1,8 +1,8 @@
1
1
  module Treetop #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 1
4
- MINOR = 4
5
- TINY = 15
4
+ MINOR = 5
5
+ TINY = 1
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -228,19 +228,19 @@ module CharacterClassSpec
228
228
  end
229
229
 
230
230
  describe "a character class mixed with other expressions" do
231
- testing_expression '[A-Z] "a"'
231
+ testing_expression '[A-Z] "a" "bc"'
232
232
  it "lazily instantiates a node for the character" do
233
- result = parse('Aa')
233
+ result = parse('Aabc')
234
234
  result.instance_variable_get("@elements").should include(true)
235
235
  result.elements.should_not include(true)
236
- result.elements.size.should == 2
236
+ result.elements.size.should == 3
237
237
  end
238
238
  end
239
239
 
240
240
  describe "a character class with a node class declaration mixed with other expressions" do
241
- testing_expression '([A-Z] <CharacterClassSpec::Foo>) "a"'
241
+ testing_expression '([A-Z] <CharacterClassSpec::Foo>) "ab"'
242
242
  it "actively generates a node for the character because it has a node class declared" do
243
- result = parse('Aa')
243
+ result = parse('Aab')
244
244
  result.instance_variable_get("@elements").should_not include(true)
245
245
  result.elements.should_not include(true)
246
246
  result.elements.size.should == 2
@@ -248,9 +248,9 @@ module CharacterClassSpec
248
248
  end
249
249
 
250
250
  describe "a character class with a node module declaration mixed with other expressions" do
251
- testing_expression '([A-Z] <CharacterClassSpec::ModFoo>) "a"'
251
+ testing_expression '([A-Z] <CharacterClassSpec::ModFoo>) "ab"'
252
252
  it "actively generates a node for the character because it has a node module declared" do
253
- result = parse('Aa')
253
+ result = parse('Aab')
254
254
  result.instance_variable_get("@elements").should_not include(true)
255
255
  result.elements.should_not include(true)
256
256
  result.elements.size.should == 2
@@ -258,9 +258,9 @@ module CharacterClassSpec
258
258
  end
259
259
 
260
260
  describe "a character class with an inline block mixed with other expressions" do
261
- testing_expression '([A-Z] { def a_method; end }) "a"'
261
+ testing_expression '([A-Z] { def a_method; end }) "ab"'
262
262
  it "actively generates a node for the character because it has an inline block" do
263
- result = parse('Aa')
263
+ result = parse('Aab')
264
264
  result.instance_variable_get("@elements").should_not include(true)
265
265
  result.elements.should_not include(true)
266
266
  result.elements.size.should == 2
@@ -268,28 +268,28 @@ module CharacterClassSpec
268
268
  end
269
269
 
270
270
  describe "a character class with a label mixed with other expressions" do
271
- testing_expression 'upper:([A-Z]) "b"'
271
+ testing_expression 'upper:([A-Z]) "b" "cd"'
272
272
  it "returns the correct element for the labeled expression" do
273
- result = parse('Ab')
273
+ result = parse('Abcd')
274
274
  result.upper.text_value.should == "A"
275
- result.elements.size.should == 2
275
+ result.elements.size.should == 3
276
276
  end
277
277
  end
278
278
 
279
279
  describe "a character class repetition mixed with other expressions" do
280
- testing_expression '[A-Z]+ "a"'
280
+ testing_expression '[A-Z]+ "a" "bc"'
281
281
  it "lazily instantiates a node for the character" do
282
- result = parse('ABCa')
282
+ result = parse('ABCabc')
283
283
  result.elements[0].instance_variable_get("@elements").should include(true)
284
284
  result.elements[0].elements.should_not include(true)
285
285
  result.elements[0].elements.size.should == 3
286
- result.elements.size.should == 2
287
- result.elements.inspect.should == %Q{[SyntaxNode offset=0, "ABC":\n SyntaxNode offset=0, "A"\n SyntaxNode offset=1, "B"\n SyntaxNode offset=2, "C", SyntaxNode offset=3, "a"]}
286
+ result.elements.size.should == 3
287
+ result.elements.inspect.should == %Q{[SyntaxNode offset=0, "ABC":\n SyntaxNode offset=0, "A"\n SyntaxNode offset=1, "B"\n SyntaxNode offset=2, "C", SyntaxNode offset=3, "a", SyntaxNode offset=4, "bc"]}
288
288
  end
289
289
  end
290
290
 
291
291
  describe "a character class that gets cached because of a choice" do
292
- testing_expression "[A-Z] 'a' / [A-Z]"
292
+ testing_expression "[A-Z] 'a' 'bc' / [A-Z]"
293
293
 
294
294
  it "generates a node for the lazily-instantiated character when it is the primary node" do
295
295
  result = parse('A')
@@ -54,10 +54,10 @@ module ChoiceSpec
54
54
  end
55
55
 
56
56
  describe "A choice between terminals followed by a block" do
57
- testing_expression "('a'/ 'b' / 'c') { def a_method; end }"
57
+ testing_expression "('a'/ 'bb' / [c]) { def a_method; end }"
58
58
 
59
59
  it "extends a match of any of its subexpressions with a module created from the block" do
60
- ['a', 'b', 'c'].each do |letter|
60
+ ['a', 'bb', 'c'].each do |letter|
61
61
  parse(letter).should respond_to(:a_method)
62
62
  end
63
63
  end
@@ -69,10 +69,10 @@ module ChoiceSpec
69
69
  end
70
70
 
71
71
  describe "a choice followed by a declared module" do
72
- testing_expression "('a'/ 'b' / 'c') <ChoiceSpec::TestModule>"
72
+ testing_expression "('a'/ 'bb' / [c]) <ChoiceSpec::TestModule>"
73
73
 
74
74
  it "extends a match of any of its subexpressions with a module created from the block" do
75
- ['a', 'b', 'c'].each do |letter|
75
+ ['a', 'bb', 'c'].each do |letter|
76
76
  parse(letter).should respond_to(:a_method)
77
77
  end
78
78
  end
@@ -29,10 +29,10 @@ module NotPredicateSpec
29
29
  end
30
30
 
31
31
  describe "A !-predicated sequence" do
32
- testing_expression '!("a" "b" "c")'
32
+ testing_expression '!("a" "b" "cc")'
33
33
 
34
34
  it "fails to parse matching input" do
35
- parse('abc').should be_nil
35
+ parse('abcc').should be_nil
36
36
  end
37
37
  end
38
38
  end
@@ -5,7 +5,7 @@ module RepeatedSubruleSpec
5
5
  testing_grammar %{
6
6
  grammar Foo
7
7
  rule foo
8
- a:'a' space b:'b' space 'c'
8
+ a:'a' space b:'b' space 'cc'
9
9
  end
10
10
 
11
11
  rule space
@@ -15,7 +15,7 @@ module RepeatedSubruleSpec
15
15
  }
16
16
 
17
17
  it "should produce a parser having sequence-numbered node accessor methods" do
18
- parse("a b c") do |result|
18
+ parse("a b cc") do |result|
19
19
  result.should_not be_nil
20
20
  result.should respond_to(:space1)
21
21
  result.should respond_to(:space2)
@@ -4,6 +4,50 @@ module TerminalSymbolSpec
4
4
  class Foo < Treetop::Runtime::SyntaxNode
5
5
  end
6
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
+ end
22
+ end
23
+
24
+ it "fails to match the input string in the wrong case" do
25
+ parse "foo", :index => 0 do |result|
26
+ result.should be_nil
27
+ end
28
+ end
29
+ end
30
+
31
+ describe "a terminal symbol with case-insensitive matching" do
32
+ testing_expression "'Foo'i"
33
+
34
+ it "matches the input string in the same case" do
35
+ parse "Foo", :index => 0 do |result|
36
+ result.should_not be_nil
37
+ result.interval.should == (0...3)
38
+ result.text_value.should == 'Foo'
39
+ end
40
+ end
41
+
42
+ it "matches the input string in varied case" do
43
+ parse "foO", :index => 0 do |result|
44
+ result.should_not be_nil
45
+ result.interval.should == (0...3)
46
+ result.text_value.should == 'foO'
47
+ end
48
+ end
49
+ end
50
+
7
51
  describe "a terminal symbol followed by a node class declaration and a block" do
8
52
  testing_expression "'foo' <TerminalSymbolSpec::Foo> { def a_method; end }"
9
53
 
@@ -47,7 +47,7 @@ module ZeroOrMoreSpec
47
47
  end
48
48
 
49
49
  describe "Zero or more of a choice" do
50
- testing_expression '("a" / "b")*'
50
+ testing_expression '("a" / "bb")*'
51
51
 
52
52
  it "successfully parses matching input" do
53
53
  parse('abba').should_not be_nil
@@ -1,11 +1,11 @@
1
1
  module Test
2
2
  grammar B
3
3
  rule b
4
- 'b'
4
+ 'bb'
5
5
  end
6
6
 
7
7
  rule inherit
8
8
  super 'keyword'
9
9
  end
10
10
  end
11
- end
11
+ end
@@ -16,7 +16,7 @@ module GrammarCompositionSpec
16
16
  end
17
17
 
18
18
  specify "rules in C have access to rules defined in A and B" do
19
- @c.parse('abc').should_not be_nil
19
+ @c.parse('abbc').should_not be_nil
20
20
  end
21
21
 
22
22
  specify "rules in C can override rules in A and B with super semantics" do
@@ -33,7 +33,7 @@ module GrammarCompositionSpec
33
33
  end
34
34
 
35
35
  specify "rules in F have access to rule defined in E" do
36
- @f.parse('abcef').should_not be_nil
36
+ @f.parse('abbcef').should_not be_nil
37
37
  end
38
38
 
39
39
  end
@@ -11,7 +11,7 @@ module CompiledParserSpec
11
11
  end
12
12
 
13
13
  rule b
14
- 'b'
14
+ 'bb'
15
15
  end
16
16
  end
17
17
  }
@@ -25,7 +25,7 @@ module CompiledParserSpec
25
25
  parser.parse('b').should be_nil
26
26
 
27
27
  # Check that the temporary-override works:
28
- parser.parse('b', :root => :b).should_not be_nil
28
+ parser.parse('bb', :root => :b).should_not be_nil
29
29
  parser.parse('a', :root => :b).should be_nil
30
30
 
31
31
  # Check that the temporary-override isn't sticky:
@@ -33,7 +33,7 @@ module CompiledParserSpec
33
33
 
34
34
  # Try a permanent override:
35
35
  parser.root = :b
36
- parser.parse('b').should_not be_nil
36
+ parser.parse('bb').should_not be_nil
37
37
  parser.parse('a').should be_nil
38
38
  end
39
39
 
data/treetop.gemspec CHANGED
@@ -2,15 +2,17 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
+ # stub: treetop 1.5.1 ruby lib
5
6
 
6
7
  Gem::Specification.new do |s|
7
8
  s.name = "treetop"
8
- s.version = "1.4.15"
9
+ s.version = "1.5.1"
9
10
 
10
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
11
13
  s.authors = ["Nathan Sobo", "Clifford Heath"]
12
14
  s.autorequire = "treetop"
13
- s.date = "2013-08-17"
15
+ s.date = "2014-03-12"
14
16
  s.email = "cliffordheath@gmail.com"
15
17
  s.executables = ["tt"]
16
18
  s.extra_rdoc_files = [
@@ -136,41 +138,37 @@ Gem::Specification.new do |s|
136
138
  ]
137
139
  s.homepage = "https://github.com/cjheath/treetop"
138
140
  s.licenses = ["MIT"]
139
- s.require_paths = ["lib"]
140
- s.rubygems_version = "1.8.24"
141
+ s.rubygems_version = "2.2.2"
141
142
  s.summary = "A Ruby-based text parsing and interpretation DSL"
142
143
 
143
144
  if s.respond_to? :specification_version then
144
- s.specification_version = 3
145
+ s.specification_version = 4
145
146
 
146
147
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
147
- s.add_runtime_dependency(%q<polyglot>, [">= 0"])
148
- s.add_development_dependency(%q<jeweler>, [">= 0"])
149
- s.add_development_dependency(%q<activesupport>, [">= 0"])
150
- s.add_development_dependency(%q<i18n>, ["~> 0.5.0"])
148
+ s.add_runtime_dependency(%q<polyglot>, ["~> 0.3"])
149
+ s.add_development_dependency(%q<jeweler>, ["~> 2.0"])
150
+ s.add_development_dependency(%q<activesupport>, ["~> 4.0"])
151
+ s.add_development_dependency(%q<i18n>, ["~> 0.6"])
151
152
  s.add_development_dependency(%q<rr>, ["~> 1.0"])
152
- s.add_development_dependency(%q<rspec>, [">= 2.0.0"])
153
- s.add_development_dependency(%q<rake>, [">= 0"])
154
- s.add_runtime_dependency(%q<polyglot>, [">= 0.3.1"])
153
+ s.add_development_dependency(%q<rspec>, ["~> 2"])
154
+ s.add_development_dependency(%q<rake>, ["~> 10"])
155
155
  else
156
- s.add_dependency(%q<polyglot>, [">= 0"])
157
- s.add_dependency(%q<jeweler>, [">= 0"])
158
- s.add_dependency(%q<activesupport>, [">= 0"])
159
- s.add_dependency(%q<i18n>, ["~> 0.5.0"])
156
+ s.add_dependency(%q<polyglot>, ["~> 0.3"])
157
+ s.add_dependency(%q<jeweler>, ["~> 2.0"])
158
+ s.add_dependency(%q<activesupport>, ["~> 4.0"])
159
+ s.add_dependency(%q<i18n>, ["~> 0.6"])
160
160
  s.add_dependency(%q<rr>, ["~> 1.0"])
161
- s.add_dependency(%q<rspec>, [">= 2.0.0"])
162
- s.add_dependency(%q<rake>, [">= 0"])
163
- s.add_dependency(%q<polyglot>, [">= 0.3.1"])
161
+ s.add_dependency(%q<rspec>, ["~> 2"])
162
+ s.add_dependency(%q<rake>, ["~> 10"])
164
163
  end
165
164
  else
166
- s.add_dependency(%q<polyglot>, [">= 0"])
167
- s.add_dependency(%q<jeweler>, [">= 0"])
168
- s.add_dependency(%q<activesupport>, [">= 0"])
169
- s.add_dependency(%q<i18n>, ["~> 0.5.0"])
165
+ s.add_dependency(%q<polyglot>, ["~> 0.3"])
166
+ s.add_dependency(%q<jeweler>, ["~> 2.0"])
167
+ s.add_dependency(%q<activesupport>, ["~> 4.0"])
168
+ s.add_dependency(%q<i18n>, ["~> 0.6"])
170
169
  s.add_dependency(%q<rr>, ["~> 1.0"])
171
- s.add_dependency(%q<rspec>, [">= 2.0.0"])
172
- s.add_dependency(%q<rake>, [">= 0"])
173
- s.add_dependency(%q<polyglot>, [">= 0.3.1"])
170
+ s.add_dependency(%q<rspec>, ["~> 2"])
171
+ s.add_dependency(%q<rake>, ["~> 10"])
174
172
  end
175
173
  end
176
174