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

Commit

Permalink
Refactor mark handling in Cursor. Fixes a bunch of greedy quantifier …
Browse files Browse the repository at this point in the history
…tests.
  • Loading branch information
pmichaud committed Oct 9, 2009
1 parent f4b488a commit f12bd0c
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/PAST/Compiler-Regex.pir
Expand Up @@ -96,7 +96,7 @@ Return the POST representation of the regex AST rooted by C<node>.
$P0 = self.'post_regex'(node)
ops.'push'($P0)
ops.'push'(faillabel)
self.'!cursorop'(ops, '!mark_fail', 3, rep, pos, '$I10')
self.'!cursorop'(ops, '!mark_fail', 3, rep, pos, '$I10', 0)
ops.'push_pirop'('lt', pos, -1, donelabel)
ops.'push_pirop'('eq', pos, -1, faillabel)
ops.'push_pirop'('jump', '$I10')
Expand Down
60 changes: 35 additions & 25 deletions src/Regex/Cursor.pir
Expand Up @@ -195,55 +195,65 @@ the address of a label to branch to when backtracking occurs.)
.end
=item !mark_fail([tomark])
=item !mark_peek(mark)
Remove the most recent C<mark> and backtrack the cursor to the
point given by that mark. If no C<mark> is provided, then
backtracks the most recent mark. Returns the backtracked
values of repetition count, cursor position, and mark (address).
Return information about the latest frame for C<mark>.
If C<mark> is zero, return information about the latest frame.
=cut
.sub '!mark_fail' :method
.param int tomark :optional
.param int has_tomark :opt_flag
.sub '!mark_peek' :method
.param int tomark
.local pmc bstack, mstack
bstack = getattribute self, '@!bstack'
if null bstack goto cursor_fail
unless bstack goto cursor_fail
if null bstack goto no_mark
unless bstack goto no_mark
# get the frame associated with the mark
.local int bptr
bptr = elements bstack
bptr_loop:
bptr = bptr - 4
if bptr < 0 goto cursor_fail
if bptr < 0 goto no_mark
.local int rep, pos, mark, mptr
mark = bstack[bptr]
unless has_tomark goto bptr_done
if mark != tomark goto bptr_loop
unless tomark goto bptr_done
unless mark == tomark goto bptr_loop
bptr_done:
$I0 = bptr + 1
pos = bstack[$I0]
inc $I0
rep = bstack[$I0]
inc $I0
mptr = bstack[$I0]
.return (rep, pos, mark, bptr, bstack, mptr)
# release the backtracked stack elements
assign bstack, bptr
no_mark:
.return (0, -2, 0, -4)
.end
# return mark values
.return (rep, pos, mark)
cursor_fail:
null $P0
setattribute self, '@!bstack', $P0
setattribute self, '@!mstack', $P0
setattribute self, '$!match', $P0
.return (0, -2, 0)
=item !mark_fail(tomark)
Remove the most recent C<mark> and backtrack the cursor to the
point given by that mark. If C<mark> is zero, then
backtracks the most recent mark. Returns the backtracked
values of repetition count, cursor position, and mark (address).
=cut
.sub '!mark_fail' :method
.param int mark
.local int rep, pos, mark, bptr, mptr
.local pmc bstack
(rep, pos, mark, bptr, bstack) = self.'!mark_peek'(mark)
unless bptr >= 0 goto done
assign bstack, bptr
done:
.return (rep, pos, mark)
.end
Expand All @@ -260,7 +270,7 @@ match state.
# backtrack
.local int rep, pos, mark
(rep, pos, mark, $P0) = self.'!mark_fail'(mark)
(rep, pos, mark) = self.'!mark_fail'(mark)
.return (rep, pos, mark)
.end
Expand Down

0 comments on commit f12bd0c

Please sign in to comment.