Skip to content
This repository has been archived by the owner on Feb 3, 2021. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Fully handle arrayed subcaptures.
  • Loading branch information
pmichaud committed Oct 12, 2009
1 parent a1f5fa1 commit 8a90013
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 65 deletions.
36 changes: 29 additions & 7 deletions src/PAST/Compiler-Regex.pir
Expand Up @@ -54,27 +54,49 @@ Return the POST representation of the regex AST rooted by C<node>.
goto iter_loop
iter_done:


.local pmc faillabel
.local pmc startlabel, donelabel, faillabel
$S0 = concat prefix, 'start'
startlabel = self.'post_new'('Label', 'result'=>$S0)
$S0 = concat prefix, 'done'
donelabel = self.'post_new'('Label', 'result'=>$S0)
$S0 = concat prefix, 'fail'
faillabel = self.'post_new'('Label', 'result'=>$S0)
reghash['fail'] = faillabel

# If capnames is available, it's a hash where each key is the
# name of a potential subcapture and the value is greater than 1
# if it's to be an array. This builds a list of arrayed subcaptures
# for use by "!cursor_caparray" below.
.local pmc capnames, capnames_it, caparray
capnames = node.'capnames'()
caparray = box 0
unless capnames goto capnames_done
capnames_it = iter capnames
caparray = new ['ResizablePMCArray']
capnames_loop:
unless capnames_it goto capnames_done
$S0 = shift capnames_it
$I0 = capnames[$S0]
unless $I0 > 1 goto capnames_loop
$S0 = self.'escape'($S0)
push caparray, $S0
goto capnames_loop
capnames_done:

.local string cur, rep, pos, tgt, off, eos
(cur, rep, pos, tgt, off, eos) = self.'!rxregs'('cur rep pos tgt off eos')

.local pmc startlabel, donelabel
$S0 = concat prefix, 'start'
startlabel = self.'post_new'('Label', 'result'=>$S0)
$S0 = concat prefix, 'done'
donelabel = self.'post_new'('Label', 'result'=>$S0)
$S0 = concat '(', cur
concat $S0, ', '
concat $S0, pos
concat $S0, ', '
concat $S0, tgt
concat $S0, ', $I10)'
ops.'push_pirop'('callmethod', '"!cursor_start"', 'self', 'result'=>$S0)
unless caparray goto caparray_skip
self.'!cursorop'(ops, '!cursor_caparray', 0, caparray :flat)
caparray_skip:

ops.'push_pirop'('.lex', 'unicode:"$\x{a2}"', cur)
ops.'push_pirop'('length', eos, tgt, 'result'=>eos)

Expand Down
94 changes: 36 additions & 58 deletions src/Regex/Cursor.pir
Expand Up @@ -19,7 +19,7 @@ grammars.
load_bytecode 'P6object.pbc'
.local pmc p6meta
p6meta = new 'P6metaclass'
$P0 = p6meta.'new_class'('Regex::Cursor', 'attr'=>'$!target $!from $!pos $!match $!action $!names @!bstack @!cstack')
$P0 = p6meta.'new_class'('Regex::Cursor', 'attr'=>'$!target $!from $!pos $!match $!action $!names @!bstack @!cstack @!caparray')
$P0 = box 0
set_global '$!generation', $P0
$P0 = new ['Boolean']
Expand Down Expand Up @@ -58,6 +58,21 @@ for the Cursor if one hasn't been created yet.
to = getattribute self, '$!pos'
setattribute match, '$!to', to

# Create any arrayed subcaptures.
.local pmc caparray, caparray_it, caphash
caparray = getattribute self, '@!caparray'
if null caparray goto caparray_done
caparray_it = iter caparray
caphash = new ['Hash']
caparray_loop:
unless caparray_it goto caparray_done
$P0 = shift caparray_it
$P1 = new ['ResizablePMCArray']
match[$P0] = $P1
caphash[$P0] = $P1
goto caparray_loop
caparray_done:

# If it's not a successful match, or if there are
# no saved subcursors, we're done.
if to < from goto match_done
Expand All @@ -74,6 +89,13 @@ for the Cursor if one hasn't been created yet.
subnames = getattribute subcur, '$!names'
if null subnames goto cstack_loop
submatch = subcur.'MATCH'()
if null caparray goto cstack_bind
$I0 = exists caphash[subnames]
unless $I0 goto cstack_bind
$P0 = match[subnames]
push $P0, submatch
goto cstack_loop
cstack_bind:
match[subnames] = submatch
goto cstack_loop
cstack_done:
Expand Down Expand Up @@ -223,9 +245,21 @@ with a "real" Match object when requested.
.end


=item !cursor_caparray(caparray :slurpy)

Set the list of subcaptures that produce arrays to C<caparray>.

=cut

.sub '!cursor_caparray' :method
.param pmc caparray :slurpy
setattribute self, '@!caparray', caparray
.end


=item !cursor_names(names)

Set the Cursor's name (for binding) to names.
Set the Cursor's name (for binding) to C<names>.
=cut
Expand Down Expand Up @@ -407,62 +441,6 @@ match state.
.end


=item !match_arrays(names :slurpy)

Bind submatches C<names> of the current Match object to arrays.

=cut

.sub '!match_arrays' :method
.param pmc names :slurpy

.local pmc match, names_it
match = self.'MATCH'()
names_it = iter names
names_loop:
unless names_it goto names_done
$P0 = shift names_it
$P1 = new ['ResizablePMCArray']
match[$P0] = $P1
goto names_loop
names_done:
.end


=item !match_bind(bindval, names :slurpy)

Bind C<bindval>'s match object as submatches of the current cursor
under C<names>.
=cut
.sub '!match_bind' :method
.param pmc bindval
.param pmc names :slurpy
.local pmc match, names_it
match = self.'MATCH'()
$I0 = isa bindval, ['Regex';'Cursor']
unless $I0 goto have_bindval
bindval = bindval.'MATCH'()
have_bindval:
names_it = iter names
names_loop:
unless names_it goto names_done
$P0 = shift names_it
$P1 = match[$P0]
if null $P1 goto bind_1
$I0 = isa $P1, ['ResizablePMCArray']
unless $I0 goto bind_1
push $P1, bindval
goto names_loop
bind_1:
match[$P0] = bindval
goto names_loop
names_done:
.end
=item !protoregex(name)

Perform a match for protoregex C<name>.
Expand Down

0 comments on commit 8a90013

Please sign in to comment.