diff options
author | ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15> | 2010-10-10 17:33:07 +0000 |
---|---|---|
committer | ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15> | 2010-10-10 17:33:07 +0000 |
commit | e5f5a0846fd1a4c912d3aa6c505a0bde13c40944 (patch) | |
tree | d9af1bbab36170e18d2fe85aa3941b7f81cd8f67 | |
parent | a0ab6e7fdaff6d0b459689f4bc5c79792cfd85cd (diff) | |
download | pcre-e5f5a0846fd1a4c912d3aa6c505a0bde13c40944.tar.gz |
Make (*COMMIT) override (*THEN) and similar.
git-svn-id: svn://vcs.exim.org/pcre/code/trunk@551 2f5784b3-3f2a-0410-8824-cb99058d5e15
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | doc/pcrepattern.3 | 18 | ||||
-rw-r--r-- | pcre_exec.c | 21 | ||||
-rw-r--r-- | testdata/testinput11 | 11 | ||||
-rw-r--r-- | testdata/testoutput11 | 14 |
5 files changed, 65 insertions, 5 deletions
@@ -10,6 +10,12 @@ Version 8.11 10-Oct-2010 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 diff --git a/doc/pcrepattern.3 b/doc/pcrepattern.3 index 63f3df8..04b4afd 100644 --- a/doc/pcrepattern.3 +++ b/doc/pcrepattern.3 @@ -2644,6 +2644,24 @@ behaviour of (*THEN:NAME) is exactly the same as (*MARK:NAME)(*THEN) if the 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 diff --git a/pcre_exec.c b/pcre_exec.c index 32f8c5a..1eeea52 100644 --- a/pcre_exec.c +++ b/pcre_exec.c @@ -710,36 +710,47 @@ for (;;) 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 diff --git a/testdata/testinput11 b/testdata/testinput11 index 795e1be..5509b52 100644 --- a/testdata/testinput11 +++ b/testdata/testinput11 @@ -483,4 +483,15 @@ however, we need the complication for Perl. ---/ /(?&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 --/ diff --git a/testdata/testoutput11 b/testdata/testoutput11 index 6270d5b..0c56c66 100644 --- a/testdata/testoutput11 +++ b/testdata/testoutput11 @@ -942,4 +942,18 @@ No match 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 --/ |