Possessive and non greedy quantifier modifiers are mutually exclusive
authorYves Orton <demerphq@gmail.com>
Thu, 13 Jun 2013 19:02:36 +0000 (21:02 +0200)
committerYves Orton <demerphq@gmail.com>
Thu, 13 Jun 2013 19:15:00 +0000 (21:15 +0200)
When I added support for possessive modifiers it was possible to
build perl so that they could be combined even if it made no sense
to do so.

Later on in relation to Perl #118375 I got confused and thought
they were undocumented but legal.

So to prevent further confusion, and since nobody has every mentioned
it since they were added, I am removing the unusued conditional
build logic, and clearly documenting why they aren't allowed.

pod/perlre.pod
regcomp.c
regcomp.h
t/re/re_tests

index 1a3f34a..49777a3 100644 (file)
@@ -539,7 +539,7 @@ X<?> X<*?> X<+?> X<??> X<{n}?> X<{n,}?> X<{n,m}?>
     {n,}?     Match at least n times, not greedily
     {n,m}?    Match at least n but not more than m times, not greedily
 
-By default, when a quantified subpattern does not allow the rest of the
+Normally when a quantified subpattern does not allow the rest of the
 overall pattern to match, Perl will backtrack. However, this behaviour is
 sometimes undesirable. Thus Perl provides the "possessive" quantifier form
 as well.
@@ -571,6 +571,16 @@ instance the above example could also be written as follows:
 
    /"(?>(?:(?>[^"\\]+)|\\.)*)"/
 
+Note that the possessive quantifier modifier can not be be combined
+with the non-greedy modifier. This is because it would make no sense.
+Consider the follow equivalency table:
+
+    Illegal         Legal
+    ------------    ------
+    X??+            X{0}
+    X+?+            X{1}
+    X{min,max}?+    X{min}
+
 =head3 Escape sequences
 
 Because patterns are processed as double-quoted strings, the following
index 3426112..0033805 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -9702,14 +9702,9 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
 
                 /* But the quantifier includes any '?', the non-greedy
                  * modifier, after the {}, [perl #118375]
-                 * Likewise the '+', the possessive modifier, and
-                 * they can be combined too, '?+' is the possessive
-                 * non-greedy modifier.
+                 * Likewise the '+', the possessive modifier. They are mutually exclusive.
                  */
-                if (RExC_parse < RExC_end && *RExC_parse == '?' ) {
-                    nextchar(pRExC_state);
-                }
-                if (RExC_parse < RExC_end && *RExC_parse == '+' ) {
+                if (RExC_parse < RExC_end && (*RExC_parse == '?' || *RExC_parse == '+') ) {
                     nextchar(pRExC_state);
                 }
                 return ret;
@@ -9825,9 +9820,7 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
        reginsert(pRExC_state, MINMOD, ret, depth+1);
         REGTAIL(pRExC_state, ret, ret + NODE_STEP_REGNODE);
     }
-#ifndef REG_ALLOW_MINMOD_SUSPEND
     else
-#endif
     if (RExC_parse < RExC_end && *RExC_parse == '+') {
         regnode *ender;
         nextchar(pRExC_state);
@@ -9837,7 +9830,6 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
         ret->flags = 0;
         ender = reg_node(pRExC_state, TAIL);
         REGTAIL(pRExC_state, ret, ender);
-        /*ret= ender;*/
     }
 
     if (RExC_parse < RExC_end && ISMULT2(RExC_parse)) {
index bf497e0..8b1b695 100644 (file)
--- a/regcomp.h
+++ b/regcomp.h
 #define RE_TRACK_PATTERN_OFFSETS
 #endif
 
-/* Unless the next line is uncommented it is illegal to combine lazy 
-   matching with possessive matching. Frankly it doesn't make much sense 
-   to allow it as X*?+ matches nothing, X+?+ matches a single char only, 
-   and X{min,max}?+ matches min times only.
- */
-/* #define REG_ALLOW_MINMOD_SUSPEND */
-
 /*
  * The "internal use only" fields in regexp.h are present to pass info from
  * compile to execute that permits the execute phase to run lots faster on
index 45018df..de7d590 100644 (file)
@@ -1747,7 +1747,4 @@ m?^xy\?$? xy?     y       $&      xy?
 /(a|(bc)){0,0}+xyz/    xyz     y       $&      xyz
 /( a | ( bc ) ) {0,0} + xyz/x  xyz     y       $&      xyz
 
-/(a|(bc)){0,0}?xyz/    xyz     y       $&      xyz
-/( a | ( bc ) ) {0,0} ? + xyz/x        xyz     y       $&      xyz
-
 # vim: softtabstop=0 noexpandtab