antlr3 1.2.3
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/ANTLR-LICENSE.txt +26 -0
- data/History.txt +66 -0
- data/README.txt +139 -0
- data/bin/antlr4ruby +33 -0
- data/java/RubyTarget.java +524 -0
- data/java/antlr-full-3.2.1.jar +0 -0
- data/lib/antlr3.rb +176 -0
- data/lib/antlr3/constants.rb +88 -0
- data/lib/antlr3/debug.rb +701 -0
- data/lib/antlr3/debug/event-hub.rb +210 -0
- data/lib/antlr3/debug/record-event-listener.rb +25 -0
- data/lib/antlr3/debug/rule-tracer.rb +55 -0
- data/lib/antlr3/debug/socket.rb +360 -0
- data/lib/antlr3/debug/trace-event-listener.rb +92 -0
- data/lib/antlr3/dfa.rb +247 -0
- data/lib/antlr3/dot.rb +174 -0
- data/lib/antlr3/error.rb +657 -0
- data/lib/antlr3/main.rb +561 -0
- data/lib/antlr3/modes/ast-builder.rb +41 -0
- data/lib/antlr3/modes/filter.rb +56 -0
- data/lib/antlr3/profile.rb +322 -0
- data/lib/antlr3/recognizers.rb +1280 -0
- data/lib/antlr3/streams.rb +985 -0
- data/lib/antlr3/streams/interactive.rb +91 -0
- data/lib/antlr3/streams/rewrite.rb +412 -0
- data/lib/antlr3/test/call-stack.rb +57 -0
- data/lib/antlr3/test/config.rb +23 -0
- data/lib/antlr3/test/core-extensions.rb +269 -0
- data/lib/antlr3/test/diff.rb +165 -0
- data/lib/antlr3/test/functional.rb +207 -0
- data/lib/antlr3/test/grammar.rb +371 -0
- data/lib/antlr3/token.rb +592 -0
- data/lib/antlr3/tree.rb +1415 -0
- data/lib/antlr3/tree/debug.rb +163 -0
- data/lib/antlr3/tree/visitor.rb +84 -0
- data/lib/antlr3/tree/wizard.rb +481 -0
- data/lib/antlr3/util.rb +149 -0
- data/lib/antlr3/version.rb +27 -0
- data/samples/ANTLRv3Grammar.g +621 -0
- data/samples/Cpp.g +749 -0
- data/templates/AST.stg +335 -0
- data/templates/ASTDbg.stg +40 -0
- data/templates/ASTParser.stg +153 -0
- data/templates/ASTTreeParser.stg +272 -0
- data/templates/Dbg.stg +192 -0
- data/templates/Ruby.stg +1514 -0
- data/test/functional/ast-output/auto-ast.rb +797 -0
- data/test/functional/ast-output/construction.rb +555 -0
- data/test/functional/ast-output/hetero-nodes.rb +753 -0
- data/test/functional/ast-output/rewrites.rb +1327 -0
- data/test/functional/ast-output/tree-rewrite.rb +1662 -0
- data/test/functional/debugging/debug-mode.rb +689 -0
- data/test/functional/debugging/profile-mode.rb +165 -0
- data/test/functional/debugging/rule-tracing.rb +74 -0
- data/test/functional/delegation/import.rb +379 -0
- data/test/functional/lexer/basic.rb +559 -0
- data/test/functional/lexer/filter-mode.rb +245 -0
- data/test/functional/lexer/nuances.rb +47 -0
- data/test/functional/lexer/properties.rb +104 -0
- data/test/functional/lexer/syn-pred.rb +32 -0
- data/test/functional/lexer/xml.rb +206 -0
- data/test/functional/main/main-scripts.rb +245 -0
- data/test/functional/parser/actions.rb +224 -0
- data/test/functional/parser/backtracking.rb +244 -0
- data/test/functional/parser/basic.rb +282 -0
- data/test/functional/parser/calc.rb +98 -0
- data/test/functional/parser/ll-star.rb +143 -0
- data/test/functional/parser/nuances.rb +165 -0
- data/test/functional/parser/predicates.rb +103 -0
- data/test/functional/parser/properties.rb +242 -0
- data/test/functional/parser/rule-methods.rb +132 -0
- data/test/functional/parser/scopes.rb +274 -0
- data/test/functional/token-rewrite/basic.rb +318 -0
- data/test/functional/token-rewrite/via-parser.rb +100 -0
- data/test/functional/tree-parser/basic.rb +750 -0
- data/test/unit/sample-input/file-stream-1 +2 -0
- data/test/unit/sample-input/teststreams.input2 +2 -0
- data/test/unit/test-dfa.rb +52 -0
- data/test/unit/test-exceptions.rb +44 -0
- data/test/unit/test-recognizers.rb +55 -0
- data/test/unit/test-scheme.rb +62 -0
- data/test/unit/test-streams.rb +459 -0
- data/test/unit/test-tree-wizard.rb +535 -0
- data/test/unit/test-trees.rb +854 -0
- metadata +205 -0
data/lib/antlr3/tree.rb
ADDED
@@ -0,0 +1,1415 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
=begin LICENSE
|
5
|
+
|
6
|
+
[The "BSD licence"]
|
7
|
+
Copyright (c) 2009 Kyle Yetter
|
8
|
+
All rights reserved.
|
9
|
+
|
10
|
+
Redistribution and use in source and binary forms, with or without
|
11
|
+
modification, are permitted provided that the following conditions
|
12
|
+
are met:
|
13
|
+
|
14
|
+
1. Redistributions of source code must retain the above copyright
|
15
|
+
notice, this list of conditions and the following disclaimer.
|
16
|
+
2. Redistributions in binary form must reproduce the above copyright
|
17
|
+
notice, this list of conditions and the following disclaimer in the
|
18
|
+
documentation and/or other materials provided with the distribution.
|
19
|
+
3. The name of the author may not be used to endorse or promote products
|
20
|
+
derived from this software without specific prior written permission.
|
21
|
+
|
22
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
23
|
+
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
24
|
+
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
25
|
+
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
26
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
27
|
+
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
28
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
29
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
30
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
31
|
+
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
32
|
+
|
33
|
+
=end
|
34
|
+
|
35
|
+
require 'antlr3'
|
36
|
+
|
37
|
+
module ANTLR3
|
38
|
+
|
39
|
+
=begin rdoc ANTLR3::AST
|
40
|
+
|
41
|
+
Name space containing all of the entities pertaining to tree construction and
|
42
|
+
tree parsing.
|
43
|
+
|
44
|
+
=end
|
45
|
+
|
46
|
+
module AST
|
47
|
+
|
48
|
+
autoload :Wizard, 'antlr3/tree/wizard'
|
49
|
+
autoload :Visitor, 'antlr3/tree/visitor'
|
50
|
+
|
51
|
+
####################################################################################################
|
52
|
+
############################################ Tree Parser ###########################################
|
53
|
+
####################################################################################################
|
54
|
+
|
55
|
+
=begin rdoc ANTLR3::AST::TreeParser
|
56
|
+
|
57
|
+
= TreeParser
|
58
|
+
|
59
|
+
TreeParser is the default base class of ANTLR-generated tree parsers. The class
|
60
|
+
tailors the functionality provided by BaseRecognizer to the task of tree-pattern
|
61
|
+
recognition.
|
62
|
+
|
63
|
+
== About Tree Parsers
|
64
|
+
|
65
|
+
ANTLR generates three basic types of recognizers:
|
66
|
+
* lexers
|
67
|
+
* parsers
|
68
|
+
* tree parsers
|
69
|
+
|
70
|
+
Furthermore, it is capable of generating several different flavors of parser,
|
71
|
+
including parsers that take token input and use it to build Abstract Syntax
|
72
|
+
Trees (ASTs), tree structures that reflect the high-level syntactic and semantic
|
73
|
+
structures defined by the language.
|
74
|
+
|
75
|
+
You can take the information encapsulated by the AST and process it directly in
|
76
|
+
a program. However, ANTLR also provides a means to create a recognizer which is
|
77
|
+
capable of walking through the AST, verifying its structure and performing
|
78
|
+
custom actions along the way -- tree parsers.
|
79
|
+
|
80
|
+
Tree parsers are created from tree grammars. ANTLR-generated tree parsers
|
81
|
+
closely mirror the general structure of regular parsers and lexers.
|
82
|
+
|
83
|
+
For more in-depth coverage of the topic, check out the ANTLR documentation
|
84
|
+
(http://www.antlr.org).
|
85
|
+
|
86
|
+
== The Tree Parser API
|
87
|
+
|
88
|
+
Like Parser, the class does not stray too far from the BaseRecognizer API.
|
89
|
+
Mainly, it customizes a few methods specifically to deal with tree nodes
|
90
|
+
(instead of basic tokens), and adds some helper methods for working with trees.
|
91
|
+
|
92
|
+
Like all ANTLR recognizers, tree parsers contained a shared state structure and
|
93
|
+
an input stream, which should be a TreeNodeStream. ANTLR intends to keep its
|
94
|
+
tree features flexible and customizable, and thus it does not make any
|
95
|
+
assumptions about the class of the actual nodes it processes. One consequence of
|
96
|
+
this flexibility is that tree parsers also require an extra tree adaptor object,
|
97
|
+
the purpose of which is to provide a homogeneous interface for handling tree
|
98
|
+
construction and analysis of your tree nodes.
|
99
|
+
|
100
|
+
See Tree and TreeAdaptor for more information.
|
101
|
+
|
102
|
+
=end
|
103
|
+
|
104
|
+
class TreeParser < BaseRecognizer
|
105
|
+
def self.main(argv = ARGV, options = {})
|
106
|
+
if argv.is_a?(::Hash) then argv, options = ARGV, argv end
|
107
|
+
main = ANTLR3::Main::WalkerMain.new(self, options)
|
108
|
+
block_given? ? yield(main) : main.execute(argv)
|
109
|
+
end
|
110
|
+
|
111
|
+
def initialize(input, options = {})
|
112
|
+
super(options)
|
113
|
+
@input = input
|
114
|
+
end
|
115
|
+
|
116
|
+
alias tree_node_stream input
|
117
|
+
alias tree_node_stream= input=
|
118
|
+
def source_name
|
119
|
+
@input.source_name
|
120
|
+
end
|
121
|
+
|
122
|
+
def current_input_symbol
|
123
|
+
@input.look
|
124
|
+
end
|
125
|
+
|
126
|
+
def missing_symbol(error, expected_token_type, follow)
|
127
|
+
name = token_name(expected_token_type).to_s
|
128
|
+
text = "<missing " << name << '>'
|
129
|
+
tk = create_token do |t|
|
130
|
+
t.text = text
|
131
|
+
t.type = expected_token_type
|
132
|
+
end
|
133
|
+
return(CommonTree.new(tk))
|
134
|
+
end
|
135
|
+
|
136
|
+
DOT_DOT_PATTERN = /.*[^\.]\\.{2}[^\.].*/
|
137
|
+
DOUBLE_ETC_PATTERN = /.*\.{3}\s+\.{3}.*/
|
138
|
+
|
139
|
+
def in_context?(context)
|
140
|
+
self.class.in_context?(
|
141
|
+
@input.tree_adaptor, token_names, @input.look, context)
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.in_context?(adaptor, token_names, tree, context)
|
145
|
+
case context
|
146
|
+
when DOT_DOT_PATTERN then raise ArgumentError, "invalid syntax: .."
|
147
|
+
when DOUBLE_ETC_PATTERN then raise ArgumentError, "invalid syntax: ... ..."
|
148
|
+
end
|
149
|
+
|
150
|
+
context = context.gsub(/([^\.\s])\.{3}([^\.])/, '\1 ... \2')
|
151
|
+
context.strip!
|
152
|
+
nodes = context.split(/\s+/)
|
153
|
+
|
154
|
+
ni = nodes.length.pred
|
155
|
+
tree = adaptor.parent(tree)
|
156
|
+
while ni >= 0 and tree
|
157
|
+
if nodes[ni] == '...'
|
158
|
+
ni.zero? and return true
|
159
|
+
goal = nodes[ni.pred]
|
160
|
+
ancestor = ancestor(adaptor, token_names, tree, goal) or return false
|
161
|
+
tree = ancestor
|
162
|
+
ni -= 1
|
163
|
+
end
|
164
|
+
name = token_names[adaptor.type_of(tree)]
|
165
|
+
name == nodes[ni] or return false
|
166
|
+
ni -= 1
|
167
|
+
tree = adaptor.parent(tree)
|
168
|
+
end
|
169
|
+
|
170
|
+
tree.nil? && ni >= 0 and return false
|
171
|
+
return true
|
172
|
+
end
|
173
|
+
|
174
|
+
def self.ancestor(adaptor, token_names, tree, goal)
|
175
|
+
while tree
|
176
|
+
name = token_names[adaptor.type_of(tree)]
|
177
|
+
name == goal and return tree
|
178
|
+
tree = adaptor.parent(tree)
|
179
|
+
end
|
180
|
+
return nil
|
181
|
+
end
|
182
|
+
|
183
|
+
def match_any(ignore = nil)
|
184
|
+
@state.error_recovery = false
|
185
|
+
|
186
|
+
look = @input.look
|
187
|
+
if @input.tree_adaptor.child_count(look) == 0
|
188
|
+
@input.consume
|
189
|
+
return
|
190
|
+
end
|
191
|
+
level = 0
|
192
|
+
token_type = @input.tree_adaptor.type_of(look)
|
193
|
+
until token_type == EOF or (token_type == UP && level == 0)
|
194
|
+
@input.consume
|
195
|
+
look = @input.look
|
196
|
+
case token_type = @input.tree_adaptor.type_of(look)
|
197
|
+
when DOWN then level += 1
|
198
|
+
when UP then level -= 1
|
199
|
+
end
|
200
|
+
end
|
201
|
+
@input.consume # consume UP
|
202
|
+
end
|
203
|
+
|
204
|
+
def mismatch(input, type, follow = nil)
|
205
|
+
raise MismatchedTreeNode.new(type, input)
|
206
|
+
end
|
207
|
+
|
208
|
+
def error_header(err)
|
209
|
+
(<<-END.strip!)
|
210
|
+
#{self.grammar_file_name}: node from #{
|
211
|
+
err.approximate_line_info? ? 'after ' : ''
|
212
|
+
} line #{err.line}:#{err.column}
|
213
|
+
END
|
214
|
+
end
|
215
|
+
|
216
|
+
def error_message(e)
|
217
|
+
adaptor = e.input.tree_adaptor
|
218
|
+
e.token = adaptor.token(e.node)
|
219
|
+
e.token ||= create_token do |tok|
|
220
|
+
tok.type = adaptor.type_of(e.node)
|
221
|
+
tok.text = adaptor.text_of(e.node)
|
222
|
+
end
|
223
|
+
return super(e)
|
224
|
+
end
|
225
|
+
|
226
|
+
def trace_in(rule_name, rule_index)
|
227
|
+
super(rule_name, rule_index, @input.look)
|
228
|
+
end
|
229
|
+
def trace_out(rule_name, rule_index)
|
230
|
+
super(rule_name, rule_index, @input.look)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
####################################################################################################
|
235
|
+
############################################ Tree Nodes ############################################
|
236
|
+
####################################################################################################
|
237
|
+
|
238
|
+
=begin rdoc ANTLR3::AST::Tree
|
239
|
+
|
240
|
+
= ANTLR Abstract Syntax Trees
|
241
|
+
|
242
|
+
As ANTLR is concerned, an Abstract Syntax Tree (AST) node is an object that
|
243
|
+
wraps a token, a list of child trees, and some information about the collective
|
244
|
+
source text embodied within the tree and its children.
|
245
|
+
|
246
|
+
The Tree module, like the Token and Stream modules, emulates an abstract base
|
247
|
+
class for AST classes; it specifies the attributes that are expected of basic
|
248
|
+
tree nodes as well as the methods trees need to implement.
|
249
|
+
|
250
|
+
== Terminology
|
251
|
+
|
252
|
+
While much of this terminology is probably familiar to most developers, the
|
253
|
+
following brief glossary is intended to clarify terminology used in code
|
254
|
+
throughout the AST library:
|
255
|
+
|
256
|
+
[payload] either a token value contained within a node or +nil+
|
257
|
+
[flat list (nil tree)] a tree node without a token payload, but with more
|
258
|
+
than one children -- functions like an array of
|
259
|
+
tree nodes
|
260
|
+
[root] a top-level tree node, i.e. a node that does not have a parent
|
261
|
+
[leaf] a node that does not have any children
|
262
|
+
[siblings] all other nodes sharing the same parent as some node
|
263
|
+
[ancestors] the list of successive parents from a tree node to the root node
|
264
|
+
[error node] a special node used to represent an erroneous series of tokens
|
265
|
+
from an input stream
|
266
|
+
|
267
|
+
=end
|
268
|
+
|
269
|
+
module Tree
|
270
|
+
attr_accessor :parent
|
271
|
+
attr_accessor :token_start_index
|
272
|
+
attr_accessor :token_stop_index
|
273
|
+
attr_accessor :child_index
|
274
|
+
attr_reader :type
|
275
|
+
attr_reader :text
|
276
|
+
attr_reader :line
|
277
|
+
attr_reader :column
|
278
|
+
attr_reader :children
|
279
|
+
attr_reader :token
|
280
|
+
|
281
|
+
def [](index, length = nil) # getChild(index)
|
282
|
+
length.nil? ? self.children[index] : self.children[index, length]
|
283
|
+
end
|
284
|
+
|
285
|
+
alias child []
|
286
|
+
|
287
|
+
def child_count # getChildCount
|
288
|
+
self.children.length
|
289
|
+
end
|
290
|
+
|
291
|
+
def push(node, *nodes)
|
292
|
+
self.children.push(node, *nodes)
|
293
|
+
end
|
294
|
+
|
295
|
+
alias << push
|
296
|
+
|
297
|
+
def shift
|
298
|
+
self.children.shift
|
299
|
+
end
|
300
|
+
|
301
|
+
def unshift(node, *nodes)
|
302
|
+
self.children.unshift(node, *nodes)
|
303
|
+
end
|
304
|
+
|
305
|
+
alias add_child shift
|
306
|
+
|
307
|
+
def set_child(index, tree)
|
308
|
+
self.children[index] = tree
|
309
|
+
end
|
310
|
+
|
311
|
+
alias []= set_child
|
312
|
+
|
313
|
+
def delete_child(index)
|
314
|
+
self.children.delete(index)
|
315
|
+
end
|
316
|
+
|
317
|
+
def replace_children(start, stop, trees)
|
318
|
+
self.children[start..stop] = trees
|
319
|
+
end
|
320
|
+
|
321
|
+
def to_a
|
322
|
+
child_arrays = children.map { |child| child.to_a }
|
323
|
+
[token, *child_arrays]
|
324
|
+
end
|
325
|
+
|
326
|
+
include Enumerable
|
327
|
+
|
328
|
+
def each_child
|
329
|
+
block_given? or return enum_for(__method__)
|
330
|
+
self.children.each { |child| yield(child) }
|
331
|
+
end
|
332
|
+
|
333
|
+
def each_ancestor
|
334
|
+
block_given? or return enum_for(__method__)
|
335
|
+
self.ancestors.each { |anc| yield(anc) }
|
336
|
+
end
|
337
|
+
|
338
|
+
def walk
|
339
|
+
block_given? or return(enum_for(__method__))
|
340
|
+
stack = []
|
341
|
+
cursor = self
|
342
|
+
loop do
|
343
|
+
begin
|
344
|
+
yield(cursor)
|
345
|
+
stack.push(cursor.children.clone) unless cursor.leaf?
|
346
|
+
rescue StopIteration
|
347
|
+
# skips adding children to prune the node
|
348
|
+
ensure
|
349
|
+
break if stack.empty?
|
350
|
+
cursor = stack.last.shift
|
351
|
+
stack.pop if stack.last.empty?
|
352
|
+
end
|
353
|
+
end
|
354
|
+
return self
|
355
|
+
end
|
356
|
+
|
357
|
+
def prune
|
358
|
+
raise StopIteration
|
359
|
+
end
|
360
|
+
|
361
|
+
alias :each :walk
|
362
|
+
|
363
|
+
def root?
|
364
|
+
parent.nil?
|
365
|
+
end
|
366
|
+
|
367
|
+
def leaf?
|
368
|
+
children.empty?
|
369
|
+
end
|
370
|
+
|
371
|
+
def ancestors
|
372
|
+
a = []
|
373
|
+
cursor = self
|
374
|
+
until cursor.root?
|
375
|
+
a.push(cursor.parent)
|
376
|
+
cursor = cursor.parent
|
377
|
+
end
|
378
|
+
return a
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
|
383
|
+
=begin rdoc ANTLR3::AST::BaseTree
|
384
|
+
|
385
|
+
A base implementation of an Abstract Syntax Tree Node. It mainly defines the
|
386
|
+
methods and attributes required to implement the parent-node-children
|
387
|
+
relationship that characterize a tree; it does not provide any logic concerning
|
388
|
+
a node's token <i>payload</i>.
|
389
|
+
|
390
|
+
=end
|
391
|
+
|
392
|
+
class BaseTree
|
393
|
+
extend ClassMacros
|
394
|
+
include Tree
|
395
|
+
|
396
|
+
def initialize(node = nil)
|
397
|
+
@children = []
|
398
|
+
@parent = nil
|
399
|
+
@child_index = 0
|
400
|
+
end
|
401
|
+
|
402
|
+
def child(index)
|
403
|
+
@children[index]
|
404
|
+
end
|
405
|
+
|
406
|
+
def first_child_with_type(tree_type)
|
407
|
+
@children.find { |child| child.type == tree_type }
|
408
|
+
end
|
409
|
+
|
410
|
+
def child_count
|
411
|
+
@children.length
|
412
|
+
end
|
413
|
+
|
414
|
+
def add_child(child_tree)
|
415
|
+
child_tree.nil? and return
|
416
|
+
if child_tree.flat_list?
|
417
|
+
if @children.equal?(child_tree.children)
|
418
|
+
raise ArgumentError, "attempt to add child list to itself"
|
419
|
+
end
|
420
|
+
child_tree.children.each_with_index do |child, index|
|
421
|
+
child.parent = self
|
422
|
+
child.child_index = @children.length + index
|
423
|
+
end
|
424
|
+
@children.concat(child_tree.children)
|
425
|
+
else
|
426
|
+
@children << child_tree
|
427
|
+
child_tree.parent = self
|
428
|
+
child_tree.child_index = @children.length - 1
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
def add_children(children)
|
433
|
+
@children.concat(children)
|
434
|
+
end
|
435
|
+
|
436
|
+
def set_child(index, tree)
|
437
|
+
return if tree.nil?
|
438
|
+
tree.flat_list? and raise ArgumentError, "Can't set single child to a list"
|
439
|
+
tree.parent = self
|
440
|
+
tree.child_index = index
|
441
|
+
@children[index] = tree
|
442
|
+
end
|
443
|
+
|
444
|
+
def delete_child(index)
|
445
|
+
if killed = @children[index]
|
446
|
+
@children[index, 1] = nil
|
447
|
+
@children[index..-1].each_with_index do |child, i|
|
448
|
+
child.child_index = index + i
|
449
|
+
end
|
450
|
+
end
|
451
|
+
return killed
|
452
|
+
end
|
453
|
+
|
454
|
+
def replace_children(start_index, stop_index, new_tree)
|
455
|
+
start_index >= @children.length or stop_index >= @children.length and
|
456
|
+
raise IndexError, (<<-END).gsub!(/^\s+\| /,'')
|
457
|
+
| indices span beyond the number of children:
|
458
|
+
| children.length = #{@children.length}
|
459
|
+
| start = #{start_index.inspect}
|
460
|
+
| stop = #{stop_index.inspect}
|
461
|
+
END
|
462
|
+
new_children = new_tree.flat_list? ? new_tree.children : [new_tree]
|
463
|
+
@children[start_index..stop_index] = new_children
|
464
|
+
freshen_parent_and_child_indexes(start_index)
|
465
|
+
return self
|
466
|
+
end
|
467
|
+
|
468
|
+
def flat_list?
|
469
|
+
false
|
470
|
+
end
|
471
|
+
|
472
|
+
def freshen_parent_and_child_indexes(offset = 0)
|
473
|
+
@children[offset..-1].each_with_index do |child, index|
|
474
|
+
child.child_index = index + offset
|
475
|
+
child.parent = self
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
|
480
|
+
def sanity_check_parent_and_child_indexes(parent = nil, i = -1)
|
481
|
+
parent == @parent or
|
482
|
+
raise TreeInconsistency.failed_parent_check!(parent, @parent)
|
483
|
+
i == @child_index or
|
484
|
+
raise TreeInconsistency.failed_index_check!(i, @child_index)
|
485
|
+
@children.each_with_index do |child, index|
|
486
|
+
child.sanity_check_parent_and_child_indexes(self, index)
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
def to_string_tree
|
491
|
+
@children.empty? and return self.to_s
|
492
|
+
buffer = []
|
493
|
+
buffer << '(' << self.to_s << ' ' unless self.flat_list?
|
494
|
+
buffer << @children.map { |child| child.to_string_tree }.join(' ')
|
495
|
+
buffer << ' '
|
496
|
+
buffer << ')' unless self.flat_list?
|
497
|
+
return buffer.join
|
498
|
+
end
|
499
|
+
|
500
|
+
def line; return 0; end
|
501
|
+
def column; return 0; end
|
502
|
+
|
503
|
+
abstract :to_s
|
504
|
+
end
|
505
|
+
|
506
|
+
|
507
|
+
=begin rdoc ANTLR3::AST::CommonTree
|
508
|
+
|
509
|
+
The default Tree class implementation used by ANTLR tree-related code.
|
510
|
+
|
511
|
+
A CommonTree object is a tree node that wraps a token <i>payload</i> (or a +nil+
|
512
|
+
value) and contains zero or more child tree nodes. Additionally, it tracks
|
513
|
+
information about the range of data collectively spanned by the tree node:
|
514
|
+
|
515
|
+
* the token stream start and stop indexes of tokens contained throughout
|
516
|
+
the tree
|
517
|
+
* that start and stop positions of the character input stream from which
|
518
|
+
the tokens were defined
|
519
|
+
|
520
|
+
Tracking this information simplifies tasks like extracting a block of code or
|
521
|
+
rewriting the input stream. However, depending on the purpose of the
|
522
|
+
application, building trees with all of this extra information may be
|
523
|
+
unnecessary. In such a case, a more bare-bones tree class could be written
|
524
|
+
(optionally using the BaseTree class or the Token module). Define a customized
|
525
|
+
TreeAdaptor class to handle tree construction and manipulation for the
|
526
|
+
customized node class, and recognizers will be able to build, rewrite, and parse
|
527
|
+
the customized lighter-weight trees.
|
528
|
+
|
529
|
+
=end
|
530
|
+
|
531
|
+
class CommonTree < BaseTree
|
532
|
+
def initialize(payload = nil)
|
533
|
+
super()
|
534
|
+
@start_index = -1
|
535
|
+
@stop_index = -1
|
536
|
+
@child_index = -1
|
537
|
+
case payload
|
538
|
+
when CommonTree then
|
539
|
+
@token = payload.token
|
540
|
+
@start_index = payload.start_index
|
541
|
+
@stop_index = payload.stop_index
|
542
|
+
when nil, Token then @token = payload
|
543
|
+
else raise ArgumentError, "Invalid argument type: #{payload.class} (#{payload.inspect})"
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
def initialize_copy(orig)
|
548
|
+
super
|
549
|
+
@parent = nil
|
550
|
+
@children = []
|
551
|
+
end
|
552
|
+
|
553
|
+
attr_reader :token
|
554
|
+
|
555
|
+
def copy_node
|
556
|
+
return CommonTree.new(@token)
|
557
|
+
end
|
558
|
+
|
559
|
+
def flat_list?
|
560
|
+
@token.nil?
|
561
|
+
end
|
562
|
+
|
563
|
+
def type
|
564
|
+
@token.nil? ? 0 : @token.type
|
565
|
+
end
|
566
|
+
|
567
|
+
def text
|
568
|
+
@token.text rescue nil
|
569
|
+
end
|
570
|
+
|
571
|
+
def line
|
572
|
+
if @token.nil? or @token.line == 0
|
573
|
+
return (child_count > 0 ? child(0).line : 0)
|
574
|
+
end
|
575
|
+
return @token.line
|
576
|
+
end
|
577
|
+
|
578
|
+
def column
|
579
|
+
if @token.nil? or @token.column == -1
|
580
|
+
return(child_count > 0 ? child(0).column : 0)
|
581
|
+
end
|
582
|
+
return @token.column
|
583
|
+
end
|
584
|
+
|
585
|
+
def start_index
|
586
|
+
return @token.index if @start_index == -1 and !@token.nil?
|
587
|
+
return @start_index
|
588
|
+
end
|
589
|
+
|
590
|
+
def stop_index
|
591
|
+
return @token.index if @stop_index == -1 and !@token.nil?
|
592
|
+
return @stop_index
|
593
|
+
end
|
594
|
+
|
595
|
+
attr_writer :start_index, :stop_index
|
596
|
+
alias token_start_index= start_index=
|
597
|
+
alias token_stop_index= stop_index=
|
598
|
+
alias token_start_index start_index
|
599
|
+
alias token_stop_index stop_index
|
600
|
+
|
601
|
+
def name
|
602
|
+
@token.nil? ? 'INVALID' : @token.name
|
603
|
+
end
|
604
|
+
|
605
|
+
def token_range
|
606
|
+
unknown_token_boundaries? and set_unknown_token_boundaries
|
607
|
+
@start_index..@stop_index
|
608
|
+
end
|
609
|
+
def source_range
|
610
|
+
unknown_token_boundaries? and set_unknown_token_boundaries
|
611
|
+
tokens = self.map do |node|
|
612
|
+
tk = node.token
|
613
|
+
(tk && tk.index >= 0) ? tk : nil
|
614
|
+
end
|
615
|
+
tokens.compact!
|
616
|
+
first, last = tokens.minmax_by { |tk| tk.index }
|
617
|
+
(first.start)..(last.stop)
|
618
|
+
end
|
619
|
+
|
620
|
+
def set_unknown_token_boundaries
|
621
|
+
if @children.nil? || @children.empty? and (@start_index < 0 or @stop_index < 0)
|
622
|
+
@start_index = @stop_index = @token.index rescue -1
|
623
|
+
return
|
624
|
+
end
|
625
|
+
for child in @children do child.set_unknown_token_boundaries end
|
626
|
+
return if @start_index >= 0 and @stop_index >= 0
|
627
|
+
|
628
|
+
@start_index = @children.first.token_start_index
|
629
|
+
@stop_index = @children.last.token_stop_index
|
630
|
+
return nil
|
631
|
+
end
|
632
|
+
|
633
|
+
def unknown_token_boundaries?
|
634
|
+
@start_index < 0 || @stop_index < 0
|
635
|
+
end
|
636
|
+
|
637
|
+
def to_s
|
638
|
+
flat_list? ? 'nil' : @token.text.to_s
|
639
|
+
end
|
640
|
+
|
641
|
+
def to_string_tree
|
642
|
+
children.empty? and return self.to_s
|
643
|
+
|
644
|
+
out = ''
|
645
|
+
out << "(#{self} " unless flat_list?
|
646
|
+
|
647
|
+
out << children.map { |child| child.to_string_tree }.join(' ')
|
648
|
+
out << ')' unless flat_list?
|
649
|
+
return out
|
650
|
+
end
|
651
|
+
alias inspect to_string_tree
|
652
|
+
|
653
|
+
def pretty_print(printer)
|
654
|
+
if children.empty?
|
655
|
+
lines = self.to_s.split(/\r?\n/, -1)
|
656
|
+
for line in lines[0...-1]
|
657
|
+
printer.text(line)
|
658
|
+
printer.text(printer.newline)
|
659
|
+
printer.text(printer.genspace[printer.indent])
|
660
|
+
end
|
661
|
+
return(printer.text(lines.last))
|
662
|
+
end
|
663
|
+
|
664
|
+
endpoints = flat_list? ? ['', ''] : ["(#{self}", ')']
|
665
|
+
printer.group(1, *endpoints) do
|
666
|
+
for child in self.children
|
667
|
+
printer.breakable
|
668
|
+
printer.pp(child)
|
669
|
+
end
|
670
|
+
end
|
671
|
+
end
|
672
|
+
|
673
|
+
end
|
674
|
+
|
675
|
+
|
676
|
+
=begin rdoc ANTLR3::AST::CommonErrorNode
|
677
|
+
|
678
|
+
Represents a series of erroneous tokens from a token stream input
|
679
|
+
|
680
|
+
=end
|
681
|
+
|
682
|
+
class CommonErrorNode < CommonTree
|
683
|
+
include ANTLR3::Error
|
684
|
+
include ANTLR3::Constants
|
685
|
+
|
686
|
+
attr_accessor :input, :start, :stop, :error
|
687
|
+
|
688
|
+
def initialize(input, start, stop, error)
|
689
|
+
super(nil)
|
690
|
+
stop = start if stop.nil? or
|
691
|
+
(stop.token_index < start.token_index and stop.type != EOF)
|
692
|
+
@input = input
|
693
|
+
@start = start
|
694
|
+
@stop = stop
|
695
|
+
@error = error
|
696
|
+
end
|
697
|
+
|
698
|
+
def flat_list?
|
699
|
+
return false
|
700
|
+
end
|
701
|
+
|
702
|
+
def type
|
703
|
+
INVALID_TOKEN_TYPE
|
704
|
+
end
|
705
|
+
|
706
|
+
def text
|
707
|
+
case @start
|
708
|
+
when Token
|
709
|
+
i = @start.token_index
|
710
|
+
j = (@stop.type == EOF) ? @input.size : @stop.token_index
|
711
|
+
@input.to_s(i,j) # <- the bad text
|
712
|
+
when Tree
|
713
|
+
@input.to_s(@start, @stop) # <- the bad text
|
714
|
+
else
|
715
|
+
"<unknown>"
|
716
|
+
end
|
717
|
+
end
|
718
|
+
|
719
|
+
def to_s
|
720
|
+
case @error
|
721
|
+
when MissingToken
|
722
|
+
"<missing type: #{@error.missing_type}>"
|
723
|
+
when UnwantedToken
|
724
|
+
"<extraneous: #{@error.token.inspect}, resync = #{self.text}>"
|
725
|
+
when MismatchedToken
|
726
|
+
"<mismatched token: #{@error.token.inspect}, resync = #{self.text}>"
|
727
|
+
when NoViableAlternative
|
728
|
+
"<unexpected: #{@error.token.inspect}, resync = #{self.text}>"
|
729
|
+
else "<error: #{text}>"
|
730
|
+
end
|
731
|
+
end
|
732
|
+
|
733
|
+
end
|
734
|
+
|
735
|
+
Constants::INVALID_NODE = CommonTree.new(ANTLR3::INVALID_TOKEN)
|
736
|
+
|
737
|
+
####################################################################################################
|
738
|
+
########################################### Tree Adaptors ##########################################
|
739
|
+
####################################################################################################
|
740
|
+
|
741
|
+
=begin rdoc ANTLR3::AST::TreeAdaptor
|
742
|
+
|
743
|
+
Since a tree can be represented by a multitude of formats, ANTLR's tree-related
|
744
|
+
code mandates the use of Tree Adaptor objects to build and manipulate any actual
|
745
|
+
trees. Using an adaptor object permits a single recognizer to work with any
|
746
|
+
number of different tree structures without adding rigid interface requirements
|
747
|
+
on customized tree structures. For example, if you want to represent trees using
|
748
|
+
simple arrays of arrays, you just need to design an appropriate tree adaptor and
|
749
|
+
provide it to the parser.
|
750
|
+
|
751
|
+
Tree adaptors are tasked with:
|
752
|
+
|
753
|
+
* copying and creating tree nodes and tokens
|
754
|
+
* defining parent-child relationships between nodes
|
755
|
+
* cleaning up / normalizing a full tree structure after construction
|
756
|
+
* reading and writing the attributes ANTLR expects of tree nodes
|
757
|
+
* providing node access and iteration
|
758
|
+
|
759
|
+
=end
|
760
|
+
|
761
|
+
module TreeAdaptor
|
762
|
+
include TokenFactory
|
763
|
+
include Constants
|
764
|
+
|
765
|
+
def add_child(tree, child)
|
766
|
+
tree.add_child(child) if tree and child
|
767
|
+
end
|
768
|
+
|
769
|
+
def child_count(tree)
|
770
|
+
tree.child_count
|
771
|
+
end
|
772
|
+
|
773
|
+
def child_index(tree)
|
774
|
+
tree.child_index rescue 0
|
775
|
+
end
|
776
|
+
|
777
|
+
def child_of(tree, index)
|
778
|
+
tree.nil? ? nil : tree.child(index)
|
779
|
+
end
|
780
|
+
|
781
|
+
def copy_node(tree_node)
|
782
|
+
tree_node.dup unless tree_node.nil?
|
783
|
+
end
|
784
|
+
|
785
|
+
def copy_tree(tree, parent = nil)
|
786
|
+
tree or return nil
|
787
|
+
new_tree = copy_node(tree)
|
788
|
+
set_child_index(new_tree, child_index(tree))
|
789
|
+
set_parent(new_tree, parent)
|
790
|
+
each_child(tree) do |child|
|
791
|
+
new_sub_tree = copy_tree(child, tree)
|
792
|
+
add_child(new_tree, new_sub_tree)
|
793
|
+
end
|
794
|
+
return new_tree
|
795
|
+
end
|
796
|
+
|
797
|
+
def delete_child(tree, index)
|
798
|
+
tree.delete_child(index)
|
799
|
+
end
|
800
|
+
|
801
|
+
def each_child(tree)
|
802
|
+
block_given? or return enum_for(__method__)
|
803
|
+
i = 0
|
804
|
+
n = child_count(tree)
|
805
|
+
while i < n
|
806
|
+
yield child_of(tree, i)
|
807
|
+
i += 1
|
808
|
+
end
|
809
|
+
end
|
810
|
+
|
811
|
+
def flat_list?(tree)
|
812
|
+
tree.flat_list?
|
813
|
+
end
|
814
|
+
|
815
|
+
def parent(tree)
|
816
|
+
tree.parent
|
817
|
+
end
|
818
|
+
|
819
|
+
def replace_children(parent, start_index, stop_index, replacement_tree)
|
820
|
+
parent.nil? or
|
821
|
+
parent.replace_children(start_index, stop_index, replacement_tree)
|
822
|
+
end
|
823
|
+
|
824
|
+
def rule_post_processing(root)
|
825
|
+
if root and root.flat_list?
|
826
|
+
case root.child_count
|
827
|
+
when 0 then root = nil
|
828
|
+
when 1
|
829
|
+
root = root.child(0)
|
830
|
+
root.parent = nil
|
831
|
+
root.child_index = -1
|
832
|
+
end
|
833
|
+
end
|
834
|
+
return root
|
835
|
+
end
|
836
|
+
|
837
|
+
def set_child_index(tree, index)
|
838
|
+
tree.child_index = index
|
839
|
+
end
|
840
|
+
|
841
|
+
def set_parent(tree, parent)
|
842
|
+
tree.parent = parent
|
843
|
+
end
|
844
|
+
|
845
|
+
def set_token_boundaries(tree, start_token = nil, stop_token = nil)
|
846
|
+
return(nil) if tree.nil?
|
847
|
+
start = stop = 0
|
848
|
+
start = start_token.index unless start_token.nil?
|
849
|
+
stop = stop_token.index unless stop_token.nil?
|
850
|
+
tree.token_start_index = start
|
851
|
+
tree.token_stop_index = stop
|
852
|
+
return tree
|
853
|
+
end
|
854
|
+
|
855
|
+
def text_of(tree)
|
856
|
+
tree.text rescue nil
|
857
|
+
end
|
858
|
+
|
859
|
+
def token(tree)
|
860
|
+
tree.is_a?(CommonTree) ? tree.token : nil
|
861
|
+
end
|
862
|
+
|
863
|
+
def token_start_index(tree)
|
864
|
+
tree.nil? ? -1 : tree.token_start_index
|
865
|
+
end
|
866
|
+
|
867
|
+
def token_stop_index(tree)
|
868
|
+
tree.nil? ? -1 : tree.token_stop_index
|
869
|
+
end
|
870
|
+
|
871
|
+
def type_name(tree)
|
872
|
+
tree.nil? ? 'INVALID' : tree.name
|
873
|
+
end
|
874
|
+
|
875
|
+
def type_of(tree)
|
876
|
+
tree.nil? ? INVALID_TOKEN_TYPE : tree.type
|
877
|
+
end
|
878
|
+
|
879
|
+
def unique_id(node)
|
880
|
+
node.hash
|
881
|
+
end
|
882
|
+
end
|
883
|
+
|
884
|
+
|
885
|
+
|
886
|
+
=begin rdoc ANTLR3::AST::CommonTreeAdaptor
|
887
|
+
|
888
|
+
The default tree adaptor used by ANTLR-generated tree code. It, of course,
|
889
|
+
builds and manipulates CommonTree nodes.
|
890
|
+
|
891
|
+
=end
|
892
|
+
|
893
|
+
class CommonTreeAdaptor
|
894
|
+
include TreeAdaptor
|
895
|
+
include ANTLR3::Constants
|
896
|
+
|
897
|
+
def initialize(token_class = ANTLR3::CommonToken)
|
898
|
+
@token_class = token_class
|
899
|
+
end
|
900
|
+
|
901
|
+
def create_flat_list!
|
902
|
+
return self.create_with_payload!(nil)
|
903
|
+
end
|
904
|
+
|
905
|
+
def become_root(new_root, old_root)
|
906
|
+
new_root = create!(new_root) if new_root.is_a?(Token)
|
907
|
+
old_root.nil? and return(new_root)
|
908
|
+
|
909
|
+
new_root = create_with_payload!(new_root) unless new_root.is_a?(CommonTree)
|
910
|
+
if new_root.flat_list?
|
911
|
+
count = new_root.child_count
|
912
|
+
if count == 1
|
913
|
+
new_root = new_root.child(0)
|
914
|
+
elsif count > 1
|
915
|
+
raise TreeInconsistency.multiple_roots!
|
916
|
+
end
|
917
|
+
end
|
918
|
+
|
919
|
+
new_root.add_child(old_root)
|
920
|
+
return new_root
|
921
|
+
end
|
922
|
+
|
923
|
+
def create_from_token!(token_type, from_token, text = nil)
|
924
|
+
from_token = from_token.clone
|
925
|
+
from_token.type = token_type
|
926
|
+
from_token.text = text unless text.nil?
|
927
|
+
tree = create_with_payload!(from_token)
|
928
|
+
return tree
|
929
|
+
end
|
930
|
+
|
931
|
+
def create_from_type!(token_type, text)
|
932
|
+
from_token = create_token(token_type, DEFAULT_CHANNEL, text)
|
933
|
+
create_with_payload!(from_token)
|
934
|
+
end
|
935
|
+
|
936
|
+
def create_error_node!(input, start, stop, exc)
|
937
|
+
CommonErrorNode.new(input, start, stop, exc)
|
938
|
+
end
|
939
|
+
|
940
|
+
def create_with_payload!(payload)
|
941
|
+
return CommonTree.new(payload)
|
942
|
+
end
|
943
|
+
|
944
|
+
def create!(*args)
|
945
|
+
n = args.length
|
946
|
+
if n == 1 and args.first.is_a?(Token) then create_with_payload!(args[0])
|
947
|
+
elsif n >= 2 and args[0].is_a?(Integer) and args[1].is_a?(Token)
|
948
|
+
create_from_token!(*args)
|
949
|
+
elsif n == 2 and args[0].is_a?(Integer) and args[1].is_a?(String)
|
950
|
+
create_from_type!(*args)
|
951
|
+
else
|
952
|
+
sig = args.map { |f| f.class }.join(', ')
|
953
|
+
raise TypeError, "No create method with this signature found: (#{sig})"
|
954
|
+
end
|
955
|
+
end
|
956
|
+
end
|
957
|
+
|
958
|
+
|
959
|
+
####################################################################################################
|
960
|
+
########################################### Tree Streams ###########################################
|
961
|
+
####################################################################################################
|
962
|
+
|
963
|
+
=begin rdoc ANTLR3::AST::TreeNodeStream
|
964
|
+
|
965
|
+
TreeNodeStreams flatten two-dimensional tree structures into one-dimensional
|
966
|
+
sequences. They preserve the two-dimensional structure of the tree by inserting
|
967
|
+
special +UP+ and +DOWN+ nodes.
|
968
|
+
|
969
|
+
Consider a hypothetical tree:
|
970
|
+
|
971
|
+
[A]
|
972
|
+
+--[B]
|
973
|
+
| +--[C]
|
974
|
+
| `--[D]
|
975
|
+
`--[E]
|
976
|
+
`--[F]
|
977
|
+
|
978
|
+
A tree node stream would serialize the tree into the following sequence:
|
979
|
+
|
980
|
+
A DOWN B DOWN C D UP E DOWN F UP UP EOF
|
981
|
+
|
982
|
+
Other than serializing a tree into a sequence of nodes, a tree node stream
|
983
|
+
operates similarly to other streams. They are commonly used by tree parsers as
|
984
|
+
the main form of input. #peek, like token streams, returns the type of the token
|
985
|
+
of the next node. #look returns the next full tree node.
|
986
|
+
|
987
|
+
=end
|
988
|
+
|
989
|
+
module TreeNodeStream
|
990
|
+
extend ClassMacros
|
991
|
+
include Stream
|
992
|
+
include Constants
|
993
|
+
|
994
|
+
abstract :at
|
995
|
+
abstract :look
|
996
|
+
abstract :tree_source
|
997
|
+
abstract :token_stream
|
998
|
+
abstract :tree_adaptor
|
999
|
+
abstract :unique_navigation_nodes=
|
1000
|
+
abstract :to_s
|
1001
|
+
abstract :replace_children
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
=begin rdoc ANTLR3::AST::CommonTreeNodeStream
|
1005
|
+
|
1006
|
+
An implementation of TreeNodeStream tailed for streams based on CommonTree
|
1007
|
+
objects. CommonTreeNodeStreams are the default input streams for tree parsers.
|
1008
|
+
|
1009
|
+
=end
|
1010
|
+
|
1011
|
+
class CommonTreeNodeStream
|
1012
|
+
include TreeNodeStream
|
1013
|
+
|
1014
|
+
def initialize(*args)
|
1015
|
+
|
1016
|
+
case args.length
|
1017
|
+
when 1
|
1018
|
+
adaptor = CommonTreeAdaptor.new
|
1019
|
+
tree = args[0]
|
1020
|
+
@nodes = @down = @up = @eof = nil
|
1021
|
+
when 2
|
1022
|
+
adaptor, tree = *args
|
1023
|
+
@nodes = @down = @up = @eof = nil
|
1024
|
+
when 3
|
1025
|
+
parent, start, stop = *args
|
1026
|
+
adaptor = parent.adaptor
|
1027
|
+
tree = parent.root
|
1028
|
+
@nodes = parent.nodes[start...stop]
|
1029
|
+
@down = parent.down
|
1030
|
+
@up = parent.up
|
1031
|
+
@eof = parent.eof
|
1032
|
+
else raise ArgumentError, "Invalid arguments"
|
1033
|
+
end
|
1034
|
+
@down ||= adaptor.create_from_type!(DOWN, 'DOWN')
|
1035
|
+
@up ||= adaptor.create_from_type!(UP, 'UP')
|
1036
|
+
@eof ||= adaptor.create_from_type!(EOF, 'EOF')
|
1037
|
+
@nodes ||= []
|
1038
|
+
@root = tree
|
1039
|
+
@tokens = nil
|
1040
|
+
@adaptor = adaptor
|
1041
|
+
@unique_navigation_nodes = false
|
1042
|
+
@position = -1
|
1043
|
+
@last_marker = nil
|
1044
|
+
@calls = []
|
1045
|
+
end
|
1046
|
+
|
1047
|
+
def fill_buffer
|
1048
|
+
__fill_buffer__(@root)
|
1049
|
+
@position = 0
|
1050
|
+
end
|
1051
|
+
|
1052
|
+
def node_index(node)
|
1053
|
+
@position == -1 and fill_buffer
|
1054
|
+
return @nodes.index(node)
|
1055
|
+
end
|
1056
|
+
|
1057
|
+
def add_navigation_node(type)
|
1058
|
+
navigation_node =
|
1059
|
+
case type
|
1060
|
+
when DOWN
|
1061
|
+
has_unique_navigation_nodes? ? @adaptor.create_from_type!(DOWN, 'DOWN') : @down
|
1062
|
+
else
|
1063
|
+
has_unique_navigation_nodes? ? @adaptor.create_from_type!(UP, 'UP') : @up
|
1064
|
+
end
|
1065
|
+
@nodes << navigation_node
|
1066
|
+
end
|
1067
|
+
|
1068
|
+
def at(index)
|
1069
|
+
@position == -1 and fill_buffer
|
1070
|
+
@nodes[index]
|
1071
|
+
end
|
1072
|
+
|
1073
|
+
def look(k = 1)
|
1074
|
+
@position == -1 and fill_buffer
|
1075
|
+
k == 0 and return nil
|
1076
|
+
k < 0 and return self.lookbehind(-k)
|
1077
|
+
|
1078
|
+
absolute = @position + k - 1
|
1079
|
+
return(absolute >= @nodes.length ? @eof : @nodes[absolute])
|
1080
|
+
end
|
1081
|
+
|
1082
|
+
def current_symbol
|
1083
|
+
look
|
1084
|
+
end
|
1085
|
+
|
1086
|
+
def lookbehind(k = 1)
|
1087
|
+
k == 0 and return nil
|
1088
|
+
absolute = @position - k
|
1089
|
+
return((absolute < 0) ? nil : @nodes[absolute])
|
1090
|
+
end
|
1091
|
+
|
1092
|
+
def tree_source
|
1093
|
+
@root
|
1094
|
+
end
|
1095
|
+
|
1096
|
+
def source_name
|
1097
|
+
self.token_stream.source_name
|
1098
|
+
end
|
1099
|
+
|
1100
|
+
def token_stream
|
1101
|
+
@tokens
|
1102
|
+
end
|
1103
|
+
|
1104
|
+
def token_stream=(tokens)
|
1105
|
+
@tokens = tokens
|
1106
|
+
end
|
1107
|
+
|
1108
|
+
def tree_adaptor
|
1109
|
+
@adaptor
|
1110
|
+
end
|
1111
|
+
|
1112
|
+
def has_unique_navigation_nodes?
|
1113
|
+
return @unique_navigation_nodes
|
1114
|
+
end
|
1115
|
+
attr_writer :unique_navigation_nodes
|
1116
|
+
|
1117
|
+
def consume
|
1118
|
+
@position == -1 and fill_buffer
|
1119
|
+
@position += 1
|
1120
|
+
end
|
1121
|
+
|
1122
|
+
def peek(i = 1)
|
1123
|
+
@adaptor.type_of self.look(i)
|
1124
|
+
end
|
1125
|
+
|
1126
|
+
alias >> peek
|
1127
|
+
def <<(k)
|
1128
|
+
self >> -k
|
1129
|
+
end
|
1130
|
+
|
1131
|
+
def mark
|
1132
|
+
@position == -1 and fill_buffer
|
1133
|
+
@last_marker = self.index
|
1134
|
+
return @last_marker
|
1135
|
+
end
|
1136
|
+
|
1137
|
+
def release(marker = nil)
|
1138
|
+
# do nothing?
|
1139
|
+
end
|
1140
|
+
|
1141
|
+
def index
|
1142
|
+
@position
|
1143
|
+
end
|
1144
|
+
|
1145
|
+
def rewind(marker = @last_marker, release = true)
|
1146
|
+
seek(marker)
|
1147
|
+
end
|
1148
|
+
|
1149
|
+
def seek(index)
|
1150
|
+
@position == -1 and fill_buffer
|
1151
|
+
@position = index
|
1152
|
+
end
|
1153
|
+
|
1154
|
+
def push(index)
|
1155
|
+
@calls << @position
|
1156
|
+
seek(index)
|
1157
|
+
end
|
1158
|
+
|
1159
|
+
def pop
|
1160
|
+
ret = @calls.pop and seek(ret)
|
1161
|
+
return ret
|
1162
|
+
end
|
1163
|
+
|
1164
|
+
def reset
|
1165
|
+
@position = 0
|
1166
|
+
@last_marker = 0
|
1167
|
+
@calls = []
|
1168
|
+
end
|
1169
|
+
|
1170
|
+
def replace_children(parent, start_index, stop_index, replacement_tree)
|
1171
|
+
parent.nil? or
|
1172
|
+
@adaptor.replace_children(parent, start_index,
|
1173
|
+
stop_index, replacement_tree)
|
1174
|
+
end
|
1175
|
+
|
1176
|
+
def size
|
1177
|
+
@position == -1 and fill_buffer
|
1178
|
+
return @nodes.length
|
1179
|
+
end
|
1180
|
+
|
1181
|
+
def inspect
|
1182
|
+
@position == -1 and fill_buffer
|
1183
|
+
@nodes.map { |nd| @adaptor.type_of(nd) }.join(' ')
|
1184
|
+
end
|
1185
|
+
|
1186
|
+
def to_s(start = nil, stop = nil)
|
1187
|
+
start.nil? || stop.nil? and return nil
|
1188
|
+
@position == -1 and fill_buffer
|
1189
|
+
|
1190
|
+
unless @tokens.nil?
|
1191
|
+
begin_token_index = @adaptor.token_start_index(start)
|
1192
|
+
end_token_index = @adaptor.token_stop_index(stop)
|
1193
|
+
|
1194
|
+
if @adaptor.type_of(stop) == UP
|
1195
|
+
end_token_index = @adaptor.token_stop_index(start)
|
1196
|
+
elsif @adaptor.type_of(stop) == EOF
|
1197
|
+
end_token_index = size() - 2
|
1198
|
+
end
|
1199
|
+
return @tokens.to_string(begin_token_index, end_token_index)
|
1200
|
+
end
|
1201
|
+
|
1202
|
+
t, ind = @nodes.each_with_index.find { |nd, ind| nd == start }
|
1203
|
+
|
1204
|
+
buffer = []
|
1205
|
+
until t == stop
|
1206
|
+
text = (@adaptor.text_of(t) || ' ' << @adaptor.type_of(t).to_s)
|
1207
|
+
buffer << text
|
1208
|
+
ind += 1
|
1209
|
+
t = @nodes[ind]
|
1210
|
+
end
|
1211
|
+
|
1212
|
+
text = (@adaptor.text_of(stop) || ' ' << @adaptor.type_of(stop).to_s)
|
1213
|
+
buffer << text
|
1214
|
+
|
1215
|
+
return buffer,join
|
1216
|
+
end
|
1217
|
+
|
1218
|
+
def each
|
1219
|
+
@position == -1 and fill_buffer
|
1220
|
+
block_given? or return enum_for(:each)
|
1221
|
+
@nodes.each { |node| yield(node) }
|
1222
|
+
end
|
1223
|
+
|
1224
|
+
include Enumerable
|
1225
|
+
|
1226
|
+
def to_a
|
1227
|
+
return @nodes.dup
|
1228
|
+
end
|
1229
|
+
|
1230
|
+
private
|
1231
|
+
def linear_node_index(node)
|
1232
|
+
@position == -1 and fill_buffer
|
1233
|
+
@nodes.each_with_index do |n, i|
|
1234
|
+
node == n and return(i)
|
1235
|
+
end
|
1236
|
+
return -1
|
1237
|
+
end
|
1238
|
+
|
1239
|
+
def __fill_buffer__(tree)
|
1240
|
+
nil_tree = @adaptor.flat_list?(tree)
|
1241
|
+
unless nil_tree
|
1242
|
+
@nodes << tree
|
1243
|
+
end
|
1244
|
+
|
1245
|
+
n = @adaptor.child_count(tree)
|
1246
|
+
add_navigation_node(DOWN) if not nil_tree and n > 0
|
1247
|
+
|
1248
|
+
n.times { |c| __fill_buffer__ @adaptor.child_of(tree, c) }
|
1249
|
+
|
1250
|
+
add_navigation_node(UP) if not nil_tree and n > 0
|
1251
|
+
end
|
1252
|
+
|
1253
|
+
end
|
1254
|
+
|
1255
|
+
=begin rdoc ANTLR3::AST::RewriteRuleElementStream
|
1256
|
+
|
1257
|
+
Special type of stream that is used internally by tree-building and tree-
|
1258
|
+
rewriting parsers.
|
1259
|
+
|
1260
|
+
=end
|
1261
|
+
|
1262
|
+
class RewriteRuleElementStream
|
1263
|
+
extend ClassMacros
|
1264
|
+
include Error
|
1265
|
+
|
1266
|
+
def initialize(adaptor, element_description, elements = nil)
|
1267
|
+
@cursor = 0
|
1268
|
+
@single_element = nil
|
1269
|
+
@elements = nil
|
1270
|
+
@dirty = false
|
1271
|
+
@element_description = element_description
|
1272
|
+
@adaptor = adaptor
|
1273
|
+
if elements.is_a?(Array)
|
1274
|
+
@single_element = nil
|
1275
|
+
@elements = elements
|
1276
|
+
else
|
1277
|
+
add(elements)
|
1278
|
+
end
|
1279
|
+
end
|
1280
|
+
|
1281
|
+
def reset
|
1282
|
+
@cursor = 0
|
1283
|
+
@dirty = true
|
1284
|
+
end
|
1285
|
+
|
1286
|
+
def add(el)
|
1287
|
+
return(nil) unless el
|
1288
|
+
unless @elements.nil?
|
1289
|
+
@elements << el
|
1290
|
+
return
|
1291
|
+
end
|
1292
|
+
if @single_element.nil?
|
1293
|
+
@single_element = el
|
1294
|
+
return
|
1295
|
+
end
|
1296
|
+
@elements = [@single_element, el]
|
1297
|
+
@single_element = nil
|
1298
|
+
return(@elements)
|
1299
|
+
end
|
1300
|
+
|
1301
|
+
def next_tree
|
1302
|
+
if @dirty or (@cursor >= self.length && self.length == 1)
|
1303
|
+
el = __next__()
|
1304
|
+
return self.dup(el)
|
1305
|
+
end
|
1306
|
+
el = __next__()
|
1307
|
+
return el
|
1308
|
+
end
|
1309
|
+
|
1310
|
+
abstract :dup
|
1311
|
+
|
1312
|
+
def to_tree(el)
|
1313
|
+
return el
|
1314
|
+
end
|
1315
|
+
|
1316
|
+
def has_next?
|
1317
|
+
return(!@single_element.nil? && @cursor < 1 or !@elements.nil? && @cursor < @elements.length)
|
1318
|
+
end
|
1319
|
+
|
1320
|
+
def size
|
1321
|
+
@single_element and return 1
|
1322
|
+
@elements and return @elements.length
|
1323
|
+
return 0
|
1324
|
+
end
|
1325
|
+
alias length size
|
1326
|
+
|
1327
|
+
private
|
1328
|
+
def __next__
|
1329
|
+
if self.length == 0
|
1330
|
+
raise Error::RewriteEmptyStream.new(@element_description)
|
1331
|
+
end
|
1332
|
+
if @cursor >= self.length
|
1333
|
+
self.length == 1 and return self.to_tree(@single_element)
|
1334
|
+
raise RewriteCardinalityError.new(@element_description)
|
1335
|
+
end
|
1336
|
+
unless @single_element.nil?
|
1337
|
+
@cursor += 1
|
1338
|
+
return self.to_tree(@single_element)
|
1339
|
+
end
|
1340
|
+
out = self.to_tree(@elements[@cursor])
|
1341
|
+
@cursor += 1
|
1342
|
+
return out
|
1343
|
+
end
|
1344
|
+
end
|
1345
|
+
|
1346
|
+
|
1347
|
+
=begin rdoc ANTLR3::AST::RewriteRuleTokenStream
|
1348
|
+
|
1349
|
+
Special type of stream that is used internally by tree-building and tree-
|
1350
|
+
rewriting parsers.
|
1351
|
+
|
1352
|
+
=end
|
1353
|
+
class RewriteRuleTokenStream < RewriteRuleElementStream
|
1354
|
+
def to_tree(el)
|
1355
|
+
return el
|
1356
|
+
end
|
1357
|
+
|
1358
|
+
def next_node
|
1359
|
+
t = __next__
|
1360
|
+
return @adaptor.create_with_payload!(t)
|
1361
|
+
end
|
1362
|
+
|
1363
|
+
def next
|
1364
|
+
return __next__()
|
1365
|
+
end
|
1366
|
+
|
1367
|
+
def dup(el)
|
1368
|
+
raise TypeError, "dup can't be called for a token stream"
|
1369
|
+
end
|
1370
|
+
end
|
1371
|
+
|
1372
|
+
=begin rdoc ANTLR3::AST::RewriteRuleSubtreeStream
|
1373
|
+
|
1374
|
+
Special type of stream that is used internally by tree-building and tree-
|
1375
|
+
rewriting parsers.
|
1376
|
+
|
1377
|
+
=end
|
1378
|
+
|
1379
|
+
class RewriteRuleSubtreeStream < RewriteRuleElementStream
|
1380
|
+
def next_node
|
1381
|
+
if @dirty or (@cursor >= self.length) && (self.length == 1)
|
1382
|
+
el = __next__
|
1383
|
+
return @adaptor.copy_node(el)
|
1384
|
+
end
|
1385
|
+
el = __next__
|
1386
|
+
return el
|
1387
|
+
end
|
1388
|
+
|
1389
|
+
def dup(el)
|
1390
|
+
@adaptor.copy_tree(el)
|
1391
|
+
end
|
1392
|
+
end
|
1393
|
+
|
1394
|
+
=begin rdoc ANTLR3::AST::RewriteRuleNodeStream
|
1395
|
+
|
1396
|
+
Special type of stream that is used internally by tree-building and tree-
|
1397
|
+
rewriting parsers.
|
1398
|
+
|
1399
|
+
=end
|
1400
|
+
|
1401
|
+
class RewriteRuleNodeStream < RewriteRuleElementStream
|
1402
|
+
def next_node
|
1403
|
+
__next__
|
1404
|
+
end
|
1405
|
+
def to_tree(el)
|
1406
|
+
@adaptor.copy_node(el)
|
1407
|
+
end
|
1408
|
+
def dup(el)
|
1409
|
+
raise TypeError, "dup can't be called for a node stream"
|
1410
|
+
end
|
1411
|
+
end
|
1412
|
+
end
|
1413
|
+
|
1414
|
+
include AST
|
1415
|
+
end
|