Revision: 551
http://vcs.pcre.org/viewvc?view=rev&revision=551
Author: ph10
Date: 2010-10-10 18:33:07 +0100 (Sun, 10 Oct 2010)
Log Message:
-----------
Make (*COMMIT) override (*THEN) and similar.
Modified Paths:
--------------
code/trunk/ChangeLog
code/trunk/doc/pcrepattern.3
code/trunk/pcre_exec.c
code/trunk/testdata/testinput11
code/trunk/testdata/testoutput11
Modified: code/trunk/ChangeLog
===================================================================
--- code/trunk/ChangeLog 2010-10-10 16:24:11 UTC (rev 550)
+++ code/trunk/ChangeLog 2010-10-10 17:33:07 UTC (rev 551)
@@ -10,6 +10,12 @@
at the same level (in this case, to look for "c"). The Perl documentation
is clear that when (*THEN) is backtracked onto, it goes to the "next
alternative in the innermost enclosing group".
+
+2. (*COMMIT) was not overriding (*THEN), as it does in Perl. In a pattern
+ such as (A(*COMMIT)B(*THEN)C|D) any failure after matching A should
+ result in overall failure. Similarly, (*COMMIT) now overrides (*PRUNE) and
+ (*SKIP), (*SKIP) overrides (*PRUNE) and (*THEN), and (*PRUNE) overrides
+ (*THEN).
Version 8.10 25-Jun-2010
Modified: code/trunk/doc/pcrepattern.3
===================================================================
--- code/trunk/doc/pcrepattern.3 2010-10-10 16:24:11 UTC (rev 550)
+++ code/trunk/doc/pcrepattern.3 2010-10-10 17:33:07 UTC (rev 551)
@@ -2644,7 +2644,25 @@
overall match fails. If (*THEN) is not directly inside an alternation, it acts
like (*PRUNE).
.
+.P
+The above verbs provide four different "strengths" of control when subsequent
+matching fails. (*THEN) is the weakest, carrying on the match at the next
+alternation. (*PRUNE) comes next, failing the match at the current starting
+position, but allowing an advance to the next character (for an unanchored
+pattern). (*SKIP) is similar, except that the advance may be more than one
+character. (*COMMIT) is the strongest, causing the entire match to fail.
+.P
+If more than one is present in a pattern, the "stongest" one wins. For example,
+consider this pattern, where A, B, etc. are complex pattern fragments:
+.sp
+ (A(*COMMIT)B(*THEN)C|D)
+.sp
+Once A has matched, PCRE is committed to this match, at the current starting
+position. If subsequently B matches, but C does not, the normal (*THEN) action
+of trying the next alternation (that is, D) does not happen because (*COMMIT)
+overrides.
.
+.
.SH "SEE ALSO"
.rs
.sp
Modified: code/trunk/pcre_exec.c
===================================================================
--- code/trunk/pcre_exec.c 2010-10-10 16:24:11 UTC (rev 550)
+++ code/trunk/pcre_exec.c 2010-10-10 17:33:07 UTC (rev 551)
@@ -710,36 +710,47 @@
case OP_FAIL:
MRRETURN(MATCH_NOMATCH);
+ /* COMMIT overrides PRUNE, SKIP, and THEN */
+
case OP_COMMIT:
RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
ims, eptrb, flags, RM52);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE &&
+ rrc != MATCH_SKIP && rrc != MATCH_SKIP_ARG &&
+ rrc != MATCH_THEN)
+ RRETURN(rrc);
MRRETURN(MATCH_COMMIT);
+ /* PRUNE overrides THEN */
+
case OP_PRUNE:
RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
ims, eptrb, flags, RM51);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
MRRETURN(MATCH_PRUNE);
case OP_PRUNE_ARG:
RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md,
ims, eptrb, flags, RM56);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc);
md->mark = ecode + 2;
RRETURN(MATCH_PRUNE);
+ /* SKIP overrides PRUNE and THEN */
+
case OP_SKIP:
RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode], offset_top, md,
ims, eptrb, flags, RM53);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN)
+ RRETURN(rrc);
md->start_match_ptr = eptr; /* Pass back current position */
MRRETURN(MATCH_SKIP);
case OP_SKIP_ARG:
RMATCH(eptr, ecode + _pcre_OP_lengths[*ecode] + ecode[1], offset_top, md,
ims, eptrb, flags, RM57);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN)
+ RRETURN(rrc);
/* Pass back the current skip name by overloading md->start_match_ptr and
returning the special MATCH_SKIP_ARG return code. This will either be
Modified: code/trunk/testdata/testinput11
===================================================================
--- code/trunk/testdata/testinput11 2010-10-10 16:24:11 UTC (rev 550)
+++ code/trunk/testdata/testinput11 2010-10-10 17:33:07 UTC (rev 551)
@@ -483,4 +483,15 @@
/(?&t)(?#()(?(DEFINE)(?<t>a))/
bac
+/--- COMMIT should override THEN ---/
+
+/(?>(*COMMIT)(?>yes|no)(*THEN)(*F))?/
+ yes
+
+/(?>(*COMMIT)(yes|no)(*THEN)(*F))?/
+ yes
+
+/^((yes|no)(*THEN)(*F))?/
+ yes
+
/-- End of testinput11 --/
Modified: code/trunk/testdata/testoutput11
===================================================================
--- code/trunk/testdata/testoutput11 2010-10-10 16:24:11 UTC (rev 550)
+++ code/trunk/testdata/testoutput11 2010-10-10 17:33:07 UTC (rev 551)
@@ -942,4 +942,18 @@
bac
0: a
+/--- COMMIT should override THEN ---/
+
+/(?>(*COMMIT)(?>yes|no)(*THEN)(*F))?/
+ yes
+No match
+
+/(?>(*COMMIT)(yes|no)(*THEN)(*F))?/
+ yes
+No match
+
+/^((yes|no)(*THEN)(*F))?/
+ yes
+ 0:
+
/-- End of testinput11 --/