antlr3 1.8.0 → 1.8.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/History.txt +35 -0
- data/Manifest.txt +73 -0
- data/README.txt +6 -13
- data/java/RubyTarget.java +43 -19
- data/java/antlr-full-3.2.1.jar +0 -0
- data/lib/antlr3/debug.rb +2 -0
- data/lib/antlr3/debug/event-hub.rb +55 -55
- data/lib/antlr3/debug/record-event-listener.rb +2 -2
- data/lib/antlr3/debug/rule-tracer.rb +14 -14
- data/lib/antlr3/debug/socket.rb +47 -47
- data/lib/antlr3/debug/trace-event-listener.rb +8 -8
- data/lib/antlr3/main.rb +29 -9
- data/lib/antlr3/modes/ast-builder.rb +7 -7
- data/lib/antlr3/modes/filter.rb +19 -17
- data/lib/antlr3/profile.rb +34 -6
- data/lib/antlr3/recognizers.rb +50 -1
- data/lib/antlr3/streams.rb +19 -15
- data/lib/antlr3/streams/rewrite.rb +241 -229
- data/lib/antlr3/template/group-file-lexer.rb +6 -8
- data/lib/antlr3/template/group-file-parser.rb +16 -16
- data/lib/antlr3/template/group-file.rb +1 -1
- data/lib/antlr3/test/call-stack.rb +13 -13
- data/lib/antlr3/test/core-extensions.rb +69 -69
- data/lib/antlr3/test/functional.rb +0 -4
- data/lib/antlr3/test/grammar.rb +70 -70
- data/lib/antlr3/token.rb +41 -17
- data/lib/antlr3/tree.rb +11 -14
- data/lib/antlr3/tree/debug.rb +53 -53
- data/lib/antlr3/tree/visitor.rb +11 -11
- data/lib/antlr3/tree/wizard.rb +35 -35
- data/lib/antlr3/util.rb +18 -0
- data/lib/antlr3/version.rb +1 -1
- data/rakefile +1 -0
- data/samples/ANTLRv3Grammar.g +3 -3
- data/samples/JavaScript.g +702 -0
- data/samples/standard/C/C.g +543 -0
- data/samples/standard/C/C.tokens +175 -0
- data/samples/standard/C/C__testrig.st +0 -0
- data/samples/standard/C/c.rb +12 -0
- data/samples/standard/C/input +3479 -0
- data/samples/standard/C/output +171 -0
- data/samples/standard/LL-star/LLStar.g +101 -0
- data/samples/standard/LL-star/input +12 -0
- data/samples/standard/LL-star/ll-star.rb +12 -0
- data/samples/standard/LL-star/output +2 -0
- data/samples/standard/calc/Calculator.g +47 -0
- data/samples/standard/calc/Calculator.py +16 -0
- data/samples/standard/calc/Calculator.rb +28 -0
- data/samples/standard/cminus/CMinus.g +141 -0
- data/samples/standard/cminus/bytecode.group +80 -0
- data/samples/standard/cminus/cminus.rb +16 -0
- data/samples/standard/cminus/input +9 -0
- data/samples/standard/cminus/java.group +91 -0
- data/samples/standard/cminus/output +11 -0
- data/samples/standard/cminus/python.group +48 -0
- data/samples/standard/dynamic-scope/DynamicScopes.g +50 -0
- data/samples/standard/dynamic-scope/dynamic-scopes.rb +12 -0
- data/samples/standard/dynamic-scope/input +7 -0
- data/samples/standard/dynamic-scope/output +4 -0
- data/samples/standard/fuzzy/FuzzyJava.g +89 -0
- data/samples/standard/fuzzy/fuzzy.py +11 -0
- data/samples/standard/fuzzy/fuzzy.rb +9 -0
- data/samples/standard/fuzzy/input +13 -0
- data/samples/standard/fuzzy/output +12 -0
- data/samples/standard/hoisted-predicates/HoistedPredicates.g +40 -0
- data/samples/standard/hoisted-predicates/hoisted-predicates.rb +13 -0
- data/samples/standard/hoisted-predicates/input +1 -0
- data/samples/standard/hoisted-predicates/output +1 -0
- data/samples/standard/island-grammar/Javadoc.g +46 -0
- data/samples/standard/island-grammar/Simple.g +104 -0
- data/samples/standard/island-grammar/input +11 -0
- data/samples/standard/island-grammar/island.rb +12 -0
- data/samples/standard/island-grammar/output +16 -0
- data/samples/standard/java/Java.g +827 -0
- data/samples/standard/java/input +80 -0
- data/samples/standard/java/java.rb +13 -0
- data/samples/standard/java/output +1 -0
- data/samples/standard/python/Python.g +718 -0
- data/samples/standard/python/PythonTokenSource.rb +107 -0
- data/samples/standard/python/input +210 -0
- data/samples/standard/python/output +24 -0
- data/samples/standard/python/python.rb +14 -0
- data/samples/standard/rakefile +18 -0
- data/samples/standard/scopes/SymbolTable.g +66 -0
- data/samples/standard/scopes/input +12 -0
- data/samples/standard/scopes/output +3 -0
- data/samples/standard/scopes/scopes.rb +12 -0
- data/samples/standard/simplecTreeParser/SimpleC.g +113 -0
- data/samples/standard/simplecTreeParser/SimpleCWalker.g +64 -0
- data/samples/standard/simplecTreeParser/input +12 -0
- data/samples/standard/simplecTreeParser/output +1 -0
- data/samples/standard/simplecTreeParser/simplec.rb +18 -0
- data/samples/standard/treeparser/Lang.g +24 -0
- data/samples/standard/treeparser/LangDumpDecl.g +17 -0
- data/samples/standard/treeparser/input +1 -0
- data/samples/standard/treeparser/output +2 -0
- data/samples/standard/treeparser/treeparser.rb +18 -0
- data/samples/standard/tweak/Tweak.g +68 -0
- data/samples/standard/tweak/input +9 -0
- data/samples/standard/tweak/output +16 -0
- data/samples/standard/tweak/tweak.rb +13 -0
- data/samples/standard/xml/README +16 -0
- data/samples/standard/xml/XML.g +123 -0
- data/samples/standard/xml/input +21 -0
- data/samples/standard/xml/output +39 -0
- data/samples/standard/xml/xml.rb +9 -0
- data/templates/Ruby.stg +4 -4
- data/test/functional/ast-output/auto-ast.rb +0 -5
- data/test/functional/ast-output/rewrites.rb +4 -4
- data/test/unit/test-scope.rb +45 -0
- metadata +96 -8
data/lib/antlr3/profile.rb
CHANGED
|
@@ -1,6 +1,37 @@
|
|
|
1
1
|
#!/usr/bin/ruby
|
|
2
2
|
# encoding: utf-8
|
|
3
3
|
|
|
4
|
+
=begin LICENSE
|
|
5
|
+
|
|
6
|
+
[The "BSD licence"]
|
|
7
|
+
Copyright (c) 2009-2010 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
|
+
|
|
4
35
|
module ANTLR3
|
|
5
36
|
module Profile
|
|
6
37
|
=begin rdoc ANTLR3::Profile::ParserEvents
|
|
@@ -52,9 +83,6 @@ class DataSet < ::Array
|
|
|
52
83
|
end
|
|
53
84
|
|
|
54
85
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
86
|
unless const_defined?( :Profile )
|
|
59
87
|
Profile = Struct.new(
|
|
60
88
|
:grammar_file, :parser_class, :top_rule,
|
|
@@ -231,7 +259,7 @@ class Profiler
|
|
|
231
259
|
|
|
232
260
|
def enter_decision( decision_number )
|
|
233
261
|
@decision_level += 1
|
|
234
|
-
starting_look_index = @parser.
|
|
262
|
+
starting_look_index = @parser.input.index
|
|
235
263
|
@look_stack << starting_look_index
|
|
236
264
|
end
|
|
237
265
|
|
|
@@ -262,7 +290,7 @@ class Profiler
|
|
|
262
290
|
def look( i, token )
|
|
263
291
|
in_decision? or return
|
|
264
292
|
starting_index = look_stack.last
|
|
265
|
-
input = @parser.
|
|
293
|
+
input = @parser.input
|
|
266
294
|
this_ref_index = input.index
|
|
267
295
|
num_hidden = input.tokens( starting_index, this_ref_index ).count { |t| t.hidden? }
|
|
268
296
|
depth = i + this_ref_index - starting_index - num_hidden
|
|
@@ -284,7 +312,7 @@ class Profiler
|
|
|
284
312
|
end
|
|
285
313
|
|
|
286
314
|
def terminate
|
|
287
|
-
input = @parser.
|
|
315
|
+
input = @parser.input
|
|
288
316
|
hidden_tokens = input.select { |token| token.hidden? }
|
|
289
317
|
@profile.hidden_tokens = hidden_tokens.length
|
|
290
318
|
@profile.tokens = input.tokens.length
|
data/lib/antlr3/recognizers.rb
CHANGED
|
@@ -124,6 +124,52 @@ end
|
|
|
124
124
|
|
|
125
125
|
end # unless const_defined?( :RecognizerSharedState )
|
|
126
126
|
|
|
127
|
+
=begin rdoc ANTLR3::Recognizer
|
|
128
|
+
|
|
129
|
+
= Scope
|
|
130
|
+
|
|
131
|
+
Scope is used to represent instances of ANTLR's various attribute scopes.
|
|
132
|
+
It is identical to Ruby's built-in Struct class, but it takes string
|
|
133
|
+
attribute declarations from the ANTLR grammar as parameters, and overrides
|
|
134
|
+
the #initialize method to set the default values if any are present in
|
|
135
|
+
the scope declaration.
|
|
136
|
+
|
|
137
|
+
Block = Scope.new( "name", "depth = 0", "variables = {}" )
|
|
138
|
+
Block.new # => #<struct Block name=nil, depth=0, variables={}>
|
|
139
|
+
Block.new( "function" ) # => #<struct Block name="function", depth=0, variables={}>
|
|
140
|
+
Block.new( 'a', 1, :x => 3 ) # => #<struct Block name="a", depth=1, variables={ :x => 3 }>
|
|
141
|
+
|
|
142
|
+
=end
|
|
143
|
+
|
|
144
|
+
class Scope < ::Struct
|
|
145
|
+
def self.new( *declarations, &body )
|
|
146
|
+
names = []
|
|
147
|
+
defaults = {}
|
|
148
|
+
for decl in declarations
|
|
149
|
+
name, default = decl.to_s.split( /\s*=\s*/, 2 )
|
|
150
|
+
names << ( name = name.to_sym )
|
|
151
|
+
default and defaults[ name ] = default
|
|
152
|
+
end
|
|
153
|
+
super( *names ) do
|
|
154
|
+
|
|
155
|
+
# If no defaults, leave the initialize method the same as
|
|
156
|
+
# the struct's default initialize for speed. Otherwise,
|
|
157
|
+
# overwrite the initialize to populate with default values.
|
|
158
|
+
unless defaults.empty?
|
|
159
|
+
parameters = names.map do | name |
|
|
160
|
+
"#{ name } = " << defaults.fetch( name, 'nil' )
|
|
161
|
+
end.join( ', ' )
|
|
162
|
+
class_eval( <<-END )
|
|
163
|
+
def initialize( #{ parameters } )
|
|
164
|
+
super( #{ names.join( ', ' ) } )
|
|
165
|
+
end
|
|
166
|
+
END
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
body and class_eval( &body )
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
127
173
|
|
|
128
174
|
=begin rdoc ANTLR3::Recognizer
|
|
129
175
|
|
|
@@ -158,7 +204,6 @@ class Recognizer
|
|
|
158
204
|
|
|
159
205
|
# inherited class methods and hooks
|
|
160
206
|
class << self
|
|
161
|
-
|
|
162
207
|
attr_reader :grammar_file_name,
|
|
163
208
|
:antlr_version,
|
|
164
209
|
:antlr_version_string,
|
|
@@ -262,6 +307,10 @@ class Recognizer
|
|
|
262
307
|
return false
|
|
263
308
|
end
|
|
264
309
|
|
|
310
|
+
def Scope( *declarations, &body )
|
|
311
|
+
Scope.new( *declarations, &body )
|
|
312
|
+
end
|
|
313
|
+
|
|
265
314
|
def token_class
|
|
266
315
|
@token_class ||= begin
|
|
267
316
|
self::Token rescue
|
data/lib/antlr3/streams.rb
CHANGED
|
@@ -173,46 +173,51 @@ module Stream
|
|
|
173
173
|
abstract :consume
|
|
174
174
|
|
|
175
175
|
##
|
|
176
|
-
# :method: peek(k=1)
|
|
176
|
+
# :method: peek( k = 1 )
|
|
177
177
|
# used to quickly retreive the object of interest to a recognizer at lookahead
|
|
178
178
|
# position specified by <tt>k</tt> (such as integer value of a character or an
|
|
179
179
|
# integer token type)
|
|
180
180
|
abstract :peek
|
|
181
181
|
|
|
182
182
|
##
|
|
183
|
-
# :method: look(k=1)
|
|
183
|
+
# :method: look( k = 1 )
|
|
184
184
|
# used to retreive the full object of interest at lookahead position specified
|
|
185
185
|
# by <tt>k</tt> (such as a character string or a token structure)
|
|
186
186
|
abstract :look
|
|
187
187
|
|
|
188
188
|
##
|
|
189
189
|
# :method: mark
|
|
190
|
-
#
|
|
190
|
+
# saves the current position for the purposes of backtracking and
|
|
191
|
+
# returns a value to pass to #rewind at a later time
|
|
191
192
|
abstract :mark
|
|
192
193
|
|
|
193
194
|
##
|
|
194
195
|
# :method: index
|
|
195
|
-
#
|
|
196
|
+
# returns the current position of the stream
|
|
196
197
|
abstract :index
|
|
197
198
|
|
|
198
199
|
##
|
|
199
|
-
# :method: rewind(marker=last_marker)
|
|
200
|
-
#
|
|
200
|
+
# :method: rewind( marker = last_marker )
|
|
201
|
+
# restores the stream position using the state information previously saved
|
|
202
|
+
# by the given marker
|
|
201
203
|
abstract :rewind
|
|
202
204
|
|
|
203
205
|
##
|
|
204
|
-
# :method: release(marker = last_marker)
|
|
205
|
-
#
|
|
206
|
+
# :method: release( marker = last_marker )
|
|
207
|
+
# clears the saved state information associated with the given marker value
|
|
206
208
|
abstract :release
|
|
207
209
|
|
|
208
210
|
##
|
|
209
|
-
# :method: seek(position)
|
|
210
|
-
#
|
|
211
|
+
# :method: seek( position )
|
|
212
|
+
# move the stream to the given absolute index given by +position+
|
|
211
213
|
abstract :seek
|
|
212
214
|
|
|
213
|
-
|
|
215
|
+
##
|
|
216
|
+
# the total number of symbols in the stream
|
|
214
217
|
attr_reader :size
|
|
215
|
-
|
|
218
|
+
|
|
219
|
+
##
|
|
220
|
+
# indicates an identifying name for the stream -- usually the file path of the input
|
|
216
221
|
attr_accessor :source_name
|
|
217
222
|
end
|
|
218
223
|
|
|
@@ -252,7 +257,6 @@ module CharacterStream
|
|
|
252
257
|
include Stream
|
|
253
258
|
extend ClassMacros
|
|
254
259
|
include Constants
|
|
255
|
-
#EOF = -1
|
|
256
260
|
|
|
257
261
|
##
|
|
258
262
|
# :method: substring(start,stop)
|
|
@@ -328,8 +332,8 @@ module TokenStream
|
|
|
328
332
|
abstract :to_s
|
|
329
333
|
|
|
330
334
|
##
|
|
331
|
-
# :method: at
|
|
332
|
-
#
|
|
335
|
+
# :method: at( i )
|
|
336
|
+
# return the stream symbol at index +i+
|
|
333
337
|
abstract :at
|
|
334
338
|
end
|
|
335
339
|
|
|
@@ -42,6 +42,10 @@ TokenRewriteStream is a specialized form of CommonTokenStream that provides simp
|
|
|
42
42
|
|
|
43
43
|
class TokenRewriteStream < CommonTokenStream
|
|
44
44
|
|
|
45
|
+
unless defined?( RewriteOperation )
|
|
46
|
+
RewriteOperation = Struct.new( :stream, :location, :text )
|
|
47
|
+
end
|
|
48
|
+
|
|
45
49
|
=begin rdoc ANTLR3::TokenRewriteStream::RewriteOperation
|
|
46
50
|
|
|
47
51
|
RewiteOperation objects represent some particular editing command that should
|
|
@@ -59,29 +63,34 @@ define specific implementations of stream edits.
|
|
|
59
63
|
|
|
60
64
|
=end
|
|
61
65
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
class
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
66
|
+
class RewriteOperation
|
|
67
|
+
extend ClassMacros
|
|
68
|
+
@operation_name = ''
|
|
69
|
+
|
|
70
|
+
class << self
|
|
71
|
+
##
|
|
72
|
+
# the printable name of operations represented by the class -- used for inspection
|
|
73
|
+
attr_reader :operation_name
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
##
|
|
77
|
+
# :method: execute( buffer )
|
|
78
|
+
# run the rewrite operation represented by this object and append the output to +buffer+
|
|
79
|
+
abstract :execute
|
|
80
|
+
|
|
81
|
+
##
|
|
82
|
+
# return the name of this operation as set by its class
|
|
83
|
+
def name
|
|
84
|
+
self.class.operation_name
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
##
|
|
88
|
+
# return a compact, readable representation of this operation
|
|
89
|
+
def inspect
|
|
90
|
+
return "(%s @ %p : %p)" % [ name, location, text ]
|
|
91
|
+
end
|
|
78
92
|
end
|
|
79
93
|
|
|
80
|
-
# TODO: document
|
|
81
|
-
def inspect
|
|
82
|
-
return "(%s @ %p : %p)" % [ name, location, text ]
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
94
|
|
|
86
95
|
=begin rdoc ANTLR3::TokenRewriteStream::InsertBefore
|
|
87
96
|
|
|
@@ -91,21 +100,21 @@ add string <tt>op.text</tt> to the rewrite output immediately before adding the
|
|
|
91
100
|
text content of the token at index <tt>op.index</tt>
|
|
92
101
|
|
|
93
102
|
=end
|
|
94
|
-
|
|
95
|
-
class InsertBefore < RewriteOperation
|
|
96
|
-
@operation_name = 'insert-before'.freeze
|
|
97
103
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
class InsertBefore < RewriteOperation
|
|
105
|
+
@operation_name = 'insert-before'.freeze
|
|
106
|
+
|
|
107
|
+
alias index location
|
|
108
|
+
alias index= location=
|
|
109
|
+
|
|
110
|
+
def execute( buffer )
|
|
111
|
+
buffer << text.to_s
|
|
112
|
+
token = stream[ location ]
|
|
113
|
+
buffer << token.text.to_s if token
|
|
114
|
+
return location + 1
|
|
115
|
+
end
|
|
106
116
|
end
|
|
107
|
-
|
|
108
|
-
|
|
117
|
+
|
|
109
118
|
=begin rdoc ANTLR3::TokenRewriteStream::Replace
|
|
110
119
|
|
|
111
120
|
Represents rewrite operation:
|
|
@@ -114,34 +123,36 @@ add text <tt>op.text</tt> to the rewrite buffer in lieu of the text of tokens
|
|
|
114
123
|
indexed within the range <tt>op.index .. op.last_index</tt>
|
|
115
124
|
|
|
116
125
|
=end
|
|
117
|
-
|
|
118
|
-
class Replace < RewriteOperation
|
|
119
|
-
@operation_name = 'replace'.freeze
|
|
120
|
-
def initialize( stream, location, text )
|
|
121
|
-
super( stream, nil, text )
|
|
122
|
-
self.location = location
|
|
123
|
-
end
|
|
124
126
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
super(
|
|
127
|
+
class Replace < RewriteOperation
|
|
128
|
+
|
|
129
|
+
@operation_name = 'replace'.freeze
|
|
130
|
+
|
|
131
|
+
def initialize( stream, location, text )
|
|
132
|
+
super( stream, nil, text )
|
|
133
|
+
self.location = location
|
|
131
134
|
end
|
|
135
|
+
|
|
136
|
+
def location=( val )
|
|
137
|
+
case val
|
|
138
|
+
when Range then super( val )
|
|
139
|
+
else
|
|
140
|
+
val = val.to_i
|
|
141
|
+
super( val..val )
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def execute( buffer )
|
|
146
|
+
buffer << text.to_s unless text.nil?
|
|
147
|
+
return( location.end + 1 )
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def index
|
|
151
|
+
location.first
|
|
152
|
+
end
|
|
153
|
+
|
|
132
154
|
end
|
|
133
155
|
|
|
134
|
-
def execute( buffer )
|
|
135
|
-
buffer << text.to_s unless text.nil?
|
|
136
|
-
return( location.end + 1 )
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
def index
|
|
140
|
-
location.first
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
end
|
|
144
|
-
|
|
145
156
|
=begin rdoc ANTLR3::TokenRewriteStream::Delete
|
|
146
157
|
|
|
147
158
|
Represents rewrite operation:
|
|
@@ -150,203 +161,204 @@ skip over the tokens indexed within the range <tt>op.index .. op.last_index</tt>
|
|
|
150
161
|
and do not add any text to the rewrite buffer
|
|
151
162
|
|
|
152
163
|
=end
|
|
153
|
-
|
|
154
|
-
class Delete < Replace
|
|
155
|
-
@operation_name = 'delete'.freeze
|
|
156
|
-
def initialize( stream, location )
|
|
157
|
-
super( stream, location, nil )
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
class RewriteProgram
|
|
162
|
-
def initialize( stream, name = nil )
|
|
163
|
-
@stream = stream
|
|
164
|
-
@name = name
|
|
165
|
-
@operations = []
|
|
166
|
-
end
|
|
167
164
|
|
|
168
|
-
|
|
169
|
-
|
|
165
|
+
class Delete < Replace
|
|
166
|
+
@operation_name = 'delete'.freeze
|
|
170
167
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
def insert_before( index, text )
|
|
177
|
-
index = index.to_i
|
|
178
|
-
index < 0 and index += @stream.length
|
|
179
|
-
op = InsertBefore.new( @stream, index, text )
|
|
180
|
-
@operations << op
|
|
181
|
-
return op
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
def insert_after( index, text )
|
|
185
|
-
index = index.to_i
|
|
186
|
-
index < 0 and index += @stream.length
|
|
187
|
-
op = InsertBefore.new( @stream, index + 1, text )
|
|
188
|
-
@operations << op
|
|
189
|
-
return op
|
|
168
|
+
def initialize( stream, location )
|
|
169
|
+
super( stream, location, nil )
|
|
170
|
+
end
|
|
190
171
|
end
|
|
191
172
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
def reduce
|
|
200
|
-
operations = @operations.reverse
|
|
201
|
-
reduced = []
|
|
173
|
+
class RewriteProgram
|
|
174
|
+
def initialize( stream, name = nil )
|
|
175
|
+
@stream = stream
|
|
176
|
+
@name = name
|
|
177
|
+
@operations = []
|
|
178
|
+
end
|
|
202
179
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
location = operation.location
|
|
180
|
+
def replace( *range_arguments )
|
|
181
|
+
range, text = cast_range( range_arguments, 1 )
|
|
206
182
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
183
|
+
op = Replace.new( @stream, range, text )
|
|
184
|
+
@operations << op
|
|
185
|
+
return op
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def insert_before( index, text )
|
|
189
|
+
index = index.to_i
|
|
190
|
+
index < 0 and index += @stream.length
|
|
191
|
+
op = InsertBefore.new( @stream, index, text )
|
|
192
|
+
@operations << op
|
|
193
|
+
return op
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def insert_after( index, text )
|
|
197
|
+
index = index.to_i
|
|
198
|
+
index < 0 and index += @stream.length
|
|
199
|
+
op = InsertBefore.new( @stream, index + 1, text )
|
|
200
|
+
@operations << op
|
|
201
|
+
return op
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def delete( *range_arguments )
|
|
205
|
+
range, = cast_range( range_arguments )
|
|
206
|
+
op = Delete.new( @stream, range )
|
|
207
|
+
@operations << op
|
|
208
|
+
return op
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def reduce
|
|
212
|
+
operations = @operations.reverse
|
|
213
|
+
reduced = []
|
|
214
|
+
|
|
215
|
+
until operations.empty?
|
|
216
|
+
operation = operations.shift
|
|
217
|
+
location = operation.location
|
|
218
|
+
|
|
219
|
+
case operation
|
|
220
|
+
when Replace
|
|
221
|
+
operations.delete_if do |prior_operation|
|
|
222
|
+
prior_location = prior_operation.location
|
|
223
|
+
|
|
224
|
+
case prior_operation
|
|
225
|
+
when InsertBefore
|
|
226
|
+
location.include?( prior_location )
|
|
227
|
+
when Replace
|
|
228
|
+
if location.covers?( prior_location )
|
|
229
|
+
true
|
|
230
|
+
elsif location.overlaps?( prior_location )
|
|
231
|
+
conflict!( operation, prior_operation )
|
|
232
|
+
end
|
|
220
233
|
end
|
|
221
234
|
end
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
235
|
+
when InsertBefore
|
|
236
|
+
operations.delete_if do |prior_operation|
|
|
237
|
+
prior_location = prior_operation.location
|
|
238
|
+
|
|
239
|
+
case prior_operation
|
|
240
|
+
when InsertBefore
|
|
241
|
+
if prior_location == location
|
|
242
|
+
operation.text += prior_operation.text
|
|
243
|
+
true
|
|
244
|
+
end
|
|
245
|
+
when Replace
|
|
246
|
+
if location == prior_location.first
|
|
247
|
+
prior_operation.text = operation.text << prior_operation.text.to_s
|
|
248
|
+
operation = nil
|
|
249
|
+
break( false )
|
|
250
|
+
elsif prior_location.include?( location )
|
|
251
|
+
conflict!( operation, prior_operation )
|
|
252
|
+
end
|
|
240
253
|
end
|
|
241
254
|
end
|
|
242
255
|
end
|
|
256
|
+
|
|
257
|
+
reduced.unshift( operation ) if operation
|
|
243
258
|
end
|
|
244
259
|
|
|
245
|
-
|
|
260
|
+
@operations.replace( reduced )
|
|
261
|
+
|
|
262
|
+
@operations.inject( {} ) do |map, operation|
|
|
263
|
+
other_operaiton = map[ operation.index ] and
|
|
264
|
+
ANTLR3.bug!( Util.tidy( <<-END ) % [ self.class, operation, other_operaiton ] )
|
|
265
|
+
| %s#reduce! should have left only one operation per index,
|
|
266
|
+
| but %p conflicts with %p
|
|
267
|
+
END
|
|
268
|
+
map[ operation.index ] = operation
|
|
269
|
+
map
|
|
270
|
+
end
|
|
246
271
|
end
|
|
247
272
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
273
|
+
def execute( *range_arguments )
|
|
274
|
+
if range_arguments.empty?
|
|
275
|
+
range = 0 ... @stream.length
|
|
276
|
+
else
|
|
277
|
+
range, = cast_range( range_arguments )
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
output = ''
|
|
281
|
+
|
|
282
|
+
tokens = @stream.tokens
|
|
283
|
+
|
|
284
|
+
operations = reduce
|
|
285
|
+
|
|
286
|
+
cursor = range.first
|
|
287
|
+
while range.include?( cursor )
|
|
288
|
+
if operation = operations.delete( cursor )
|
|
289
|
+
cursor = operation.execute( output )
|
|
290
|
+
else
|
|
291
|
+
token = tokens[ cursor ]
|
|
292
|
+
output << token.text if token
|
|
293
|
+
cursor += 1
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
if operation = operations.delete( cursor ) and
|
|
297
|
+
operation.is_a?( InsertBefore )
|
|
298
|
+
# catch edge 'insert-after' operations
|
|
299
|
+
operation.execute( output )
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
return output
|
|
266
303
|
end
|
|
267
304
|
|
|
268
|
-
|
|
305
|
+
def clear
|
|
306
|
+
@operations.clear
|
|
307
|
+
end
|
|
269
308
|
|
|
270
|
-
|
|
309
|
+
def undo( number_of_operations = 1 )
|
|
310
|
+
@operations.pop( number_of_operations )
|
|
311
|
+
end
|
|
271
312
|
|
|
272
|
-
|
|
313
|
+
def conflict!( current, previous )
|
|
314
|
+
message = 'operation %p overlaps with previous operation %p' % [ current, previous ]
|
|
315
|
+
raise( RangeError, message, caller )
|
|
316
|
+
end
|
|
273
317
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
318
|
+
def cast_range( args, extra = 0 )
|
|
319
|
+
single, pair = extra + 1, extra + 2
|
|
320
|
+
case check_arguments( args, single, pair )
|
|
321
|
+
when single
|
|
322
|
+
loc = args.shift
|
|
323
|
+
|
|
324
|
+
if loc.is_a?( Range )
|
|
325
|
+
first, last = loc.first.to_i, loc.last.to_i
|
|
326
|
+
loc.exlude_end? and last -= 1
|
|
327
|
+
return cast_range( args.unshift( first, last ), extra )
|
|
328
|
+
else
|
|
329
|
+
loc = loc.to_i
|
|
330
|
+
return cast_range( args.unshift( loc, loc ), extra )
|
|
331
|
+
end
|
|
332
|
+
when pair
|
|
333
|
+
first, last = args.shift( 2 ).map! { |arg| arg.to_i }
|
|
334
|
+
if first < 0 and last < 0
|
|
335
|
+
first += @stream.length
|
|
336
|
+
last += @stream.length
|
|
337
|
+
else
|
|
338
|
+
last < 0 and last += @stream.length
|
|
339
|
+
first = first.at_least( 0 )
|
|
340
|
+
end
|
|
341
|
+
return( args.unshift( first .. last ) )
|
|
282
342
|
end
|
|
283
343
|
end
|
|
284
|
-
if operation = operations.delete( cursor ) and
|
|
285
|
-
operation.is_a?( InsertBefore )
|
|
286
|
-
# catch edge 'insert-after' operations
|
|
287
|
-
operation.execute( output )
|
|
288
|
-
end
|
|
289
344
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
def conflict!( current, previous )
|
|
302
|
-
message = 'operation %p overlaps with previous operation %p' % [ current, previous ]
|
|
303
|
-
raise( RangeError, message, caller )
|
|
304
|
-
end
|
|
305
|
-
|
|
306
|
-
def cast_range( args, extra = 0 )
|
|
307
|
-
single, pair = extra + 1, extra + 2
|
|
308
|
-
case check_arguments( args, single, pair )
|
|
309
|
-
when single
|
|
310
|
-
loc = args.shift
|
|
311
|
-
|
|
312
|
-
if loc.is_a?( Range )
|
|
313
|
-
first, last = loc.first.to_i, loc.last.to_i
|
|
314
|
-
loc.exlude_end? and last -= 1
|
|
315
|
-
return cast_range( args.unshift( first, last ), extra )
|
|
316
|
-
else
|
|
317
|
-
loc = loc.to_i
|
|
318
|
-
return cast_range( args.unshift( loc, loc ), extra )
|
|
345
|
+
def check_arguments( args, min, max )
|
|
346
|
+
n = args.length
|
|
347
|
+
if n < min
|
|
348
|
+
raise ArgumentError,
|
|
349
|
+
"wrong number of arguments (#{ args.length } for #{ min })",
|
|
350
|
+
caller
|
|
351
|
+
elsif n > max
|
|
352
|
+
raise ArgumentError,
|
|
353
|
+
"wrong number of arguments (#{ args.length } for #{ max })",
|
|
354
|
+
caller
|
|
355
|
+
else return n
|
|
319
356
|
end
|
|
320
|
-
when pair
|
|
321
|
-
first, last = args.shift( 2 ).map! { |arg| arg.to_i }
|
|
322
|
-
if first < 0 and last < 0
|
|
323
|
-
first += @stream.length
|
|
324
|
-
last += @stream.length
|
|
325
|
-
else
|
|
326
|
-
last < 0 and last += @stream.length
|
|
327
|
-
first = first.at_least( 0 )
|
|
328
|
-
end
|
|
329
|
-
return( args.unshift( first .. last ) )
|
|
330
|
-
end
|
|
331
|
-
end
|
|
332
|
-
|
|
333
|
-
def check_arguments( args, min, max )
|
|
334
|
-
n = args.length
|
|
335
|
-
if n < min
|
|
336
|
-
raise ArgumentError,
|
|
337
|
-
"wrong number of arguments (#{ args.length } for #{ min })",
|
|
338
|
-
caller
|
|
339
|
-
elsif n > max
|
|
340
|
-
raise ArgumentError,
|
|
341
|
-
"wrong number of arguments (#{ args.length } for #{ max })",
|
|
342
|
-
caller
|
|
343
|
-
else return n
|
|
344
357
|
end
|
|
358
|
+
|
|
359
|
+
private :conflict!, :cast_range, :check_arguments
|
|
345
360
|
end
|
|
346
|
-
|
|
347
|
-
private :conflict!, :cast_range, :check_arguments
|
|
348
|
-
end
|
|
349
|
-
|
|
361
|
+
|
|
350
362
|
attr_reader :programs
|
|
351
363
|
|
|
352
364
|
def initialize( token_source, options = {} )
|