This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Optimize a single character [class] into EXACTish
authorKarl Williamson <public@khwilliamson.com>
Sat, 7 Jul 2012 16:10:30 +0000 (10:10 -0600)
committerKarl Williamson <public@khwilliamson.com>
Wed, 25 Jul 2012 03:13:47 +0000 (21:13 -0600)
Things like /[s]/ or /[s]/i can be optimized as if they did not have the
brackets, /s/ or /s/i.

ext/re/t/regop.t
regcomp.c

index 27d3479..a180756 100644 (file)
@@ -241,21 +241,21 @@ floating ""$ at 3..4 (checking floating)
 #Matching stclass EXACTF <.> against ".exe"
 ---
 #Compiling REx "[q]"
-#size 12 nodes Got 100 bytes for offset annotations.
+#size 3 nodes Got 28 bytes for offset annotations.
 #first at 1
 #Final program:
 #   1: EXACT <q>(3)
 #   3: END(0)
 #anchored "q" at 0 (checking anchored isall) minlen 1
-#Offsets: [12]
+#Offsets: [3]
 #        1:1[3] 3:4[0]
 #Guessing start of match, REx "[q]" against "q"...
 #Found anchored substr "q" at offset 0...
 #Guessed: match at offset 0
 #%MATCHED%
 #Freeing REx: "[q]"
-Got 100 bytes for offset annotations.
-Offsets: [12]
+Got 28 bytes for offset annotations.
+Offsets: [3]
 1:1[3] 3:4[0]
 %MATCHED%        
 Freeing REx: "[q]"
index 6e296eb..120deb8 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -11874,12 +11874,27 @@ parseit:
 
             }
         }
-        else if (! LOC) {
-            if (invert && prevvalue == '\n' && value == '\n') {
-                op = REG_ANY; /* Optimize [^\n] */
+        else if (value == prevvalue) {
+
+            /* Here, the class consists of just a single code point */
+
+            if (invert) {
+                if (! LOC && value == '\n') {
+                    op = REG_ANY; /* Optimize [^\n] */
+                }
+            }
+            else if (value < 256 || UTF) {
+
+                /* Optimize a single value into an EXACTish node, but not if it
+                 * would require converting the pattern to UTF-8. */
+                op = compute_EXACTish(pRExC_state);
             }
-            else if (prevvalue == '0' && value == '9') {
-                op = (invert) ? NDIGITA : DIGITA;
+        } /* Otherwise is a range */
+        else if (! LOC) {   /* locale could vary these */
+            if (prevvalue == '0') {
+                if (value == '9') {
+                    op = (invert) ? NDIGITA : DIGITA;
+                }
             }
         }
 
@@ -11908,6 +11923,10 @@ parseit:
 
             ret = reg_node(pRExC_state, op);
 
+            if (PL_regkind[op] == EXACT) {
+                alloc_maybe_populate_EXACT(pRExC_state, ret, 0, value);
+            }
+
             RExC_parse = (char *) cur_parse;
 
             SvREFCNT_dec(listsv);