diff --git a/src/PAST/Compiler-Regex.pir b/src/PAST/Compiler-Regex.pir index 5380c56..1585ec2 100644 --- a/src/PAST/Compiler-Regex.pir +++ b/src/PAST/Compiler-Regex.pir @@ -1101,8 +1101,9 @@ Perform a subrule call. negate = node.'negate'() testop = self.'??!!'(negate, 'if', 'unless') - .local pmc subtype + .local pmc subtype, backtrack subtype = node.'subtype'() + backtrack = node.'backtrack'() ops.'push_pirop'('inline', subpost, subtype, negate, 'inline'=>" # rx subrule %0 subtype=%1 negate=%2") @@ -1111,8 +1112,27 @@ Perform a subrule call. ops.'push_pirop'('callmethod', subpost, cur, posargs :flat, namedargs :flat, 'result'=>'$P10') ops.'push_pirop'(testop, '$P10', fail) if subtype == 'zerowidth' goto done + if backtrack != 'r' goto subrule_backtrack if subtype == 'method' goto subrule_pos self.'!cursorop'(ops, '!mark_push', 0, 0, CURSOR_FAIL, 0, '$P10') + goto subrule_named + subrule_backtrack: + .local string rxname + .local pmc backlabel, passlabel + rxname = self.'unique'('rxsubrule') + $S0 = concat rxname, '_back' + backlabel = self.'post_new'('Label', 'result'=>$S0) + $S0 = concat rxname, '_pass' + passlabel = self.'post_new'('Label', 'result'=>$S0) + ops.'push_pirop'('goto', passlabel) + ops.'push'(backlabel) + ops.'push_pirop'('callmethod', '"!cursor_next"', '$P10', 'result'=>'$P10') + ops.'push_pirop'(testop, '$P10', fail) + ops.'push'(passlabel) + ops.'push_pirop'('set_addr', '$I10', backlabel) + self.'!cursorop'(ops, '!mark_push', 0, 0, pos, '$I10', '$P10') + if subtype == 'method' goto subrule_pos + subrule_named: ops.'push'(name) ops.'push_pirop'('callmethod', '"!cursor_names"', '$P10', name) subrule_pos: diff --git a/src/Regex/Cursor.pir b/src/Regex/Cursor.pir index 308dffb..e6be79e 100644 --- a/src/Regex/Cursor.pir +++ b/src/Regex/Cursor.pir @@ -219,15 +219,8 @@ Return the next match from a successful Cursor. =cut .sub 'next' :method - .local pmc regex, cur, match - regex = getattribute self, '&!regex' - if null regex goto cur_fail - cur = self.regex() - goto cur_done - cur_fail: - cur = self.'!cursor_start'() - cur.'!cursor_fail'() - cur_done: + .local pmc cur, match + cur = self.'!cursor_next'() match = cur.'MATCH'() .return (match) .end @@ -406,7 +399,7 @@ with a "real" Match object when requested. =item !cursor_backtrack() -Configure this cursor for backtracking via .next. +Configure this cursor for backtracking via C. =cut @@ -417,6 +410,25 @@ Configure this cursor for backtracking via .next. .end +=item !cursor_next() + +Continue a regex match from where the current cursor left off. + +=cut + +.sub '!cursor_next' :method + .local pmc regex, cur + regex = getattribute self, '&!regex' + if null regex goto fail + cur = self.regex() + .return (cur) + fail: + cur = self.'!cursor_start'() + cur.'!cursor_fail'() + .return (cur) +.end + + =item !cursor_caparray(caparray :slurpy) Set the list of subcaptures that produce arrays to C.