File Coverage

blib/lib/ShiftJIS/Regexp/Class.pm
Criterion Covered Total %
statement 198 238 83.1
branch 193 260 74.2
condition 56 81 69.1
subroutine 16 16 100.0
pod 0 8 0.0
total 463 603 76.7


line stmt bran cond sub pod time code
1             package ShiftJIS::Regexp::Class;
2 6     6   35 use strict;
  6         9  
  6         215  
3 6     6   31 use Carp;
  6         9  
  6         446  
4              
5 6     6   51 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  6         140  
  6         709  
6             $VERSION = '1.03';
7              
8             require Exporter;
9             @ISA = qw(Exporter);
10             @EXPORT = qw(parse_class parse_prop parse_regex rechar);
11             @EXPORT_OK = qw();
12              
13 6     6   30 use vars qw(%AbbrevProp %Re %Eq %Err $Char $Trail);
  6         11  
  6         2126  
14 6     6   4051 use ShiftJIS::Regexp::Const qw(%AbbrevProp %Re %Err $Char $Trail);
  6         19  
  6         1530  
15 6     6   15926 use ShiftJIS::Regexp::Equiv qw(%Eq);
  6         18  
  6         46240  
16              
17             my $Open = 5.005 > $] ? '(?:' : '(?-i:';
18             my $OpenRe = quotemeta $Open;
19             my $Close = ')';
20             my $InClassRe = '[\-0-9A-Za-z\\\\]';
21              
22             sub __ord ($) {
23 478 100   478   2268 length($_[0]) > 1 ? unpack('n', $_[0]) : ord($_[0]);
24             }
25              
26             sub __ord2($) {
27 362 50   362   1705 0xFF < $_[0] ? unpack('C*', pack 'n', $_[0]) : chr($_[0]);
28             }
29              
30             sub rechar ($;$)
31             {
32 628     628 0 962 my $c = shift;
33 628   100     7921 my $mod = shift || '';
34 628 100       1299 if (1 == length $c) {
35 412         530 my $o = ord $c;
36 412 100 33     2115 return $mod =~ /i/
    50 66        
    100          
37             ? 0x41 <= $o && $o <= 0x5A
38             ? sprintf('[\\x%02x\\x%02x]', $o, $o + 0x20)
39             : 0x61 <= $o && $o <= 0x7A
40             ? sprintf('[\\x%02x\\x%02x]', $o, $o - 0x20)
41             : sprintf('\\x%02x', $o)
42             : sprintf('\\x%02x', $o)
43             }
44 216         361 my $d = ord substr($c,1,1); # the trail byte
45 216 50 100     5485 my $rechar =
    100 100        
    100 33        
    100 66        
    100 33        
    100 33        
    50 33        
    50 33        
    50 100        
    50 100        
    100 100        
    50 66        
    100 100        
    100 66        
46             $c =~ /^\x82([\x60-\x79])$/ && $mod =~ /I/
47             ? sprintf('\x82[\x%02x\x%02x]', $d, $d + 33)
48             : $c =~ /^\x82([\x81-\x9A])$/ && $mod =~ /I/
49             ? sprintf('\x82[\x%02x\x%02x]', $d, $d - 33)
50             : $c =~ /^\x83([\x9F-\xB6])$/ && $mod =~ /I/
51             ? sprintf('\x83[\x%02x\x%02x]', $d, $d + 32)
52             : $c =~ /^\x83([\xBF-\xD6])$/ && $mod =~ /I/
53             ? sprintf('\x83[\x%02x\x%02x]', $d, $d - 32)
54             : $c =~ /^\x84([\x40-\x4E])$/ && $mod =~ /I/
55             ? sprintf('\x84[\x%02x\x%02x]', $d, $d + 48)
56             : $c =~ /^\x84([\x4F-\x60])$/ && $mod =~ /I/
57             ? sprintf('\x84[\x%02x\x%02x]', $d, $d + 49)
58             : $c =~ /^\x84([\x70-\x7E])$/ && $mod =~ /I/
59             ? sprintf('\x84[\x%02x\x%02x]', $d, $d - 48)
60             : $c =~ /^\x84([\x80-\x91])$/ && $mod =~ /I/
61             ? sprintf('\x84[\x%02x\x%02x]', $d, $d - 49)
62             : $c =~ /^\x82([\x9F-\xDD])$/ && $mod =~ /j/
63             ? sprintf('\x82\x%02x|\x83\x%02x', $d, $d - 0x5F)
64             : $c =~ /^\x82([\xDE-\xF1])$/ && $mod =~ /j/
65             ? sprintf('\x82\x%02x|\x83\x%02x', $d, $d - 0x5E)
66             : $c =~ /^\x83([\x40-\x7E])$/ && $mod =~ /j/
67             ? sprintf('\x83\x%02x|\x82\x%02x', $d, $d + 0x5F)
68             : $c =~ /^\x83([\x80-\x93])$/ && $mod =~ /j/
69             ? sprintf('\x83\x%02x|\x82\x%02x', $d, $d + 0x5E)
70             : $c =~ /^\x81([\x52-\x53])$/ && $mod =~ /j/
71             ? sprintf('\x81[\x%02x\x%02x]', $d, $d + 2)
72             : $c =~ /^\x81([\x54-\x55])$/ && $mod =~ /j/
73             ? sprintf('\x81[\x%02x\x%02x]', $d, $d - 2)
74             : sprintf('\x%02x\x%02x', unpack 'C2', $c);
75 216         717 return "$Open$rechar$Close";
76             }
77              
78              
79             #
80             # parse_regex('R', ref to string)
81             # returning '\R{padA}' etc.
82             #
83             sub parse_regex ($$) {
84 1     1 0 4 my($key, $rev);
85 1         6 my $r = shift;
86 1         3 for (${ $_[0] }) {
  1         9  
87 1 50       18 if (s/^\{//) {
88 1 50       14 if (s/^([0-9A-Za-z]+)\}//) {
    0          
89 1         28 $key = lc $1;
90             }
91             elsif (s/^([0-9A-Za-z]*(?![0-9A-Za-z])$Char)//o) {
92 0         0 croak sprintf($Err{notAlnum}, "\\R\{$1");
93             }
94             else {
95 0         0 croak sprintf($Err{notTermin}, "\\R\{$_}", '}');
96             }
97             } else {
98 0         0 croak sprintf($Err{notBrace}, '\R');
99             }
100             }
101 1         11 return "\\R\{$key\}";
102             }
103              
104              
105             #
106             # parse_prop('p' or 'P', ref to string)
107             # returning '\p{digit}' etc.
108             #
109             sub parse_prop ($$) {
110 432     432 0 931 my($key, $rev);
111 432         1209 my $p = shift;
112 432         642 for (${ $_[0] }) {
  432         1123  
113 432 100       1915 if (s/^\{//) {
114 206 100       663 $rev = s/^\^// ? '^' : '';
115 206         405 s/^I[sn]//; # XXX, deprecated
116 206 50       1029 if (s/^([0-9A-Za-z]+)\}//) {
    0          
117 206         838 $key = lc $1;
118             }
119             elsif (s/^([0-9A-Za-z]*(?![0-9A-Za-z])$Char)//o) {
120 0         0 croak sprintf($Err{notAlnum}, "\\$p\{$rev$1");
121             }
122             else {
123 0         0 croak sprintf($Err{notTermin}, "\\$p\{$_}", '}');
124             }
125             } else {
126 226 100       690 $rev = s/^\^// ? '^' : '';
127 226 50       976 if (s/^([\x21-\x7e])//) {
    0          
128 226   33     1743 $key = $AbbrevProp{uc $1} || $1;
129             }
130             elsif (s/^($Char)//o) {
131 0         0 croak sprintf($Err{notASCII}, "\\$p$rev$1");
132             }
133             else {
134 0         0 croak sprintf($Err{notTermin}, "\\$p^", '');
135             }
136             }
137             }
138 432 100       1247 if ($rev) {
139 6 100       31 $p = $p eq 'p' ? 'P' : 'p';
140             }
141 432         2072 return "\\$p\{$key\}";
142             }
143              
144              
145             #
146             # parse_posix(ref to string)
147             # called after "[:" in a character class.
148             # returning '\p{digit}' etc.
149             #
150             sub parse_posix ($) {
151 86     86 0 173 my($key, $rev);
152              
153 86         153 for(${ $_[0] }) {
  86         276  
154 86 100       441 $rev = s/^\^// ? '^' : '';
155 86 50       726 if (s/^([0-9A-Za-z]+)\:\]//) {
    0          
156 86         393 $key = lc $1;
157             }
158             elsif (s/^([0-9A-Za-z]*(?![:])$Char)//o) {
159 0         0 croak sprintf($Err{notAlnum}, "[:$rev$1");
160             }
161             else {
162 0         0 croak sprintf($Err{notTermin}, "[:$rev$_", ":]");
163             }
164             }
165 86 100       487 return $rev ? "\\P\{$key\}" : "\\p\{$key\}";
166             }
167              
168              
169             #
170             # parse_char(ref to string)
171             # returning a single- or double-byte char.
172             #
173             sub parse_char ($) {
174 1138     1138 0 1251 for (${ $_[0] }) {
  1138         2433  
175 1138 50       2261 if ($_ eq '\\') {
176 0         0 croak sprintf($Err{backtips});
177             }
178 1138 50       2727 if (s/^\\([0-7][0-7][0-7])//) {
179 0         0 return chr(oct $1);
180             }
181 1138 100       3132 if (s/^\\x//) {
182 499 100       1354 if (s/^([0-9A-Fa-f][0-9A-Fa-f])//) {
183 179         838 return chr(hex $1);
184             }
185 320 50       1375 if (s/^\{([0-9A-Fa-f]{4})\}//) {
186 320         1499 return pack('n', hex $1);
187             }
188 0 0       0 if (length) {
189 0         0 croak sprintf($Err{invalHex}, $_);
190             } else {
191 0         0 croak sprintf($Err{notTermin}, '\x{$_', '}');
192             }
193             }
194 639 100       1438 if (s/^\\c//) {
195 62 50       207 if (s/([\x00-\x7F])//) {
196 62         265 return chr(ord(uc $1) ^ 64);
197             }
198 0 0       0 if (length) {
199 0         0 croak sprintf($Err{invalFlw}, ord, '\c', '[\x00-\x7F]');
200             } else {
201 0         0 croak sprintf($Err{notTermin}, '\c');
202             }
203             }
204 577 100       1238 if (s/^\\a//) { return "\a" }
  5         15  
205 572 100       1104 if (s/^\\b//) { return "\b" }
  3         47  
206 569 100       1105 if (s/^\\e//) { return "\e" }
  3         11  
207 566 100       1012 if (s/^\\f//) { return "\f" }
  5         15  
208 561 100       1011 if (s/^\\n//) { return "\n" }
  5         13  
209 556 100       1283 if (s/^\\r//) { return "\r" }
  5         12  
210 551 100       1008 if (s/^\\t//) { return "\t" }
  5         16  
211 546 100       1158 if (s/^\\0//) { return "\0" }
  14         47  
212 532 50       1058 if (s/^\\([0-9A-Za-z])//) {
213 0         0 croak sprintf($Err{invalMch}, "\\$1");
214             }
215 532 50       2452 if (s/^\\?($Char)//o) { return $1 }
  532         2131  
216 0         0 croak sprintf($Err{oddTrail}, ord);
217             }
218             }
219              
220             #
221             # parse_literal(string)
222             # returning a literal.
223             #
224             sub parse_literal ($) {
225 393     393 0 619 my $str = shift;
226 393         454 my $ret = '';
227 393         1259 $ret .= parse_char(\$str) while length $str;
228 393         783 return $ret;
229             }
230              
231              
232             sub expand ($$;$)
233             {
234 239     239 0 496 my($fr, $to, $mod) = @_;
235 239   100     1098 $mod ||= '';
236 239         339 my($ini, $fin, $i, $ch, @retv, @retd, $add);
237 0         0 my($ini_f, $fin_f, $ini_t, $fin_t, $ini_c, $fin_c);
238              
239 239 50       565 if ($fr > $to) { croak sprintf($Err{revRange}, $fr, $to) }
  0         0  
240              
241 239 100       508 if ($fr <= 0x7F) {
242 66 50       146 $ini = $fr < 0x00 ? 0x00 : $fr;
243 66 100       140 $fin = $to > 0x7F ? 0x7F : $to;
244 66 100       222 if ($ini == $fin) {
    50          
245 2         6 push @retv, rechar(chr($ini),$mod);
246             } elsif ($ini < $fin) {
247 64 100       166 if ($mod =~ /i/) {
248 12         47 for ($i=$ini; $i<=$fin; $i++) {
249 283 100 100     989 $add .= lc(chr $i) if 0x41 <= $i && $i <= 0x5A;
250 283 100 66     1035 $add .= uc(chr $i) if 0x61 <= $i && $i <= 0x7A;
251             }
252 52         87 } else { $add = '' }
253 64         385 push @retv, sprintf "[\\x%02x-\\x%02x$add]", $ini, $fin;
254             }
255             }
256              
257 239 100       640 if ($fr <= 0xDF) {
258 78 100       161 $ini = $fr < 0xA1 ? 0xA1 : $fr;
259 78 100       179 $fin = $to > 0xDF ? 0xDF : $to;
260 78 50       272 if ($ini == $fin) {
    100          
261 0         0 push @retd, sprintf('\\x%2x', $ini);
262             } elsif ($ini < $fin) {
263 18         115 push @retd, sprintf('[\\x%2x-\\x%2x]', $ini, $fin);
264             }
265             }
266              
267 239 100       604 $ini = $fr < 0x8140 ? 0x8140 : $fr;
268 239 50       511 $fin = $to > 0xFCFC ? 0xFCFC : $to;
269 239 100       568 if ($ini <= $fin) {
270 165         513 ($ini_f,$ini_t) = __ord2($ini);
271 165         383 ($fin_f,$fin_t) = __ord2($fin);
272 165 100       345 if ($ini_f == $fin_f) {
273 111 50 100     1472 push @retd,
    100 66        
    50          
    100          
    50          
274             $ini_t == $fin_t ?
275             sprintf('\x%2x\x%2x', $ini_f, $ini_t) :
276             $fin_t <= 0x7E || 0x80 <= $ini_t ?
277             sprintf('\x%2x[\x%2x-\x%2x]', $ini_f, $ini_t, $fin_t) :
278             $ini_t == 0x7E && $fin_t == 0x80 ?
279             sprintf('\x%2x[\x7e\x80]', $ini_f) :
280             $ini_t == 0x7E ?
281             sprintf('\x%2x[\x7e\x80-\x%2x]', $ini_f, $fin_t) :
282             $fin_t == 0x80 ?
283             sprintf('\x%2x[\x%2x-\x7e\x80]', $ini_f, $ini_t) :
284             sprintf('\x%2x[\x%2x-\x7e\x80-\x%2x]',$ini_f, $ini_t, $fin_t);
285             } else {
286 54 50       241 $ini_c = $ini_t == 0x40 ? $ini_f :
    100          
287             $ini_f == 0x9F ? 0xE0 : $ini_f + 1;
288 54 50       172 $fin_c = $fin_t == 0xFC ? $fin_f :
    100          
289             $fin_f == 0xE0 ? 0x9F : $fin_f - 1;
290              
291 54 100       130 if ($ini_t != 0x40) {
292 29 50       192 push @retd,
    100          
    100          
293             $ini_t == 0xFC ?
294             sprintf('\x%2x\xfc', $ini_f) :
295             0x80 <= $ini_t ?
296             sprintf('\x%2x[\x%2x-\xfc]', $ini_f, $ini_t) :
297             $ini_t == 0x7E ?
298             sprintf('\x%2x[\x7e\x80-\xfc]', $ini_f) :
299             sprintf('\x%2x[\x%2x-\x7e\x80-\xfc]', $ini_f, $ini_t);
300             }
301 54 100       124 if ($ini_c <= $fin_c) {
302 45 50 100     424 my $lead =
    50 33        
    50          
    100          
    100          
303             $ini_c == $fin_c
304             ? sprintf('\x%2x', $ini_c) :
305             $fin_c <= 0x9F || 0xE0 <= $ini_c
306             ? sprintf('[\x%2x-\x%2x]', $ini_c, $fin_c) :
307             $ini_c == 0x9F && $fin_c == 0xE0
308             ? '[\x9f\xe0]' :
309             $ini_c == 0x9F
310             ? sprintf('[\x9f\xe0-\x%2x]', $fin_c) :
311             $fin_c == 0xE0
312             ? sprintf('[\x%2x-\x9f\xe0]', $ini_c)
313             : sprintf('[\x%2x-\x9f\xe0-\x%2x]', $ini_c, $fin_c);
314 45         135 push @retd, $lead.$Trail;
315             }
316 54 100       207 if ($fin_t != 0xFC) {
317 41 50       324 push @retd,
    100          
    100          
318             $fin_t == 0x40 ?
319             sprintf('\x%2x\x40', $fin_f) :
320             $fin_t <= 0x7E ?
321             sprintf('\x%2x[\x40-\x%2x]', $fin_f, $fin_t) :
322             $fin_t == 0x80 ?
323             sprintf('\x%2x[\x40-\x7e\x80]', $fin_f) :
324             sprintf('\x%2x[\x40-\x7e\x80-\x%2x]', $fin_f, $fin_t);
325             }
326             }
327             }
328 239 100       622 if ($mod =~ /I/) {
329 12         113 foreach (
330             [0x8260, 0x8279, +33], # Full A to Z
331             [0x8281, 0x829A, -33], # Full a to z
332             [0x839F, 0x83B6, +32], # Greek Alpha to Omega
333             [0x83BF, 0x83D6, -32], # Greek alpha to omega
334             [0x8440, 0x844E, +48], # Cyrillic A to N
335             [0x8470, 0x847E, -48], # Cyrillic a to n
336             [0x844F, 0x8460, +49], # Cyrillic O to Ya
337             [0x8480, 0x8491, -49], # Cyrillic o to ya
338             ) {
339 96 100 100     367 if ($fr <= $_->[1] && $_->[0] <= $to) {
340 16 50       62 ($ini_f,$ini_t) = __ord2($fr <= $_->[0] ? $_->[0] : $fr);
341 16 50       98 ($fin_f,$fin_t) = __ord2($_->[1] <= $to ? $_->[1] : $to);
342 16         90 push @retd, sprintf('\x%02x[\x%02x-\x%02x]',
343             $ini_f, $ini_t + $_->[2], $fin_t + $_->[2]);
344             }
345             }
346             }
347 239 50       633 if ($mod =~ /j/) {
348 0         0 foreach (
349             [0x829F, 0x82DD, -0x5F, 0x83], # Hiragana Small A to Mi
350             [0x82DE, 0x82F1, -0x5E, 0x83], # Hiragana Mu to N
351             [0x8340, 0x837E, +0x5F, 0x82], # Katakana Small A to Mi
352             [0x8380, 0x8393, +0x5E, 0x82], # Katakana Mu to N
353             [0x8152, 0x8153, +2, 0x81], # Katakana Iteration Marks
354             [0x8154, 0x8155, -2, 0x81], # Hiragana Iteration Marks
355             ) {
356 0 0 0     0 if ($fr <= $_->[1] && $_->[0] <= $to) {
357 0 0       0 ($ini_f,$ini_t) = __ord2($fr <= $_->[0] ? $_->[0] : $fr);
358 0 0       0 ($fin_f,$fin_t) = __ord2($_->[1] <= $to ? $_->[1] : $to);
359 0         0 push @retd, sprintf('\x%02x[\x%02x-\x%02x]',
360             $_->[3], $ini_t + $_->[2], $fin_t + $_->[2]);
361             }
362             }
363             }
364 239 100       1441 return(@retv, @retd ? $Open.join('|',@retd).$Close : ());
365             }
366              
367              
368              
369             #
370             # parse_class(ref to string, mode)
371             # called after "[" at the beginning of a character class.
372             # returning a byte-oriented regexp.
373             #
374             sub parse_class ($;$) {
375 874     874 0 1406 my(@re, $subclass);
376 874   100     4328 my $mod = $_[1] || '';
377 874         1557 my $state = 0; # enum: initial, char, range, subclass, last;
378              
379 874         1289 for (${ $_[0] }) {
  874         2325  
380 874         2220 while (length) {
381 2564 100       7221 if (s/^\]//) {
382 874 50       2263 if (@re) {
383 874 100       2483 if ($state == 1) {
    50          
384 106         283 push @re, rechar(pop(@re), $mod);
385             } elsif ($state == 2) {
386 0         0 push @re, rechar(pop(@re), $mod);
387 0         0 push @re, rechar('-', $mod);
388             }
389             } else {
390 0         0 push(@re, ']');
391 0         0 $state = 1;
392 0         0 next;
393             }
394 874         1411 $state = 4;
395 874         2477 last;
396             }
397 1690 100       4016 if (s/^\-//) {
398 239 50       949 if ($state == 0) {
    50          
    0          
399 0         0 push(@re, '-');
400 0         0 $state = 1;
401             } elsif ($state == 1) {
402 239         613 $state = 2;
403             } elsif ($state == 2) {
404 0         0 push @re, expand(__ord(pop(@re)), __ord('-'), $mod);
405 0         0 $state = 0;
406             } else {
407 0         0 croak sprintf($Err{invalRng}, "-$_");
408             }
409 239         580 next;
410             }
411              
412 1451         1987 $subclass = undef;
413 1451 100       10126 if (s/^\[\://) {
    100          
    100          
    100          
    100          
414 86         585 my $key = parse_posix(\$_);
415 86 50       470 $subclass = defined $Re{$key} ? $Re{$key}
416             : croak sprintf($Err{Undef}, $key);
417             } elsif(s/^\\([pP])//) { # prop
418 205         1363 my $key = parse_prop($1, \$_);
419 205 50       998 $subclass = defined $Re{$key} ? $Re{$key}
420             : croak sprintf($Err{Undef}, $key);
421             } elsif(s/^(\\[dwsDWS])//) {
422 18         83 $subclass = $Re{ $1 };
423             } elsif(s/^\[=\\?([\\=])=\]//) {
424 4 50       21 $subclass = defined $Eq{$1} ? $Eq{$1} : rechar($1,$mod);
425             } elsif(s/^\[=([^=]+)=\]//) {
426 393         737 my $lit = parse_literal($1);
427 393 100       1236 $subclass = defined $Eq{$lit} ? $Eq{$lit} : rechar($lit,$mod);
428             }
429              
430 1451 100       8498 if (defined $subclass) {
431 706 50       2872 if ($state == 1) {
    50          
432 0         0 push @re, rechar(pop(@re), $mod);
433             } elsif($state == 2) {
434 0         0 croak sprintf($Err{invalRng}, "-$_");
435             }
436 706         1233 push @re, $subclass;
437 706         936 $state = 3;
438 706         1878 next;
439             }
440              
441 745         1842 my $char = parse_char(\$_);
442 745 100       2224 if ($state == 1) {
    100          
443 161         372 push @re, rechar(pop(@re), $mod);
444 161         328 push @re, $char;
445 161         393 $state = 1;
446             } elsif ($state == 2) {
447 239         816 push @re, expand(__ord(pop(@re)), __ord($char), $mod);
448 239         798 $state = 0;
449             } else {
450 345         611 push @re, $char;
451 345         888 $state = 1;
452             }
453             }
454             }
455              
456 874 50       2365 if ($state != 4) {
457 0         0 croak sprintf($Err{notTermin}, "character class", ']');
458             }
459              
460             # contract: e.g. ('\x81\x40', '\x81[\x44-\x48]') to ('\x81[\x40\x44-\x48]').
461              
462 874         1159 my ($pre, @retv, $r);
463 874         1538 push @retv, shift @re;
464 874         4237 $retv[0] =~ s/^(?:$OpenRe)? \[ ($InClassRe+) \] \)? $/[$1]/xo;
465 874         3491 $retv[0] =~ s/^(?:$OpenRe)? (\\x[0-9A-Fa-f]{2}) \)? $/[$1]/xo;
466 874         2768 $retv[0] =~ s/^(?:$OpenRe)? (\\x[0-9A-Fa-f]{2}) \[ ($InClassRe+) \] \)? $/${1}[$2]/xo;
467 874         2044 $retv[0] =~ s/^(?:$OpenRe)? (\\x[0-9A-Fa-f]{2}) (\\x[0-9A-Fa-f]{2}) \)? $/${1}[$2]/xo;
468              
469 874         1909 foreach $r (@re) {
470 344         1050 $r =~ s/^(?:$OpenRe)? \[ ($InClassRe+) \] \)? $/[$1]/xo;
471 344         1170 $r =~ s/^(?:$OpenRe)? (\\x[0-9A-Fa-f]{2}) \)? $/[$1]/xo;
472 344         1446 $r =~ s/^(?:$OpenRe)? (\\x[0-9A-Fa-f]{2})
473             \[ ($InClassRe+) \] \)? $/${1}[$2]/xo;
474 344         1209 $r =~ s/^(?:$OpenRe)? (\\x[0-9A-Fa-f]{2})
475             (\\x[0-9A-Fa-f]{2}) \)? $/${1}[$2]/xo;
476              
477 344 100       2518 if ("$retv[-1]|$r" =~ /^ \[($InClassRe+)\] \| \[($InClassRe+)\] $/xo) {
    100          
478 80         312 $retv[-1] = "[$1$2]";
479             }
480             elsif ("$retv[-1]|$r" =~ /^
481             (\\x[0-9A-Fa-f]{2}) \[($InClassRe+)\] \| \1 \[($InClassRe+)\] $/xo)
482             {
483 109         402 $retv[-1] = "$1\[$2$3\]";
484             }
485             else {
486 155         338 $retv[-1] =~ s/^\[(\\x[0-9A-Fa-f]{2})\]$/$1/x;
487 155         425 $retv[-1] =~ s/^(\\x[0-9A-Fa-f]{2})\[(\\x[0-9A-Fa-f]{2})\]$/$1$2/x;
488 155         428 push(@retv, $r);
489             }
490             }
491              
492 874         2344 $retv[-1] =~ s/^\[(\\x[0-9A-Fa-f]{2})\]$/$1/x;
493 874         1578 $retv[-1] =~ s/^(\\x[0-9A-Fa-f]{2})\[(\\x[0-9A-Fa-f]{2})\]$/$1$2/x;
494              
495 874         5021 return $Open.join('|', @retv).$Close;
496             }
497              
498             1;
499             __END__