@@ -213,7 +213,14 @@ impl Parser {
213
213
'?' | '*' | '+' => try!( self . push_repeater ( c) ) ,
214
214
'\\' => {
215
215
let ast = try!( self . parse_escape ( ) ) ;
216
- self . push ( ast)
216
+ if let AstClass ( mut ranges, flags) = ast {
217
+ if flags & FLAG_NOCASE > 0 {
218
+ ranges = case_fold_and_combine_ranges ( ranges) ;
219
+ }
220
+ self . push ( AstClass ( ranges, flags) )
221
+ } else {
222
+ self . push ( ast)
223
+ }
217
224
}
218
225
'{' => try!( self . parse_counted ( ) ) ,
219
226
'[' => match self . try_parse_ascii ( ) {
@@ -422,13 +429,10 @@ impl Parser {
422
429
}
423
430
']' if ranges. len ( ) > 0 => {
424
431
if self . flags & FLAG_NOCASE > 0 {
425
- // FIMXE(https://github.com/rust-lang/regex/issues/76): This is wrong.
426
- for range in & mut ranges {
427
- range. 0 = range. 0 . to_uppercase ( ) . next ( ) . unwrap ( ) ;
428
- range. 1 = range. 1 . to_uppercase ( ) . next ( ) . unwrap ( ) ;
429
- }
432
+ ranges = case_fold_and_combine_ranges ( ranges)
433
+ } else {
434
+ ranges = combine_ranges ( ranges) ;
430
435
}
431
- ranges = combine_ranges ( ranges) ;
432
436
if negated {
433
437
ranges = invert_ranges ( ranges) ;
434
438
}
@@ -983,6 +987,32 @@ fn combine_ranges(mut unordered: Vec<(char, char)>) -> Vec<(char, char)> {
983
987
ordered
984
988
}
985
989
990
+ fn case_fold_and_combine_ranges ( ranges : Vec < ( char , char ) > ) -> Vec < ( char , char ) > {
991
+ if ranges. is_empty ( ) {
992
+ return ranges
993
+ }
994
+ let mut chars: Vec < char > = ranges
995
+ . into_iter ( )
996
+ . flat_map ( |( start, end) | start as u32 .. end as u32 + 1 )
997
+ . filter_map ( char:: from_u32)
998
+ . map ( |c| c. to_uppercase ( ) . next ( ) . unwrap ( ) )
999
+ . collect ( ) ;
1000
+ chars. sort ( ) ;
1001
+ let mut chars = chars. into_iter ( ) ;
1002
+ let mut start = chars. next ( ) . unwrap ( ) ;
1003
+ let mut end = start;
1004
+ let mut ranges = Vec :: new ( ) ;
1005
+ for c in chars {
1006
+ if c != inc_char ( end) {
1007
+ ranges. push ( ( start, end) ) ;
1008
+ start = c;
1009
+ }
1010
+ end = c;
1011
+ }
1012
+ ranges. push ( ( start, end) ) ;
1013
+ ranges
1014
+ }
1015
+
986
1016
fn invert_ranges ( ranges : Vec < ( char , char ) > ) -> Vec < ( char , char ) > {
987
1017
if ranges. is_empty ( ) { return ranges; }
988
1018
0 commit comments