Revision: 1393
http://vcs.pcre.org/viewvc?view=rev&revision=1393
Author: ph10
Date: 2013-11-08 16:37:21 +0000 (Fri, 08 Nov 2013)
Log Message:
-----------
Allow quantifiers on (?!) so as to be the same as other assertions.
Modified Paths:
--------------
code/trunk/ChangeLog
code/trunk/pcre_compile.c
code/trunk/testdata/testinput2
code/trunk/testdata/testoutput2
Modified: code/trunk/ChangeLog
===================================================================
--- code/trunk/ChangeLog 2013-11-06 18:00:09 UTC (rev 1392)
+++ code/trunk/ChangeLog 2013-11-08 16:37:21 UTC (rev 1393)
@@ -163,6 +163,12 @@
34. Character classes such as [A-\d] or [a-[:digit:]] now cause compile-time
errors. Perl warns for these when in warning mode, but PCRE has no facility
for giving warnings.
+
+35. Change 34 for 8.13 allowed quantifiers on assertions, because Perl does.
+ However, this was not working for (?!) because it is optimized to (*FAIL),
+ for which PCRE does not allow quantifiers. The optimization is now disabled
+ when a quantifier follows (?!). I can't see any use for this, but it makes
+ things uniform.
Version 8.33 28-May-2013
Modified: code/trunk/pcre_compile.c
===================================================================
--- code/trunk/pcre_compile.c 2013-11-06 18:00:09 UTC (rev 1392)
+++ code/trunk/pcre_compile.c 2013-11-08 16:37:21 UTC (rev 1393)
@@ -5737,8 +5737,9 @@
opcodes such as BRA and CBRA, as this is the place where they get converted
into the more special varieties such as BRAPOS and SBRA. A test for >=
OP_ASSERT and <= OP_COND includes ASSERT, ASSERT_NOT, ASSERTBACK,
- ASSERTBACK_NOT, ONCE, BRA, CBRA, and COND. Originally, PCRE did not allow
- repetition of assertions, but now it does, for Perl compatibility. */
+ ASSERTBACK_NOT, ONCE, ONCE_NC, BRA, BRAPOS, CBRA, CBRAPOS, and COND.
+ Originally, PCRE did not allow repetition of assertions, but now it does,
+ for Perl compatibility. */
else if (*previous >= OP_ASSERT && *previous <= OP_COND)
{
@@ -5756,7 +5757,7 @@
/* There is no sense in actually repeating assertions. The only potential
use of repetition is in cases when the assertion is optional. Therefore,
if the minimum is greater than zero, just ignore the repeat. If the
- maximum is not not zero or one, set it to 1. */
+ maximum is not zero or one, set it to 1. */
if (*previous < OP_ONCE) /* Assertion */
{
@@ -6703,11 +6704,18 @@
ptr++;
break;
+ /* Optimize (?!) to (*FAIL) unless it is quantified - which is a weird
+ thing to do, but Perl allows all assertions to be quantified, and when
+ they contain capturing parentheses there may be a potential use for
+ this feature. Not that that applies to a quantified (?!) but we allow
+ it for uniformity. */
/* ------------------------------------------------------------ */
case CHAR_EXCLAMATION_MARK: /* Negative lookahead */
ptr++;
- if (*ptr == CHAR_RIGHT_PARENTHESIS) /* Optimize (?!) */
+ if (*ptr == CHAR_RIGHT_PARENTHESIS && ptr[1] != CHAR_ASTERISK &&
+ ptr[1] != CHAR_PLUS && ptr[1] != CHAR_QUESTION_MARK &&
+ (ptr[1] != CHAR_LEFT_CURLY_BRACKET || !is_counted_repeat(ptr+2)))
{
*code++ = OP_FAIL;
previous = NULL;
Modified: code/trunk/testdata/testinput2
===================================================================
--- code/trunk/testdata/testinput2 2013-11-06 18:00:09 UTC (rev 1392)
+++ code/trunk/testdata/testinput2 2013-11-08 16:37:21 UTC (rev 1393)
@@ -2520,8 +2520,11 @@
** Failers
ab
-/a(?!)+b/
+/a(?!)b/BZ
+/(?!)?a/BZ
+ ab
+
/a(*FAIL)+b/
/(abc|pqr|123){0}[xyz]/SI
Modified: code/trunk/testdata/testoutput2
===================================================================
--- code/trunk/testdata/testoutput2 2013-11-06 18:00:09 UTC (rev 1392)
+++ code/trunk/testdata/testoutput2 2013-11-08 16:37:21 UTC (rev 1393)
@@ -9281,9 +9281,29 @@
ab
No match
-/a(?!)+b/
-Failed: nothing to repeat at offset 5
+/a(?!)b/BZ
+------------------------------------------------------------------
+ Bra
+ a
+ *FAIL
+ b
+ Ket
+ End
+------------------------------------------------------------------
+/(?!)?a/BZ
+------------------------------------------------------------------
+ Bra
+ Brazero
+ Assert not
+ Ket
+ a
+ Ket
+ End
+------------------------------------------------------------------
+ ab
+ 0: a
+
/a(*FAIL)+b/
Failed: nothing to repeat at offset 8