This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
regex: \p{} in pattern implies Unicode semantics
authorKarl Williamson <public@khwilliamson.com>
Thu, 27 Jan 2011 23:03:11 +0000 (16:03 -0700)
committerKarl Williamson <public@khwilliamson.com>
Thu, 27 Jan 2011 23:25:57 +0000 (16:25 -0700)
Now, a Unicode property match specified in the pattern will indicate that the pattern is meant for matching according to Unicode rules

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

index 6cd2bdc..b264985 100644 (file)
@@ -326,7 +326,8 @@ L</Modules and Pragmata>.
 
 =item *
 
-XXX
+A Unicode C<\p{}> property match in a regular rexpression pattern will
+now force Unicode rules for the rest of the regular expression
 
 =back
 
index 6395614..f619b32 100644 (file)
@@ -697,15 +697,17 @@ will have Unicode semantics when it comes to case-insensitive matching.
 
 C<"d"> means to use the traditional Perl pattern matching behavior.
 This is dualistic (hence the name C<"d">, which also could stand for
-"depends").  When this is in effect, Perl matches utf8-encoded strings
-using Unicode rules, and matches non-utf8-encoded strings using the
-platform's native character set rules.  (If the regular expression
-itself is encoded in utf8, Unicode rules are used regardless of the
-target string's encoding.)
-See L<perlunicode/The "Unicode Bug">.  It is automatically selected by
-default if the regular expression is compiled neither within the scope
-of a C<"use locale"> pragma nor a <C<"use feature 'unicode_strings">
-pragma.
+"depends").  When this is in effect, Perl matches according to the
+platform's native character set rules unless there is something that
+indicates to use Unicode rules.  If either the target string or the
+pattern itself is encoded in UTF-8, Unicode rules are used.  Also, if
+the pattern contains Unicode-only features, such as code points above
+255, C<\p()> Unicode properties or C<\N{}> Unicode names, Unicode rules
+will be used.  It is automatically selected by default if the regular
+expression is compiled neither within the scope of a C<"use locale">
+pragma nor a <C<"use feature 'unicode_strings"> pragma.
+This behavior causes a number of glitches, see
+L<perlunicode/The "Unicode Bug">.
 
 Note that the C<a>, C<d>, C<l>, C<p>, and C<u> modifiers are special in
 that they can only be enabled, not disabled, and the C<a>, C<d>, C<l>, and
index 57c06d1..4ac544f 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -134,6 +134,9 @@ typedef struct RExC_state_t {
     I32                orig_utf8;      /* whether the pattern was originally in utf8 */
                                /* XXX use this for future optimisation of case
                                 * where pattern must be upgraded to utf8. */
+    I32                uni_semantics;  /* If a d charset modifier should use unicode
+                                  rules, even if the pattern is not in
+                                  utf8 */
     HV         *paren_names;           /* Paren names */
     
     regnode    **recurse;              /* Recurse regops */
@@ -178,6 +181,7 @@ typedef struct RExC_state_t {
 #define RExC_seen_zerolen      (pRExC_state->seen_zerolen)
 #define RExC_seen_evals        (pRExC_state->seen_evals)
 #define RExC_utf8      (pRExC_state->utf8)
+#define RExC_uni_semantics     (pRExC_state->uni_semantics)
 #define RExC_orig_utf8 (pRExC_state->orig_utf8)
 #define RExC_open_parens       (pRExC_state->open_parens)
 #define RExC_close_parens      (pRExC_state->close_parens)
@@ -4392,6 +4396,7 @@ Perl_re_compile(pTHX_ SV * const pattern, U32 orig_pm_flags)
     DEBUG_r(if (!PL_colorset) reginitcolors());
 
     RExC_utf8 = RExC_orig_utf8 = SvUTF8(pattern);
+    RExC_uni_semantics = 0;
 
     /****************** LONG JUMP TARGET HERE***********************/
     /* Longjmp back to here if have to switch in midstream to utf8 */
@@ -4500,6 +4505,7 @@ Perl_re_compile(pTHX_ SV * const pattern, U32 orig_pm_flags)
     if (used_setjump) {
        JMPENV_POP;
     }
+
     DEBUG_PARSE_r({
         PerlIO_printf(Perl_debug_log, 
             "Required size %"IVdf" nodes\n"
@@ -4508,6 +4514,14 @@ Perl_re_compile(pTHX_ SV * const pattern, U32 orig_pm_flags)
         RExC_lastnum=0; 
         RExC_lastparse=NULL; 
     });
+
+    /* The first pass could have found things that force Unicode semantics */
+    if ((RExC_utf8 || RExC_uni_semantics)
+        && get_regex_charset(pm_flags) == REGEX_DEPENDS_CHARSET)
+    {
+       set_regex_charset(&pm_flags, REGEX_UNICODE_CHARSET);
+    }
+
     /* Small enough for pointer-storage convention?
        If extralen==0, this means that we will not need long jumps. */
     if (RExC_size >= 0x10000L && RExC_extralen)
@@ -6274,10 +6288,9 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp,U32 depth)
                                       that follow */
                 has_use_defaults = TRUE;
                 STD_PMMOD_FLAGS_CLEAR(&RExC_flags);
-               if (RExC_utf8) {    /* But the default for a utf8 pattern is
-                                      unicode semantics */
-                   set_regex_charset(&RExC_flags, REGEX_UNICODE_CHARSET);
-               }
+               set_regex_charset(&RExC_flags, (RExC_utf8 || RExC_uni_semantics)
+                                               ? REGEX_UNICODE_CHARSET
+                                               : REGEX_DEPENDS_CHARSET);
                 goto parse_flags;
            default:
                --RExC_parse;
@@ -6325,8 +6338,9 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp,U32 depth)
 
                        /* The dual charset means unicode semantics if the
                         * pattern (or target, not known until runtime) are
-                        * utf8 */
-                       cs = (RExC_utf8)
+                        * utf8, or something in the pattern indicates unicode
+                        * semantics */
+                       cs = (RExC_utf8 || RExC_uni_semantics)
                             ? REGEX_UNICODE_CHARSET
                             : REGEX_DEPENDS_CHARSET;
                         has_charset_modifier = 1;
@@ -8600,6 +8614,9 @@ parseit:
                 * something that isn't utf8 */
                ANYOF_FLAGS(ret) |= ANYOF_NONBITMAP;
                namedclass = ANYOF_MAX;  /* no official name, but it's named */
+
+               /* \p means they want Unicode semantics */
+               RExC_uni_semantics = 1;
                }
                break;
            case 'n':   value = '\n';                   break;
index 3c3b10f..bc4a7fc 100644 (file)
@@ -1489,4 +1489,5 @@ abc\N{def -       c       -       \\N{NAME} must be resolved by the lexer
 (q1|z)*(q2|z)*z{15}-.*?(x(a|bc)*y){2,3}Z       zzzzzzzzzzzzzzzz-xayxayxayxayZ  y       $&      zzzzzzzzzzzzzzzz-xayxayxayxayZ
 
 (?:(?:)foo|bar|zot|rt78356)    foo     y       $&      foo
+/\xe0\pL/i     \xc0a   y       $&      \xc0a
 # vim: softtabstop=0 noexpandtab