myco 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/myco/bootstrap/find_constant.rb +4 -11
- data/lib/myco/code_loader.rb +2 -1
- data/lib/myco/code_tools/AST/ConstantAccess.my +47 -3
- data/lib/myco/code_tools/AST/ConstantAccess.my.rb +13 -9
- data/lib/myco/code_tools/AST/ConstantAssignment.my +1 -5
- data/lib/myco/code_tools/AST/ConstantAssignment.my.rb +3 -9
- data/lib/myco/code_tools/AST/ToRuby.my +5 -2
- data/lib/myco/code_tools/AST/ToRuby.my.rb +7 -3
- data/lib/myco/code_tools/AST.my +1 -0
- data/lib/myco/code_tools/AST.my.rb +9 -1
- data/lib/myco/code_tools/Parser.my +24 -0
- data/lib/myco/code_tools/Parser.my.rb +25 -0
- data/lib/myco/code_tools/parser/MycoBuilder.my +67 -0
- data/lib/myco/code_tools/parser/MycoBuilder.my.rb +99 -0
- data/lib/myco/code_tools/parser/MycoCharacterClasses.my +20 -0
- data/lib/myco/code_tools/parser/MycoCharacterClasses.my.rb +56 -0
- data/lib/myco/code_tools/parser/MycoGrammar.my +564 -0
- data/lib/myco/code_tools/parser/MycoGrammar.my.rb +1851 -0
- data/lib/myco/code_tools/parser/MycoTokens.my +78 -0
- data/lib/myco/code_tools/parser/MycoTokens.my.rb +170 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Builder.my +4 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Builder.my.rb +5 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeHelpers.my +142 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeHelpers.my.rb +181 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeInstructions.my +420 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeInstructions.my.rb +415 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeParser.my +137 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeParser.my.rb +237 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Constructions.my +183 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Constructions.my.rb +370 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Grammar.my +65 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Grammar.my.rb +83 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Instructions.my +139 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Instructions.my.rb +284 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Machine.my +37 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Machine.my.rb +24 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Parser.my +42 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Parser.my.rb +52 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Patterns.my +123 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Patterns.my.rb +164 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Processor.my +236 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Processor.my.rb +339 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces.my +15 -0
- data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces.my.rb +14 -0
- data/lib/myco/code_tools.rb +1 -1
- data/lib/myco/version.rb +1 -1
- data/lib/myco.rb +2 -0
- metadata +44 -25
- data/lib/myco/code_tools/parser/peg_parser.rb +0 -7182
- data/lib/myco/code_tools/parser.rb +0 -39
@@ -0,0 +1,237 @@
|
|
1
|
+
|
2
|
+
::Myco::Component.new([::Myco::FileToplevel], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
3
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(::Myco.cscope.for_method_definition.const_set(:BytecodeParser, ::Myco::Component.new([::Myco.find_constant(:BasicObject)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
4
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(
|
5
|
+
declare_meme(:grammar, [[:var, []]], nil, ::Myco.cscope.dup) { |*| (::Myco::Component.new([::Myco.find_constant(:Grammar)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
6
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {nil}}.instance)}
|
7
|
+
declare_meme(:new_worker, [], nil, ::Myco.cscope.dup) { |*| (self.set_up_worker(self.prototype.new))}
|
8
|
+
declare_meme(:prototype, [[:var, []]], nil, ::Myco.cscope.dup) { |*| (self.compile_prototype)}
|
9
|
+
declare_meme(:refresh, [], nil, ::Myco.cscope.dup) { |*| (self.__send__(
|
10
|
+
:prototype=,
|
11
|
+
self.compile_prototype
|
12
|
+
))}
|
13
|
+
declare_meme(:compile_prototype, [], nil, ::Myco.cscope.dup) { |*| (
|
14
|
+
proto = ::Myco.find_constant(:Component).new
|
15
|
+
self.grammar.construct_all_rules
|
16
|
+
self.grammar.rule_table.each { |name, rule| (self.compile_rule_into(
|
17
|
+
proto,
|
18
|
+
name,
|
19
|
+
rule
|
20
|
+
))}
|
21
|
+
proto
|
22
|
+
)}
|
23
|
+
declare_meme(:compile_rule_into, [], nil, ::Myco.cscope.dup) { |proto, name, rule| (
|
24
|
+
construct = rule.construct_rule
|
25
|
+
proto.dynamic_method(
|
26
|
+
name,
|
27
|
+
"(compiled parser)"
|
28
|
+
) { |g| (
|
29
|
+
instructor = ::Myco::Component.new([::Myco.find_constant(:BytecodeInstructions)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
30
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {nil}}.instance
|
31
|
+
instructor.__send__(
|
32
|
+
:g=,
|
33
|
+
g
|
34
|
+
)
|
35
|
+
g.extend(::Myco.find_constant(:BytecodeHelpers))
|
36
|
+
g.rule_start
|
37
|
+
construct.bytecode(instructor)
|
38
|
+
g.rule_finish
|
39
|
+
)}
|
40
|
+
)}
|
41
|
+
declare_meme(:compile_generator, [], nil, ::Myco.cscope.dup) { |name, file, line=1, &block| (
|
42
|
+
g = ::Myco.find_constant(:Myco)::ToolSet::Generator.new
|
43
|
+
g.__send__(
|
44
|
+
:name=,
|
45
|
+
name
|
46
|
+
)
|
47
|
+
g.__send__(
|
48
|
+
:file=,
|
49
|
+
file
|
50
|
+
)
|
51
|
+
g.set_line(line)
|
52
|
+
block.call(g)
|
53
|
+
g.ret
|
54
|
+
g.close
|
55
|
+
g.use_detected
|
56
|
+
g
|
57
|
+
)}
|
58
|
+
declare_meme(:compile_code, [], nil, ::Myco.cscope.dup) { |name, file, line=1, &block| (
|
59
|
+
g = self.compile_generator(
|
60
|
+
name,
|
61
|
+
file,
|
62
|
+
line,
|
63
|
+
&block
|
64
|
+
)
|
65
|
+
g.encode
|
66
|
+
g.package(::Myco.find_constant(:Rubinius)::CompiledCode)
|
67
|
+
)}
|
68
|
+
declare_meme(:save_prototype, [], nil, ::Myco.cscope.dup) { |filename| (
|
69
|
+
code = self.compile_code(
|
70
|
+
:__script__,
|
71
|
+
:"(snippet)"
|
72
|
+
) { |g| (
|
73
|
+
g.push_cpath_top
|
74
|
+
g.find_const(:Class)
|
75
|
+
g.create_block(self.compile_generator(
|
76
|
+
:__block__,
|
77
|
+
:"(snippet)"
|
78
|
+
) { |g| (self.prototype.instance_methods.each { |name| (
|
79
|
+
code = self.prototype.instance_method(name).executable
|
80
|
+
self.__send__(
|
81
|
+
:if,
|
82
|
+
code.__send__(
|
83
|
+
:is_a?,
|
84
|
+
::Myco.find_constant(:Rubinius)::CompiledCode
|
85
|
+
)
|
86
|
+
) { || (
|
87
|
+
g.push_rubinius
|
88
|
+
g.push_literal(name)
|
89
|
+
g.push_literal(code)
|
90
|
+
g.push_scope
|
91
|
+
g.push_variables
|
92
|
+
g.send(
|
93
|
+
:method_visibility,
|
94
|
+
0
|
95
|
+
)
|
96
|
+
g.send(
|
97
|
+
:add_defn_method,
|
98
|
+
4
|
99
|
+
)
|
100
|
+
)}
|
101
|
+
)})})
|
102
|
+
g.send_with_block(
|
103
|
+
:new,
|
104
|
+
0
|
105
|
+
)
|
106
|
+
)}
|
107
|
+
::Myco.find_constant(:Myco)::ToolSet::CompiledFile.dump(
|
108
|
+
code,
|
109
|
+
filename,
|
110
|
+
::Myco.find_constant(:Rubinius)::Signature,
|
111
|
+
::Myco.find_constant(:Rubinius)::RUBY_LIB_VERSION
|
112
|
+
)
|
113
|
+
)}
|
114
|
+
declare_meme(:load_prototype, [], nil, ::Myco.cscope.dup) { |filename| (
|
115
|
+
loader = ::Myco.find_constant(:Myco)::CodeLoader::BytecodeLoader.new(filename)
|
116
|
+
loader.bind_to({:call_depth => 1})
|
117
|
+
self.__send__(
|
118
|
+
:prototype=,
|
119
|
+
loader.load
|
120
|
+
)
|
121
|
+
)}
|
122
|
+
declare_meme(:set_up_worker, [], nil, ::Myco.cscope.dup) { |worker| (
|
123
|
+
worker.instance_variable_set(
|
124
|
+
:@captures,
|
125
|
+
[]
|
126
|
+
)
|
127
|
+
worker.instance_variable_set(
|
128
|
+
:@highest_idx,
|
129
|
+
0
|
130
|
+
)
|
131
|
+
worker
|
132
|
+
)}
|
133
|
+
declare_meme(:captures_of_worker, [], nil, ::Myco.cscope.dup) { |worker| (worker.instance_variable_get(:@captures))}
|
134
|
+
declare_meme(:highest_idx_of_worker, [], nil, ::Myco.cscope.dup) { |worker| (worker.instance_variable_get(:@highest_idx))}
|
135
|
+
declare_meme(:new_processor, [], nil, ::Myco.cscope.dup) { |*| (::Myco.find_constant(:Processor).new({:builder => self.new_builder}))}
|
136
|
+
declare_meme(:new_builder, [], nil, ::Myco.cscope.dup) { |*| (::Myco.find_constant(:Builder).new)}
|
137
|
+
declare_meme(:parse, [], nil, ::Myco.cscope.dup) { |string| (
|
138
|
+
worker = self.new_worker
|
139
|
+
self.__send__(
|
140
|
+
:error_idx=,
|
141
|
+
nil
|
142
|
+
)
|
143
|
+
self.__send__(
|
144
|
+
:error_row=,
|
145
|
+
nil
|
146
|
+
)
|
147
|
+
self.__send__(
|
148
|
+
:error_col=,
|
149
|
+
nil
|
150
|
+
)
|
151
|
+
self.__send__(
|
152
|
+
:error_string=,
|
153
|
+
nil
|
154
|
+
)
|
155
|
+
self.__send__(
|
156
|
+
:result=,
|
157
|
+
nil
|
158
|
+
)
|
159
|
+
self.__send__(
|
160
|
+
:end_idx=,
|
161
|
+
worker.root(
|
162
|
+
string,
|
163
|
+
0
|
164
|
+
)
|
165
|
+
)
|
166
|
+
processor = self.new_processor
|
167
|
+
self.__send__(
|
168
|
+
:if,
|
169
|
+
self.end_idx
|
170
|
+
) { || (
|
171
|
+
processor.__send__(
|
172
|
+
:string=,
|
173
|
+
string
|
174
|
+
)
|
175
|
+
processor.__send__(
|
176
|
+
:capture_items=,
|
177
|
+
self.captures_of_worker(worker)
|
178
|
+
)
|
179
|
+
self.__send__(
|
180
|
+
:result=,
|
181
|
+
processor.process
|
182
|
+
)
|
183
|
+
)}
|
184
|
+
self.__send__(
|
185
|
+
:if,
|
186
|
+
self.end_idx.__send__(:!)
|
187
|
+
) { || (
|
188
|
+
self.__send__(
|
189
|
+
:error_idx=,
|
190
|
+
self.highest_idx_of_worker(worker)
|
191
|
+
)
|
192
|
+
pos = processor.position_of(
|
193
|
+
self.error_idx,
|
194
|
+
string
|
195
|
+
)
|
196
|
+
self.__send__(
|
197
|
+
:error_row=,
|
198
|
+
pos.first
|
199
|
+
)
|
200
|
+
self.__send__(
|
201
|
+
:error_col=,
|
202
|
+
pos.last
|
203
|
+
)
|
204
|
+
self.__send__(
|
205
|
+
:error_string=,
|
206
|
+
"Unexpected character near line: #{self.error_row}, column: #{self.error_col}.\n#{string.each_line.to_a.__send__(
|
207
|
+
:[],
|
208
|
+
self.error_row.__send__(
|
209
|
+
:-,
|
210
|
+
1
|
211
|
+
)
|
212
|
+
)}#{" ".__send__(
|
213
|
+
:*,
|
214
|
+
[
|
215
|
+
self.error_col.__send__(
|
216
|
+
:-,
|
217
|
+
1
|
218
|
+
),
|
219
|
+
0
|
220
|
+
].max
|
221
|
+
)}^"
|
222
|
+
)
|
223
|
+
)}
|
224
|
+
self.result
|
225
|
+
)}
|
226
|
+
declare_meme(:end_idx, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
|
227
|
+
declare_meme(:result, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
|
228
|
+
declare_meme(:error_idx, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
|
229
|
+
declare_meme(:error_row, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
|
230
|
+
declare_meme(:error_col, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
|
231
|
+
declare_meme(:error_string, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
|
232
|
+
declare_meme(:raise_error, [], nil, ::Myco.cscope.dup) { |*| (self.raise(
|
233
|
+
::Myco.find_constant(:SyntaxError),
|
234
|
+
self.error_string
|
235
|
+
))}
|
236
|
+
)}})
|
237
|
+
.tap { |__c__| __c__.__name__ = :BytecodeParser })}}.instance
|
@@ -0,0 +1,183 @@
|
|
1
|
+
|
2
|
+
Constructions < EmptyObject {
|
3
|
+
|
4
|
+
##
|
5
|
+
# Basic types of constructions.
|
6
|
+
|
7
|
+
Base < BasicObject { }
|
8
|
+
UnaryBase < Base { var inner }
|
9
|
+
BinaryBase < Base { var first, var second }
|
10
|
+
|
11
|
+
AnyCharacter < Base { }
|
12
|
+
Character < Base { var code }
|
13
|
+
CharacterString < Base { var codes }
|
14
|
+
CharacterSet < Base { var codes }
|
15
|
+
CharacterRange < Base { var start, var stop }
|
16
|
+
|
17
|
+
NegativePredicate < UnaryBase { }
|
18
|
+
PositivePredicate < UnaryBase { }
|
19
|
+
OneOrMore < UnaryBase { }
|
20
|
+
ZeroOrOne < UnaryBase { }
|
21
|
+
ZeroOrMore < UnaryBase { }
|
22
|
+
OrderedChoice < BinaryBase { }
|
23
|
+
Concatenation < BinaryBase { }
|
24
|
+
|
25
|
+
NamedCapture < UnaryBase { var captargs }
|
26
|
+
NamedTextCapture < UnaryBase { var captargs }
|
27
|
+
NamedTokenCapture < UnaryBase { var captargs }
|
28
|
+
Reduction < UnaryBase { var captargs }
|
29
|
+
|
30
|
+
##
|
31
|
+
# Bindings of patterns to constructions.
|
32
|
+
|
33
|
+
Patterns::UnaryBase << {
|
34
|
+
construct: construct_type.new(inner:inner.construct)
|
35
|
+
}
|
36
|
+
|
37
|
+
Patterns::BinaryBase << {
|
38
|
+
construct: construct_type.new(first:first.construct,second:second.construct)
|
39
|
+
}
|
40
|
+
|
41
|
+
Patterns::AnyCharacter << { construct: AnyCharacter.new }
|
42
|
+
Patterns::Character << { construct: Character .new(code:code) }
|
43
|
+
Patterns::CharacterString << { construct: CharacterString.new(codes:codes) }
|
44
|
+
Patterns::CharacterSet << { construct: CharacterSet .new(codes:codes) }
|
45
|
+
Patterns::CharacterRange << { construct: CharacterRange .new(start:start
|
46
|
+
stop:stop) }
|
47
|
+
|
48
|
+
Patterns::NegativePredicate << { construct_type: NegativePredicate }
|
49
|
+
Patterns::PositivePredicate << { construct_type: PositivePredicate }
|
50
|
+
Patterns::OneOrMore << { construct_type: OneOrMore }
|
51
|
+
Patterns::ZeroOrOne << { construct_type: ZeroOrOne }
|
52
|
+
Patterns::ZeroOrMore << { construct_type: ZeroOrMore }
|
53
|
+
Patterns::OrderedChoice << { construct_type: OrderedChoice }
|
54
|
+
Patterns::Concatenation << { construct_type: Concatenation }
|
55
|
+
|
56
|
+
Patterns::NamedCapture << {
|
57
|
+
construct: NamedCapture.new(
|
58
|
+
inner: inner.construct
|
59
|
+
captargs: [self.name]
|
60
|
+
)
|
61
|
+
}
|
62
|
+
Patterns::NamedTextCapture << {
|
63
|
+
construct: NamedTextCapture.new(
|
64
|
+
inner: inner.construct
|
65
|
+
captargs: [self.name]
|
66
|
+
)
|
67
|
+
}
|
68
|
+
Patterns::NamedTokenCapture << {
|
69
|
+
construct: NamedTokenCapture.new(
|
70
|
+
inner: inner.construct
|
71
|
+
captargs: [self.name]
|
72
|
+
)
|
73
|
+
}
|
74
|
+
Patterns::Reduction << {
|
75
|
+
construct: Reduction.new(
|
76
|
+
inner: inner.construct
|
77
|
+
captargs: [self.code, *self.args]
|
78
|
+
)
|
79
|
+
}
|
80
|
+
|
81
|
+
##
|
82
|
+
# The instruction sequence generator for each construction.
|
83
|
+
|
84
|
+
AnyCharacter << { sequence: [[:any, 1]] }
|
85
|
+
Character << { sequence: [[:char, code]] }
|
86
|
+
CharacterString << { sequence: codes.map |code| { [:char, code] } }
|
87
|
+
CharacterSet << { sequence: [[:charset, table]]
|
88
|
+
table: codes.map |code| { [code, true] }.to_h }
|
89
|
+
CharacterRange << { sequence: [[:charrange, start, stop]] }
|
90
|
+
|
91
|
+
NegativePredicate << {
|
92
|
+
sequence: {
|
93
|
+
a = inner.sequence
|
94
|
+
[[:choice, a.size+2], *a, [:fail_twice]]
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
PositivePredicate << {
|
99
|
+
sequence: {
|
100
|
+
a = inner.sequence
|
101
|
+
size = a.size
|
102
|
+
[[:choice, size+4], [:choice, size+1], *a, [:commit, 1], [:fail]]
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
OneOrMore << {
|
107
|
+
var inlaid
|
108
|
+
sequence: {
|
109
|
+
one = inner.sequence
|
110
|
+
inlaid && (one = one + inlaid)
|
111
|
+
or_more = ZeroOrMore.new(inner:inner,inlaid:inlaid).sequence
|
112
|
+
[*one, *or_more]
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
116
|
+
ZeroOrOne << {
|
117
|
+
sequence: {
|
118
|
+
a = inner.sequence
|
119
|
+
[[:choice, a.size+2], *a, [:commit, 1]]
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
ZeroOrMore << {
|
124
|
+
var inlaid
|
125
|
+
sequence:
|
126
|
+
switch(inner, :"is_a?")
|
127
|
+
.when(CharacterSet) { [[:span, inner.table]] }
|
128
|
+
.else {
|
129
|
+
a = inner.sequence
|
130
|
+
inlaid && (a = a + inlaid)
|
131
|
+
size = a.size
|
132
|
+
[[:choice, size+2], *a, [:partial_commit, size*-1]]
|
133
|
+
}
|
134
|
+
.output
|
135
|
+
}
|
136
|
+
|
137
|
+
OrderedChoice << {
|
138
|
+
sequence: {
|
139
|
+
a = first.sequence
|
140
|
+
b = second.sequence
|
141
|
+
[[:choice, a.size+2], *a, [:commit, b.size+1], *b]
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
145
|
+
Concatenation << {
|
146
|
+
sequence: [*first.sequence, *second.sequence]
|
147
|
+
}
|
148
|
+
|
149
|
+
NamedCapture << {
|
150
|
+
sequence: {
|
151
|
+
(inner.is_a?(OneOrMore) || inner.is_a?(ZeroOrMore)) &? (
|
152
|
+
inner.inlaid = [[:capture, [:m_split, captargs]]]
|
153
|
+
a = inner.sequence
|
154
|
+
[[:capture, [:m_start]], *a, [:capture, [:m_end, captargs]]]
|
155
|
+
) ?? (
|
156
|
+
a = inner.sequence
|
157
|
+
[[:capture, [:c_start]], *a, [:capture, [:c_end, captargs]]]
|
158
|
+
)
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
162
|
+
NamedTextCapture << {
|
163
|
+
sequence: {
|
164
|
+
a = inner.sequence
|
165
|
+
[[:capture, [:s_start]], *a, [:capture, [:s_end, captargs]]]
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
NamedTokenCapture << {
|
170
|
+
sequence: {
|
171
|
+
a = inner.sequence
|
172
|
+
[[:capture, [:t_start]], *a, [:capture, [:t_end, captargs]]]
|
173
|
+
}
|
174
|
+
}
|
175
|
+
|
176
|
+
Reduction << {
|
177
|
+
sequence: {
|
178
|
+
a = inner.sequence
|
179
|
+
[[:capture, [:r_start]], *a, [:capture, [:r_end, captargs]]]
|
180
|
+
}
|
181
|
+
}
|
182
|
+
|
183
|
+
}
|