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
@@ -0,0 +1,91 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
module ANTLR3
|
5
|
+
|
6
|
+
=begin rdoc ANTLR3::Main::InteractiveStringStream
|
7
|
+
|
8
|
+
A special stream used in the <b>interactive mode</b> of the Main scripts. It
|
9
|
+
uses Readline (if available) or standard IO#gets to fetch data on demand.
|
10
|
+
|
11
|
+
=end
|
12
|
+
|
13
|
+
class InteractiveStringStream < StringStream
|
14
|
+
def initialize(options = {}, &block)
|
15
|
+
@data = ''
|
16
|
+
@size = @position = @column = @mark_depth = 0
|
17
|
+
@line = 1
|
18
|
+
@markers = []
|
19
|
+
@initialized = @eof = false
|
20
|
+
@last_marker = @name = nil
|
21
|
+
@readline = block or raise(ArgumentError, "no block was provided")
|
22
|
+
@name = options.fetch(:name, '(interactive)')
|
23
|
+
end
|
24
|
+
|
25
|
+
def <<(data)
|
26
|
+
tail = data.to_s
|
27
|
+
@size += tail.length
|
28
|
+
@data << tail
|
29
|
+
end
|
30
|
+
|
31
|
+
def consume
|
32
|
+
@position < @size and return(super)
|
33
|
+
unless @eof
|
34
|
+
readline
|
35
|
+
consume
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def peek(i = 1)
|
40
|
+
i.zero? and return 0
|
41
|
+
i += 1 if i < 0
|
42
|
+
index = @position + i - 1
|
43
|
+
index < 0 and return 0
|
44
|
+
|
45
|
+
if index < @size
|
46
|
+
char = @data[index]
|
47
|
+
elsif readline
|
48
|
+
peek(i)
|
49
|
+
else EOF
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def look(i = 1)
|
54
|
+
peek(i).chr rescue EOF
|
55
|
+
end
|
56
|
+
|
57
|
+
alias >> peek
|
58
|
+
|
59
|
+
def substring(start, stop)
|
60
|
+
fill_through(stop)
|
61
|
+
@data[start..stop]
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
def fill_through(position)
|
66
|
+
@eof and return
|
67
|
+
if position < 0 then fill_out
|
68
|
+
else readline until (@size > position or @eof)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def readline
|
73
|
+
@initialized = true
|
74
|
+
unless @eof
|
75
|
+
if line = @readline.call
|
76
|
+
self << line.to_s
|
77
|
+
return true
|
78
|
+
else
|
79
|
+
@eof = true
|
80
|
+
return false
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def fill_out
|
86
|
+
@eof and return
|
87
|
+
readline until @eof
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -0,0 +1,412 @@
|
|
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
|
+
module ANTLR3
|
36
|
+
|
37
|
+
=begin rdoc ANTLR3::TokenRewriteStream
|
38
|
+
|
39
|
+
TokenRewriteStream is a specialized form of CommonTokenStream that provides simple stream editing functionality. By creating <i>rewrite programs</i>, new text output can be created based upon the tokens in the stream. The basic token stream itself is preserved, and text output is rendered on demand using the #to_s method.
|
40
|
+
|
41
|
+
=end
|
42
|
+
|
43
|
+
class TokenRewriteStream < CommonTokenStream
|
44
|
+
|
45
|
+
=begin rdoc ANTLR3::TokenRewriteStream::RewriteOperation
|
46
|
+
|
47
|
+
RewiteOperation objects represent some particular editing command that should
|
48
|
+
be executed by a token rewrite stream at some time in future when the stream is
|
49
|
+
rendering a rewritten stream.
|
50
|
+
|
51
|
+
To perform token stream rewrites safely and efficiently, the rewrites are
|
52
|
+
executed lazily (that is, only when the rewritten text is explicitly requested).
|
53
|
+
Rewrite streams implement lazy rewriting by storing the parameters of
|
54
|
+
edit-inducing methods like +delete+ and +insert+ as RewriteOperation objects in
|
55
|
+
a rewrite program list.
|
56
|
+
|
57
|
+
The three subclasses of RewriteOperation, InsertBefore, Delete, and Replace,
|
58
|
+
define specific implementations of stream edits.
|
59
|
+
|
60
|
+
=end
|
61
|
+
|
62
|
+
unless defined?(RewriteOperation)
|
63
|
+
RewriteOperation = Struct.new(:stream, :location, :text)
|
64
|
+
end
|
65
|
+
|
66
|
+
class RewriteOperation
|
67
|
+
extend ClassMacros
|
68
|
+
@operation_name = ''
|
69
|
+
class << self
|
70
|
+
# TODO: document
|
71
|
+
attr_reader :operation_name
|
72
|
+
end
|
73
|
+
abstract :execute
|
74
|
+
|
75
|
+
# TODO: document
|
76
|
+
def name
|
77
|
+
self.class.operation_name
|
78
|
+
end
|
79
|
+
|
80
|
+
# TODO: document
|
81
|
+
def inspect
|
82
|
+
return "(%s @ %p : %p)" % [name, location, text]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
=begin rdoc ANTLR3::TokenRewriteStream::InsertBefore
|
87
|
+
|
88
|
+
Represents rewrite operation:
|
89
|
+
|
90
|
+
add string <tt>op.text</tt> to the rewrite output immediately before adding the
|
91
|
+
text content of the token at index <tt>op.index</tt>
|
92
|
+
|
93
|
+
=end
|
94
|
+
|
95
|
+
class InsertBefore < RewriteOperation
|
96
|
+
@operation_name = 'insert-before'.freeze
|
97
|
+
|
98
|
+
alias index location
|
99
|
+
alias index= location=
|
100
|
+
|
101
|
+
def execute(buffer)
|
102
|
+
buffer << text
|
103
|
+
token = stream[location]
|
104
|
+
buffer << token.text if token
|
105
|
+
return location + 1
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
=begin rdoc ANTLR3::TokenRewriteStream::Replace
|
110
|
+
|
111
|
+
Represents rewrite operation:
|
112
|
+
|
113
|
+
add text <tt>op.text</tt> to the rewrite buffer in lieu of the text of tokens
|
114
|
+
indexed within the range <tt>op.index .. op.last_index</tt>
|
115
|
+
|
116
|
+
=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
|
+
|
125
|
+
def location=(val)
|
126
|
+
case val
|
127
|
+
when Range then super(val)
|
128
|
+
else
|
129
|
+
val = val.to_i
|
130
|
+
super(val..val)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def execute(buffer)
|
135
|
+
buffer << text unless text.nil?
|
136
|
+
return(location.end + 1)
|
137
|
+
end
|
138
|
+
|
139
|
+
def index
|
140
|
+
location.first
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
=begin rdoc ANTLR3::TokenRewriteStream::Delete
|
146
|
+
|
147
|
+
Represents rewrite operation:
|
148
|
+
|
149
|
+
skip over the tokens indexed within the range <tt>op.index .. op.last_index</tt>
|
150
|
+
and do not add any text to the rewrite buffer
|
151
|
+
|
152
|
+
=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
|
+
|
168
|
+
def replace(*range_arguments)
|
169
|
+
range, text = cast_range(range_arguments, 1)
|
170
|
+
|
171
|
+
op = Replace.new(@stream, range, text)
|
172
|
+
@operations << op
|
173
|
+
return op
|
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
|
190
|
+
end
|
191
|
+
|
192
|
+
def delete(*range_arguments)
|
193
|
+
range, = cast_range(range_arguments)
|
194
|
+
op = Delete.new(@stream, range)
|
195
|
+
@operations << op
|
196
|
+
return op
|
197
|
+
end
|
198
|
+
|
199
|
+
def reduce
|
200
|
+
operations = @operations.reverse
|
201
|
+
reduced = []
|
202
|
+
|
203
|
+
until operations.empty?
|
204
|
+
operation = operations.shift
|
205
|
+
location = operation.location
|
206
|
+
|
207
|
+
case operation
|
208
|
+
when Replace
|
209
|
+
operations.delete_if do |prior_operation|
|
210
|
+
prior_location = prior_operation.location
|
211
|
+
|
212
|
+
case prior_operation
|
213
|
+
when InsertBefore
|
214
|
+
location.include?(prior_location)
|
215
|
+
when Replace
|
216
|
+
if location.covers?(prior_location)
|
217
|
+
true
|
218
|
+
elsif location.overlaps?(prior_location)
|
219
|
+
conflict!(operation, prior_operation)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
when InsertBefore
|
224
|
+
operations.delete_if do |prior_operation|
|
225
|
+
prior_location = prior_operation.location
|
226
|
+
|
227
|
+
case prior_operation
|
228
|
+
when InsertBefore
|
229
|
+
if prior_location == location
|
230
|
+
operation.text += prior_operation.text
|
231
|
+
true
|
232
|
+
end
|
233
|
+
when Replace
|
234
|
+
if location == prior_location.first
|
235
|
+
prior_operation.text = operation.text << prior_operation.text.to_s
|
236
|
+
operation = nil
|
237
|
+
break(false)
|
238
|
+
elsif prior_location.include?(location)
|
239
|
+
conflict!(operation, prior_operation)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
reduced.unshift(operation) if operation
|
246
|
+
end
|
247
|
+
|
248
|
+
@operations.replace(reduced)
|
249
|
+
|
250
|
+
@operations.inject({}) do |map, operation|
|
251
|
+
other_operaiton = map[operation.index] and
|
252
|
+
ANTLR3.bug!( Util.tidy(<<-END) % [self.class, operation, other_operaiton] )
|
253
|
+
| %s#reduce! should have left only one operation per index,
|
254
|
+
| but %p conflicts with %p
|
255
|
+
END
|
256
|
+
map[operation.index] = operation
|
257
|
+
map
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def execute(*range_arguments)
|
262
|
+
if range_arguments.empty?
|
263
|
+
range = 0 ... @stream.length
|
264
|
+
else
|
265
|
+
range, = cast_range(range_arguments)
|
266
|
+
end
|
267
|
+
|
268
|
+
output = ''
|
269
|
+
|
270
|
+
tokens = @stream.tokens
|
271
|
+
|
272
|
+
operations = reduce
|
273
|
+
|
274
|
+
cursor = range.first
|
275
|
+
while range.include?(cursor)
|
276
|
+
if operation = operations.delete(cursor)
|
277
|
+
cursor = operation.execute(output)
|
278
|
+
else
|
279
|
+
token = tokens[cursor]
|
280
|
+
output << token.text if token
|
281
|
+
cursor += 1
|
282
|
+
end
|
283
|
+
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
|
+
|
290
|
+
return output
|
291
|
+
end
|
292
|
+
|
293
|
+
def clear
|
294
|
+
@operations.clear
|
295
|
+
end
|
296
|
+
|
297
|
+
def undo(number_of_operations = 1)
|
298
|
+
@operations.pop(number_of_operations)
|
299
|
+
end
|
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)
|
319
|
+
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
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
private :conflict!, :cast_range, :check_arguments
|
348
|
+
end
|
349
|
+
|
350
|
+
attr_reader :programs
|
351
|
+
|
352
|
+
def initialize(token_source, options = {})
|
353
|
+
super(token_source, options)
|
354
|
+
|
355
|
+
@programs = Hash.new do |programs, name|
|
356
|
+
if name.is_a?(String)
|
357
|
+
programs[name] = RewriteProgram.new(self, name)
|
358
|
+
else programs[name.to_s]
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
@last_rewrite_token_indexes = {}
|
363
|
+
end
|
364
|
+
|
365
|
+
def rewrite(program_name = 'default', range = nil)
|
366
|
+
program = @programs[program_name]
|
367
|
+
if block_given?
|
368
|
+
yield(program)
|
369
|
+
program.execute(range)
|
370
|
+
else program
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
def program(name = 'default')
|
375
|
+
return @programs[name]
|
376
|
+
end
|
377
|
+
|
378
|
+
def delete_program(name = 'default')
|
379
|
+
@programs.delete(name)
|
380
|
+
end
|
381
|
+
|
382
|
+
def original_string(start = 0, finish = size - 1)
|
383
|
+
@position == -1 and fill_buffer
|
384
|
+
|
385
|
+
return(self[start..finish].map { |t| t.text }.join(''))
|
386
|
+
end
|
387
|
+
|
388
|
+
def insert_before(*args)
|
389
|
+
@programs['default'].insert_before(*args)
|
390
|
+
end
|
391
|
+
|
392
|
+
def insert_after(*args)
|
393
|
+
@programs['default'].insert_after(*args)
|
394
|
+
end
|
395
|
+
|
396
|
+
def replace(*args)
|
397
|
+
@programs['default'].replace(*args)
|
398
|
+
end
|
399
|
+
|
400
|
+
def delete(*args)
|
401
|
+
@programs['default'].delete(*args)
|
402
|
+
end
|
403
|
+
|
404
|
+
def render(*arguments)
|
405
|
+
case arguments.first
|
406
|
+
when String, Symbol then name = arguments.shift.to_s
|
407
|
+
else name = 'default'
|
408
|
+
end
|
409
|
+
@programs[name].execute(*arguments)
|
410
|
+
end
|
411
|
+
end
|
412
|
+
end
|