treetop 1.4.1 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
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