This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Integrate:
authorNicholas Clark <nick@ccl4.org>
Sat, 29 May 2004 20:04:40 +0000 (20:04 +0000)
committerNicholas Clark <nick@ccl4.org>
Sat, 29 May 2004 20:04:40 +0000 (20:04 +0000)
[ 22693]
Subject: [PATCH] lib/utf8_heavy.pl -- cascading classes and '&' support
From: Jeff 'japhy' Pinyan <japhy@perlmonk.org>
Date: Mon, 12 Apr 2004 20:24:48 -0400 (EDT)
Message-ID: <Pine.LNX.4.44.0404122011160.3038-200000@perlmonk.org>

[ 22713]
Subject: Re: [PATCH] lib/utf8_heavy.pl -- cascading classes and '&' support
From: "Jeff 'japhy' Pinyan" <japhy@perlmonk.org>
Date: Wed, 14 Apr 2004 17:01:38 -0400 (EDT)
Message-ID: <Pine.LNX.4.44.0404141659480.11423-301000@perlmonk.org>

[ 22714]
New file left out of the last commit.
p4raw-link: @22714 on //depot/perl: 0f1b7392b6ef0fdb863906170718343a907e3a42
p4raw-link: @22713 on //depot/perl: bac0b42524fd3607268d7139a21b07697a1c978b
p4raw-link: @22693 on //depot/perl: 09e0265ac2438ceab7fdd1011e375d10d5db2a81

p4raw-id: //depot/maint-5.8/perl@22856
p4raw-branched: from //depot/perl@22714 'branch in' t/uni/class.t
p4raw-integrated: from //depot/perl@22713 'merge in'
pod/perlunicode.pod (@22284..) MANIFEST (@22686..)
p4raw-integrated: from //depot/perl@22693 'copy in' lib/utf8_heavy.pl
(@19835..)

MANIFEST
lib/utf8_heavy.pl
pod/perlunicode.pod
t/uni/class.t [new file with mode: 0644]

index a35d3c3..9b25258 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -2945,6 +2945,7 @@ t/TestInit.pm                     Preamble library for core tests
 t/test.pl                      Simple testing library
 t/uni/case.pl                  See if Unicode casing works
 t/uni/chomp.t                  See if Unicode chomp works
+t/uni/class.t                  See if Unicode classes work (\p)
 t/uni/fold.t                   See if Unicode folding works
 t/uni/lower.t                  See if Unicode casing works
 t/uni/sprintf.t                        See if Unicode sprintf works
index f4a0aaa..668a176 100644 (file)
@@ -88,7 +88,7 @@ sub SWASHNEW {
            ## It could be a user-defined property.
            ##
 
-           my $caller1 = caller(1);
+           my $caller1 = $type =~ s/(.+)::// ? $1 : caller(1);
 
            if (defined $caller1 && $type =~ /^(?:\w+)$/) {
                my $prop = $caller1 . "::" . ( $wasIs ? "Is" : "" ) . $type;
@@ -108,6 +108,7 @@ sub SWASHNEW {
 
            if (defined $caller0 && $type =~ /^To(?:\w+)$/) {
                my $map = $caller0 . "::" . $type;
+
                if (exists &{$map}) {
                    no strict 'refs';
                    
@@ -203,11 +204,14 @@ sub SWASHNEW {
            my $char = $1;
            my $name = $2;
            print STDERR "$1 => $2\n" if DEBUG;
-           if ($char =~ /[-+!]/) {
+           if ($char =~ /[-+!&]/) {
                my ($c,$t) = split(/::/, $name, 2);     # bogus use of ::, really
                my $subobj;
                if ($c eq 'utf8') {
-                   $subobj = $c->SWASHNEW($t, "", 0, 0, 0);
+                   $subobj = utf8->SWASHNEW($t, "", 0, 0, 0);
+               }
+               elsif (exists &$name) {
+                   $subobj = utf8->SWASHNEW($name, "", 0, 0, 0);
                }
                elsif ($c =~ /^([0-9a-fA-F]+)/) {
                    $subobj = utf8->SWASHNEW("", $c, 0, 0, 0);
@@ -315,7 +319,7 @@ sub SWASHGET {
     }
     for my $x ($self->{EXTRAS}) {
        pos $x = 0;
-       while ($x =~ /^([-+!])(.*)/mg) {
+       while ($x =~ /^([-+!&])(.*)/mg) {
            my $char = $1;
            my $name = $2;
            print STDERR "INDIRECT $1 $2\n" if DEBUG;
@@ -356,6 +360,18 @@ sub SWASHGET {
                    }
                }
            }
+           elsif ($char eq '&') {
+               if ($bits == 1 and $otherbits == 1) {
+                   $swatch &= $other;
+               }
+               else {
+                   for ($key = 0; $key < $len; $key++) {
+                       if (!vec($other, $key, $otherbits)) {
+                           vec($swatch, $key, $bits) = 0;
+                       }
+                   }
+               }
+           }
        }
     }
     if (DEBUG) {
index 5aa3d7d..75c176f 100644 (file)
@@ -640,10 +640,21 @@ And finally, C<scalar reverse()> reverses by character rather than by byte.
 =head2 User-Defined Character Properties
 
 You can define your own character properties by defining subroutines
-whose names begin with "In" or "Is".  The subroutines must be defined
-in the C<main> package.  The user-defined properties can be used in the
-regular expression C<\p> and C<\P> constructs.  Note that the effect
-is compile-time and immutable once defined.
+whose names begin with "In" or "Is".  The subroutines can be defined in
+any package.  The user-defined properties can be used in the regular
+expression C<\p> and C<\P> constructs; if you are using a user-defined
+property from a package other than the one you are in, you must specify
+its package in the C<\p> or C<\P> construct.
+
+    # assuming property IsForeign defined in Lang::
+    package main;  # property package name required
+    if ($txt =~ /\p{Lang::IsForeign}+/) { ... }
+
+    package Lang;  # property package name not required
+    if ($txt =~ /\p{IsForeign}+/) { ... }
+
+
+Note that the effect is compile-time and immutable once defined.
 
 The subroutines must return a specially-formatted string, with one
 or more newline-separated lines.  Each line must be one of the following:
@@ -658,23 +669,30 @@ tabular characters) denoting a range of Unicode code points to include.
 =item *
 
 Something to include, prefixed by "+": a built-in character
-property (prefixed by "utf8::"), to represent all the characters in that
-property; two hexadecimal code points for a range; or a single
-hexadecimal code point.
+property (prefixed by "utf8::") or a user-defined character property,
+to represent all the characters in that property; two hexadecimal code
+points for a range; or a single hexadecimal code point.
 
 =item *
 
 Something to exclude, prefixed by "-": an existing character
-property (prefixed by "utf8::"), for all the characters in that
-property; two hexadecimal code points for a range; or a single
-hexadecimal code point.
+property (prefixed by "utf8::") or a user-defined character property,
+to represent all the characters in that property; two hexadecimal code
+points for a range; or a single hexadecimal code point.
 
 =item *
 
 Something to negate, prefixed "!": an existing character
-property (prefixed by "utf8::") for all the characters except the
-characters in the property; two hexadecimal code points for a range;
-or a single hexadecimal code point.
+property (prefixed by "utf8::") or a user-defined character property,
+to represent all the characters in that property; two hexadecimal code
+points for a range; or a single hexadecimal code point.
+
+=item *
+
+Something to intersect with, prefixed by "&": an existing character
+property (prefixed by "utf8::") or a user-defined character property,
+for all the characters except the characters in the property; two
+hexadecimal code points for a range; or a single hexadecimal code point.
 
 =back
 
@@ -722,6 +740,19 @@ The negation is useful for defining (surprise!) negated classes.
     END
     }
 
+Intersection is useful for getting the common characters matched by
+two (or more) classes.
+
+    sub InFooAndBar {
+        return <<'END';
+    +main::Foo
+    &main::Bar
+    END
+    }
+
+It's important to remember not to use "&" for the first set -- that
+would be intersecting with nothing (resulting in an empty set).
+
 You can also define your own mappings to be used in the lc(),
 lcfirst(), uc(), and ucfirst() (or their string-inlined versions).
 The principle is the same: define subroutines in the C<main> package
diff --git a/t/uni/class.t b/t/uni/class.t
new file mode 100644 (file)
index 0000000..24f65fa
--- /dev/null
@@ -0,0 +1,41 @@
+BEGIN {
+    chdir 't' if -d 't';
+    @INC = qw(../lib .);
+    require "test.pl";
+}
+
+plan tests => 4;
+
+sub MyUniClass {
+  <<END;
+0030   004F
+END
+}
+
+sub Other::Class {
+  <<END;
+0040   005F
+END
+}
+
+sub A::B::Intersection {
+  <<END;
++main::MyUniClass
+&Other::Class
+END
+}
+
+
+my $str = join "", map chr($_), 0x20 .. 0x6F;
+
+# make sure it finds built-in class
+is(($str =~ /(\p{Letter}+)/)[0], 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
+
+# make sure it finds user-defined class
+is(($str =~ /(\p{MyUniClass}+)/)[0], '0123456789:;<=>?@ABCDEFGHIJKLMNO');
+
+# make sure it finds class in other package
+is(($str =~ /(\p{Other::Class}+)/)[0], '@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_');
+
+# make sure it finds class in other OTHER package
+is(($str =~ /(\p{A::B::Intersection}+)/)[0], '@ABCDEFGHIJKLMNO');