treetop 1.4.1 → 1.4.2

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.
data/bin/tt CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'optparse'
3
3
  require 'rubygems'
4
- gem 'treetop'
4
+ require 'treetop'
5
5
 
6
6
  $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
7
7
  require 'treetop'
@@ -19,129 +19,3 @@ If a grammar by the name of `Foo` is defined, the compiled Ruby source will defi
19
19
  else
20
20
  puts 'failure'
21
21
  end
22
-
23
- ##Defining Grammars Directly in Ruby
24
- It is possible to define parser directly in Ruby source file.
25
-
26
- ###Grammars
27
- Defining parsers in Ruby code is as much similar to original definition as it is possible. To create a grammar just write:
28
-
29
- include Treetop::Syntax
30
- grammar :Foo do
31
- end
32
- parser = FooParser.new
33
-
34
- Treetop will automatically compile and load it into memory, thus an instance of `FooParser` can be created.
35
-
36
- ###Syntactic Recognition
37
- To create a rule inside of a grammar simply write:
38
-
39
- include Treetop::Syntax
40
- grammar :Foo do
41
- rule :bar do
42
- ...
43
- end
44
- end
45
-
46
- Inside the rule any of Treetop syntactic elements can be used. Each element of a rule is created with standard Ruby classes: Strings act as Terminals, Symbols stand for Nonterminals, Arrays are sequences, Regexps are character classes.
47
-
48
- _Note: it is better not to use Numbers, as terminal symbols; use Strings instead._
49
-
50
- Sequences can be defined as follows:
51
-
52
- rule :sequence do
53
- [ "foo", "bar", "baz" ]
54
- end
55
-
56
- Ordered choices use `/` operator:
57
-
58
- rule :choice do
59
- "foo" / "bar"
60
- end
61
-
62
- Sequences have higher precedence than choices, so choices must be parenthesized to be used as the elements of a sequence. For example:
63
-
64
- rule :nested do
65
- ["foo", "bar", "baz" / "bop" ] # -> "foo" "bar" ( "baz" / "bop" )
66
- end
67
-
68
- Special operators like `!`, `&`, `?`, `+` and `*` are available through methods (all of the methods return element itself so calls can be chained) of elements in a rule:
69
-
70
- Op. | Method
71
- -----------
72
- ! | bang
73
- & | amper
74
- ? | mark
75
- + | plus
76
- * | kleene
77
-
78
- For example grammar:
79
-
80
- grammar :Foo do
81
- rule :bar do
82
- [ "baz" / "bop" ].kleene
83
- end
84
- end
85
-
86
- can generate any word that contain words "bar" and "bop".
87
-
88
- ###Semantic Interpretation
89
-
90
- Syntax node declaration can be added by `node` method (which may be called the same as operators above):
91
-
92
- grammar :Parens do
93
- rule :parenthesized_letter do
94
- ([ '(', :parenthesized_letter, ')'] / /[a-z]/ ).node(:ParenNode)
95
- end
96
- end
97
-
98
- It is also possible to add inline blocks of code. They are in fact strings strictly inserted into generated grammar:
99
-
100
- grammar :Parens do
101
- rule :parenthesized_letter do
102
- (['(', :parenthesized_letter, ')'] / /[a-z]/ ).block(%{
103
- def depth
104
- if nonterminal?
105
- parenthesized_letter.depth + 1
106
- else
107
- 0
108
- end
109
- end
110
- })
111
- end
112
- end
113
-
114
- Labels in rule definitions can be written as follow (example taken from documentation):
115
-
116
- rule :labels do
117
- [/[a-z]/.label(:first_letter), [', ', /[a-z]/.kleene.label(:letter)].label(:rest_letters)].block(%{
118
- ...
119
- })
120
- end
121
-
122
- ###Composition
123
-
124
- Inclusion of a grammar works thanks to `include` function call inside the grammar definition:
125
-
126
- grammar :One do
127
- rule :a do
128
- foo"
129
- end
130
-
131
- rule :b do
132
- "baz"
133
- end
134
- end
135
-
136
- grammar :Two do
137
- include :One
138
- rule :a do
139
- :super / "bar" / :c
140
- end
141
-
142
- rule :c do
143
- :b
144
- end
145
- end
146
-
147
- Grammar Two can generate `"foo"`, `"bar"` and `"baz"` words.
@@ -4,10 +4,9 @@ module Treetop
4
4
  def compile(address, builder, parent_expression = nil)
5
5
  super
6
6
  builder.if__ "index < input_length" do
7
- builder << 'next_character = index + input[index..-1].match(/\A(.)/um).end(1)'
8
- assign_result "instantiate_node(#{node_class_name},input, index...next_character)"
7
+ assign_result "instantiate_node(#{node_class_name},input, index...(index + 1))"
9
8
  extend_result_with_inline_module
10
- builder << "@index = next_character"
9
+ builder << "@index += 1"
11
10
  end
12
11
  builder.else_ do
13
12
  builder << 'terminal_parse_failure("any character")'
@@ -5,14 +5,13 @@ module Treetop
5
5
  super
6
6
 
7
7
  builder.if__ "has_terminal?(#{grounded_regexp(text_value)}, true, index)" do
8
- builder << 'next_character = index + input[index..-1].match(/\A(.)/um).end(1)'
9
8
  if address == 0 || decorated?
10
- assign_result "instantiate_node(#{node_class_name}, input, index...next_character)"
9
+ assign_result "instantiate_node(#{node_class_name},input, index...(index + 1))"
11
10
  extend_result_with_inline_module
12
11
  else
13
12
  assign_lazily_instantiated_node
14
13
  end
15
- builder << "@index = next_character"
14
+ builder << "@index += 1"
16
15
  end
17
16
  builder.else_ do
18
17
  # "terminal_parse_failure(#{single_quote(characters)})"
@@ -53,10 +53,10 @@ module Treetop
53
53
  def compile(index, builder, rule)
54
54
  super
55
55
  builder.module_declaration(module_name) do
56
- elements_by_name = sequence_elements.inject({}){|h,e| (h[e.label_name] ||= []) << e; h}
56
+ elements_by_name = sequence_elements.inject({}){|h,e| (h[e.label_name.to_s] ||= []) << e; h}
57
57
  sequence_elements.each_with_index do |element, index|
58
58
  if element.label_name
59
- repetitions = elements_by_name[element.label_name]
59
+ repetitions = elements_by_name[element.label_name.to_s]
60
60
  label_name = element.label_name + (repetitions.size > 1 ? (repetitions.index(element)+1).to_s : "")
61
61
  builder.method_declaration(label_name) do
62
62
  builder << "elements[#{index}]"
@@ -8,7 +8,7 @@ class String
8
8
  index + 1
9
9
  end
10
10
  end
11
-
11
+
12
12
  def line_of(index)
13
13
  self[0...index].count("\n") + 1
14
14
  end
@@ -36,33 +36,7 @@ class String
36
36
  end
37
37
  end
38
38
 
39
- def indent_paragraph(n)
40
- out = ""
41
- self.each_line {|line| out += line.indent(n) }
42
- out
43
- end
44
-
45
- # Removes indentation uniformly.
46
- def justify
47
- min = self.length
48
- self.each_line {|line|
49
- next if line.strip == ""
50
- if line =~ /^( *)\S/
51
- min = $1.length if min > $1.length
52
- else
53
- min = 0
54
- end
55
- }
56
- out = ""
57
- self.each_line {|line| out += line.slice(min...line.length) || "\n" }
58
- out.strip
59
- end
60
-
61
39
  def treetop_camelize
62
40
  to_s.gsub(/\/(.?)/){ "::" + $1.upcase }.gsub(/(^|_)(.)/){ $2.upcase }
63
41
  end
64
-
65
- def to_tt
66
- "'#{self}'"
67
- end
68
- end
42
+ end
@@ -1,4 +1,2 @@
1
1
  dir = File.dirname(__FILE__)
2
- Dir.glob("#{dir}/ruby_extensions/*.rb").each do |file|
3
- require file
4
- end
2
+ require "#{dir}/ruby_extensions/string"
@@ -88,7 +88,7 @@ module Treetop
88
88
 
89
89
  def has_terminal?(terminal, regex, index)
90
90
  if regex
91
- rx = @regexps[terminal] ||= Regexp.new(terminal, nil, 'u')
91
+ rx = @regexps[terminal] ||= Regexp.new(terminal)
92
92
  input.index(rx, index) == index
93
93
  else
94
94
  input[index, terminal.size] == terminal
@@ -2,7 +2,7 @@ module Treetop #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 1
4
4
  MINOR = 4
5
- TINY = 1
5
+ TINY = 2
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/lib/treetop.rb CHANGED
@@ -11,7 +11,6 @@ TREETOP_ROOT = File.join(dir, 'treetop')
11
11
  require File.join(TREETOP_ROOT, "ruby_extensions")
12
12
  require File.join(TREETOP_ROOT, "runtime")
13
13
  require File.join(TREETOP_ROOT, "compiler")
14
- require File.join(TREETOP_ROOT, "syntax")
15
14
 
16
15
  require 'polyglot'
17
16
  Polyglot.register(Treetop::VALID_GRAMMAR_EXT, Treetop)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: treetop
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 1.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Sobo
@@ -9,7 +9,7 @@ autorequire: treetop
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-09-04 00:00:00 +10:00
12
+ date: 2009-09-11 00:00:00 +10:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -61,12 +61,7 @@ files:
61
61
  - lib/treetop/compiler/node_classes.rb
62
62
  - lib/treetop/compiler/ruby_builder.rb
63
63
  - lib/treetop/compiler.rb
64
- - lib/treetop/ruby_extensions/array.rb
65
- - lib/treetop/ruby_extensions/nil.rb
66
- - lib/treetop/ruby_extensions/object.rb
67
- - lib/treetop/ruby_extensions/regexp.rb
68
64
  - lib/treetop/ruby_extensions/string.rb
69
- - lib/treetop/ruby_extensions/symbol.rb
70
65
  - lib/treetop/ruby_extensions.rb
71
66
  - lib/treetop/runtime/compiled_parser.rb
72
67
  - lib/treetop/runtime/interval_skip_list/head_node.rb
@@ -78,7 +73,6 @@ files:
78
73
  - lib/treetop/runtime/terminal_parse_failure_debug.rb
79
74
  - lib/treetop/runtime/terminal_syntax_node.rb
80
75
  - lib/treetop/runtime.rb
81
- - lib/treetop/syntax.rb
82
76
  - lib/treetop/version.rb
83
77
  - lib/treetop.rb
84
78
  - bin/tt
@@ -101,8 +95,6 @@ files:
101
95
  - examples/lambda_calculus/lambda_calculus_node_classes.rb
102
96
  - examples/lambda_calculus/lambda_calculus_test.rb
103
97
  - examples/lambda_calculus/test_helper.rb
104
- - examples/ruby_syntax/syntax_test.rb
105
- - examples/ruby_syntax/test_helper.rb
106
98
  has_rdoc: true
107
99
  homepage: http://functionalform.blogspot.com
108
100
  licenses: []
@@ -1,105 +0,0 @@
1
- dir = File.dirname(__FILE__)
2
- require File.expand_path("#{dir}/test_helper")
3
-
4
- class SyntaxTest < Test::Unit::TestCase
5
- include Treetop::Syntax
6
- include SyntaxTestHelper
7
-
8
- def test_simple
9
- assert_grammar {
10
- grammar :OnlyGrammar do
11
- end
12
- }
13
- end
14
-
15
- def test_rules
16
- assert_grammar {
17
- grammar :Simple do
18
- rule :foo do
19
- ["foo", :bar]
20
- end
21
-
22
- rule :bar do
23
- "bar" / "baz"
24
- end
25
- end
26
- }
27
- parse('foobar')
28
- parse('foobaz')
29
- end
30
-
31
- def test_nested
32
- assert_grammar {
33
- grammar :Nested do
34
- rule :nested do
35
- ["foo", "bar", "baz" / "bop"]
36
- end
37
- end
38
- }
39
- parse('foobarbaz')
40
- parse('foobarbop')
41
- end
42
-
43
- def test_operators
44
- assert_grammar {
45
- grammar :Kleene do
46
- rule :Kleene do
47
- "foo".kleene
48
- end
49
- end
50
- }
51
- parse("")
52
- parse("foo")
53
- parse("foofoo")
54
-
55
- assert_grammar {
56
- grammar :Plus do
57
- rule :Plus do
58
- "foo".plus
59
- end
60
- end
61
- }
62
- parse("foo")
63
- parse("foofoo")
64
-
65
- assert_grammar {
66
- grammar :Optional do
67
- rule :Optional do
68
- "foo".mark
69
- end
70
- end
71
- }
72
- parse("")
73
- parse("foo")
74
- end
75
-
76
- def test_inclusion
77
- assert_grammar {
78
- grammar :One do
79
- rule :a do
80
- "foo"
81
- end
82
-
83
- rule :b do
84
- "baz"
85
- end
86
- end
87
- }
88
-
89
- assert_grammar {
90
- grammar :Two do
91
- include :One
92
- rule :a do
93
- :super / "bar" / :c
94
- end
95
-
96
- rule :c do
97
- :b
98
- end
99
- end
100
- }
101
- parse("foo")
102
- parse("bar")
103
- parse("baz")
104
- end
105
- end
@@ -1,28 +0,0 @@
1
- require 'test/unit'
2
- require 'rubygems'
3
- require 'treetop'
4
-
5
- dir = File.dirname(__FILE__)
6
- require File.expand_path("#{dir}/../../lib/treetop/ruby_extensions")
7
- require File.expand_path("#{dir}/../../lib/treetop/syntax")
8
-
9
- module SyntaxTestHelper
10
- def assert_grammar
11
- g = yield
12
- assert_not_nil g
13
- flunk "Badly generated parser" unless g
14
- @parser = eval("#{g}.new")
15
- end
16
-
17
- def parse(input)
18
- result = @parser.parse(input)
19
- unless result
20
- puts @parser.terminal_failures.join("\n")
21
- end
22
- assert_not_nil result
23
- if result
24
- assert_equal input, result.text_value
25
- end
26
- result
27
- end
28
- end
@@ -1,22 +0,0 @@
1
- class Array
2
- def join_with(method, pattern = "")
3
- return join(pattern) unless method
4
- return "" if self.length == 0
5
-
6
- args = []
7
- if method.respond_to? :to_hash
8
- args = method[:args] || []
9
- method = method[:name]
10
- end
11
-
12
- output = self[0].send(method, *args)
13
- for i in (1...self.length)
14
- output += pattern + self[i].send(method, *args)
15
- end
16
- output
17
- end
18
-
19
- def to_tt
20
- self.join_with({:name => :seq_to_tt, :args => [true]}, " ")
21
- end
22
- end
@@ -1,5 +0,0 @@
1
- class NilClass
2
- def to_tt
3
- ""
4
- end
5
- end
@@ -1,57 +0,0 @@
1
- class Object
2
- def sequence
3
- @sequence ||= []
4
- end
5
-
6
- def /(other)
7
- sequence.push(other)
8
- self
9
- end
10
-
11
- def seq_to_tt(inline = false)
12
- separator = inline ? " / " : "\n/\n"
13
- tt = if sequence.length == 0
14
- self.to_tt
15
- else
16
- output = self.to_tt + separator + sequence.join_with({:name => :seq_to_tt, :args => [true]}, separator)
17
- output = "( #{output} )" if inline
18
- output
19
- end
20
-
21
- # Operators
22
- tt = "&" + tt if @amper
23
- tt = "!" + tt if @bang
24
- tt += "*" if @kleene
25
- tt += "+" if @plus
26
- tt += "?" if @mark
27
-
28
- tt += " <#{@node.to_s}>" if @node
29
- tt += " {\n#{@block.gsub("\t", " ").justify.indent_paragraph(2)}\n}" if @block
30
- tt = @label.to_s + ':' + tt if @label
31
- tt
32
- end
33
-
34
- def node(name)
35
- @node = name
36
- self
37
- end
38
-
39
- def block(content)
40
- @block = content
41
- self
42
- end
43
-
44
- def label(name)
45
- @label = name
46
- self
47
- end
48
-
49
- [:mark, :kleene, :plus, :amper, :bang].each do |sym|
50
- Object.class_eval(%{
51
- def #{sym.to_s}
52
- @#{sym.to_s} = true
53
- self
54
- end
55
- })
56
- end
57
- end
@@ -1,5 +0,0 @@
1
- class Regexp
2
- def to_tt
3
- self.inspect
4
- end
5
- end
@@ -1,5 +0,0 @@
1
- class Symbol
2
- def to_tt
3
- self.to_s
4
- end
5
- end
@@ -1,39 +0,0 @@
1
- =begin rdoc
2
- Definition of TreeTop syntax in pure Ruby.
3
- =end
4
-
5
- module Treetop
6
- # Provides the possibility to write Treetop syntax as a Ruby code.
7
- # Symbols act as nonterminals, strings as terminals, arrays as
8
- # sequences. Ordered choices are defined similar to original Treetop
9
- # syntax.
10
- #
11
- # (Note: it is better not to use numbers; use Strings instead)
12
- #
13
- module Syntax
14
- class Grammar
15
- attr_reader :source
16
- def initialize
17
- @source = ""
18
- end
19
-
20
- def rule(name)
21
- @source += "rule #{name.to_s}\n#{yield.seq_to_tt.indent_paragraph(2)}\nend\n"
22
- end
23
-
24
- def include(name)
25
- @source += "include #{name.to_s}\n"
26
- end
27
- end
28
-
29
- def grammar(name, &block)
30
- Syntax.grammar(name, &block)
31
- end
32
-
33
- def self.grammar(name, &block)
34
- (g = Grammar.new).instance_eval(&block)
35
- source = "grammar #{name.to_s}\n#{g.source.indent_paragraph(2)}end\n"
36
- Treetop.load_from_string(source)
37
- end
38
- end
39
- end