1 # Copyright (C) 2007-2008, The Perl Foundation.
6 .namespace ['Perl6::Grammar']
8 .sub 'peek_brackets' :method
11 .local string brackets, start, stop
12 brackets = unicode:"<>[](){}\xab\xbb"
13 start = substr target, pos, 1
15 $I0 = index brackets, start
18 unless $I1 goto bracket_valid
19 self.'panic'("Using a closing delimiter for an opener is reserved")
23 stop = substr brackets, $I0, 1
29 .sub 'quote_expression' :method
31 .param pmc options :slurpy :named
33 ## create a new match object
37 (mob, pos, target) = self.'new'(self)
41 action = options['action']
43 ## set up options based on flags
44 .local pmc flagarray, iter
45 flagarray = split ' ', flags
46 iter = new 'Iterator', flagarray
48 unless iter goto iter_end
51 oname = substr oname, 1
53 if oname == 'ww' goto opt_ww
54 if oname == 'w' goto opt_w
55 if oname == 'qq' goto opt_qq
56 if oname == 'b' goto opt_b
74 .local string start, stop
75 (start, stop) = self.'peek_brackets'(target, pos)
77 ## determine pos, lastpos
80 .local int stoplen, lastpos, wsstop
82 wsstop = options['wsstop']
83 lastpos = length target
85 options['stop'] = stop
87 ## handle :regex parsing
88 .local pmc p6regex, quote_regex
89 $I0 = options['regex']
90 unless $I0 goto word_start
92 p6regex = get_root_global ['parrot';'PGE::Perl6Regex'], 'regex'
94 quote_regex = p6regex(mob, options :flat :named)
95 unless quote_regex goto fail
96 pos = quote_regex.'to'()
99 mob[key] = quote_regex
102 ## handle word parsing
104 ## set up escapes based on flags
105 .local string escapes
108 unless $I0 goto escape_s_done
112 unless $I0 goto escape_c_done
116 options['escapes'] = escapes
119 optww = options['ww']
120 unless optww goto have_wwopts
121 .local pmc wwsingleopts, wwdoubleopts
122 wwsingleopts = new 'Hash'
123 wwsingleopts['q'] = 1
124 wwsingleopts['stop'] = "'"
125 wwsingleopts['action'] = action
126 ## FIXME: RT#48112 -- currently 'clone' on a Hash can't
127 ## handle null entries (and does a deepcopy), so we're
128 ## using an iterator to do it.
129 ## wwdoubleopts = clone options
130 wwdoubleopts = new 'Hash'
132 iter2 = new 'Iterator', options
134 unless iter2 goto iter2_end
137 wwdoubleopts[$S0] = $P0
140 wwdoubleopts['stop'] = '"'
141 wwdoubleopts['wsstop'] = 0
144 .local pmc quote_concat
145 quote_concat = new 'ResizablePMCArray'
147 unless wsstop goto word_plain
149 pos = find_not_cclass .CCLASS_WHITESPACE, target, pos, lastpos
150 if pos > lastpos goto fail
151 $S0 = substr target, pos, stoplen
152 if $S0 == stop goto word_succeed
153 if pos >= lastpos goto fail
154 unless optww goto word_plain
156 $S0 = substr target, pos, 1
157 if $S0 == '"' goto word_shell_double
158 if $S0 != "'" goto word_plain
162 $P0 = mob.'quote_concat'(wwsingleopts)
164 push quote_concat, $P0
171 $P0 = mob.'quote_concat'(wwdoubleopts)
173 push quote_concat, $P0
179 $P0 = mob.'quote_concat'(options)
181 push quote_concat, $P0
186 mob[key] = quote_concat
191 if null action goto succeed_done
192 $I0 = can action, 'quote_expression'
193 unless $I0 goto succeed_done
194 action.'quote_expression'(mob, key)
203 .sub 'quote_concat' :method
206 ## create a new match object
210 (mob, pos, target) = self.'new'(self)
212 ## determine pos, lastpos
214 .local int stoplen, lastpos, wsstop
215 stop = options['stop']
216 wsstop = options['wsstop']
217 stoplen = length stop
218 lastpos = length target
221 .local string escapes
222 escapes = options['escapes']
224 .local pmc quote_term
225 quote_term = new 'ResizablePMCArray'
229 $P0 = mob.'quote_term'(options)
233 if pos > lastpos goto fail
234 $S0 = substr target, pos, stoplen
235 if $S0 == stop goto succeed
236 unless wsstop goto term_loop
237 $I0 = is_cclass .CCLASS_WHITESPACE, target, pos
238 unless $I0 goto term_loop
240 ## save the array of captured terms
241 mob['quote_term'] = quote_term
243 ## call any related {*} actions
245 action = options['action']
246 if null action goto succeed_done
247 $I0 = can action, 'quote_concat'
248 unless $I0 goto succeed_done
249 action.'quote_concat'(mob)
258 .sub 'quote_term' :method
262 action = options['action']
267 (mob, pos, target) = self.'new'(self)
269 .local string leadchar, escapes
270 escapes = options['escapes']
271 leadchar = substr target, pos, 1
272 $I0 = index escapes, leadchar
273 if $I0 < 0 goto term_literal
274 if leadchar == '$' goto term_scalar
275 if leadchar == '{' goto term_closure
278 $P0 = mob.'quote_literal'(options)
281 mob['quote_literal'] = $P0
288 $P0 = mob.'variable'('action'=>action)
289 unless $P0 goto err_scalar
297 $P0 = mob.'circumfix'('action'=>action)
306 if null action goto succeed_done
307 $I0 = can action, 'quote_term'
308 unless $I0 goto succeed_done
309 action.'quote_term'(mob, key)
319 mob.'panic'("Can't use $ as non-variable in interpolated string")
324 .sub 'quote_literal' :method
330 (mob, pos, target) = self.'new'(self)
332 .local string stop, stop1
333 .local int stoplen, lastpos, wsstop
334 stop = options['stop']
335 wsstop = options['wsstop']
336 stop1 = substr stop, 0, 1
337 stoplen = length stop
338 lastpos = length target
341 .local string escapes
342 .local int optq, optb
343 escapes = options['escapes']
347 .local string literal
351 if pos > lastpos goto fail
352 $S0 = substr target, pos, stoplen
353 if $S0 == stop goto succeed
354 unless wsstop goto scan_loop_1
355 $I0 = is_cclass .CCLASS_WHITESPACE, target, pos
358 if pos >= lastpos goto fail
361 .local string litchar
362 litchar = substr target, pos, 1
363 ## if we've reached an escape char, we're done
364 $I0 = index escapes, litchar
365 if $I0 >= 0 goto succeed
366 ## if this isn't an interpolation, add the char
367 unless optq goto add_litchar
368 if litchar != "\\" goto add_litchar
369 ## okay, we have a backslash, let's process it
370 .local string backchar
372 backchar = substr target, $I0, 1
373 ## handle :q options, \\ and \+stop
374 if backchar == "\\" goto add_backchar
375 if backchar == stop1 goto add_backchar
376 unless optb goto add_litchar
378 $I0 = index "0abefnrtxdo123456789", backchar
379 if $I0 < 0 goto add_backchar
380 if $I0 >= 11 goto fail_backchar_digit
381 if $I0 >= 8 goto scan_xdo
382 litchar = substr "\0\a\b\e\f\n\r\t", $I0, 1
383 if $I0 >= 1 goto add_litchar2
384 ## peek ahead for octal digits after \0
386 $S0 = substr target, $I0, 1
387 $I0 = index "01234567", $S0
388 if $I0 >= 0 goto fail_backchar_digit
403 ## handle \x, \d, and \o escapes. start by converting
404 ## the backchar into 8, 10, or 16 (yes, it's a hack
405 ## but it works). Then loop through the characters
406 ## that follow to compute the decimal value of codepoints,
407 ## and add the codepoints to our literal.
408 .local int base, decnum, isbracketed
409 base = index ' o d x', backchar
412 $S0 = substr target, pos, 1
413 isbracketed = iseq $S0, '['
416 $S0 = substr target, pos, 1
417 $I0 = index '0123456789abcdef0123456789ABCDEF', $S0
418 if $I0 < 0 goto scan_xdo_char_end
420 if $I0 >= base goto scan_xdo_char_end
424 goto scan_xdo_char_loop
428 unless isbracketed goto scan_xdo_end
429 if $S0 == ']' goto scan_xdo_end
430 if $S0 != ',' goto fail
433 goto scan_xdo_char_loop
439 mob.'result_object'(literal)
443 self.panic('\123 form deprecated, use \o123 instead')
454 # vim: expandtab shiftwidth=4 ft=pir: