Skip to content

Commit 4769bca

Browse files
committed
auto merge of #18282 : pczarn/rust/regex-parse, r=burntsushi
Fixes #18034 3 bugs fixed.
2 parents dd71136 + f219773 commit 4769bca

File tree

2 files changed

+55
-24
lines changed

2 files changed

+55
-24
lines changed

src/libregex/parse.rs

+27-24
Original file line numberDiff line numberDiff line change
@@ -374,16 +374,12 @@ impl<'a> Parser<'a> {
374374
let mut ranges: Vec<(char, char)> = vec!();
375375
let mut alts: Vec<Ast> = vec!();
376376

377-
if self.peek_is(1, ']') {
378-
try!(self.expect(']'))
379-
ranges.push((']', ']'))
380-
}
381377
while self.peek_is(1, '-') {
382-
try!(self.expect('-'))
378+
try!(self.expect('-'));
383379
ranges.push(('-', '-'))
384380
}
385381
loop {
386-
try!(self.noteof("a closing ']' or a non-empty character class)"))
382+
try!(self.noteof("a closing ']' or a non-empty character class)"));
387383
let mut c = self.cur();
388384
match c {
389385
'[' =>
@@ -411,10 +407,7 @@ impl<'a> Parser<'a> {
411407
ast => fail!("Unexpected AST item '{}'", ast),
412408
}
413409
}
414-
_ => {},
415-
}
416-
match c {
417-
']' => {
410+
']' if ranges.len() > 0 || alts.len() > 0 => {
418411
if ranges.len() > 0 {
419412
let flags = negated | (self.flags & FLAG_NOCASE);
420413
let mut ast = AstClass(combine_ranges(ranges), flags);
@@ -431,22 +424,32 @@ impl<'a> Parser<'a> {
431424
}
432425
return Ok(())
433426
}
434-
c => {
435-
if self.peek_is(1, '-') && !self.peek_is(2, ']') {
436-
try!(self.expect('-'))
437-
try!(self.noteof("not a ']'"))
438-
let c2 = self.cur();
439-
if c2 < c {
440-
return self.err(format!("Invalid character class \
441-
range '{}-{}'",
442-
c,
443-
c2).as_slice())
444-
}
445-
ranges.push((c, self.cur()))
446-
} else {
447-
ranges.push((c, c))
427+
_ => {}
428+
}
429+
430+
if self.peek_is(1, '-') && !self.peek_is(2, ']') {
431+
try!(self.expect('-'));
432+
// The regex can't end here.
433+
try!(self.noteof("not a ']'"));
434+
// End the range with a single character or character escape.
435+
let mut c2 = self.cur();
436+
if c2 == '\\' {
437+
match try!(self.parse_escape()) {
438+
Literal(c3, _) => c2 = c3, // allow literal escapes below
439+
ast =>
440+
return self.err(format!("Expected a literal, but got {}.",
441+
ast).as_slice()),
448442
}
449443
}
444+
if c2 < c {
445+
return self.err(format!("Invalid character class \
446+
range '{}-{}'",
447+
c,
448+
c2).as_slice())
449+
}
450+
ranges.push((c, self.cur()))
451+
} else {
452+
ranges.push((c, c))
450453
}
451454
}
452455
}

src/libregex/test/tests.rs

+28
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,30 @@ fn empty_regex_nonempty_match() {
4343
assert_eq!(ms, vec![(0, 0), (1, 1), (2, 2), (3, 3)]);
4444
}
4545

46+
#[test]
47+
fn quoted_bracket_set() {
48+
let re = regex!(r"([\x{5b}\x{5d}])");
49+
let ms = re.find_iter("[]").collect::<Vec<(uint, uint)>>();
50+
assert_eq!(ms, vec![(0, 1), (1, 2)]);
51+
let re = regex!(r"([\[\]])");
52+
let ms = re.find_iter("[]").collect::<Vec<(uint, uint)>>();
53+
assert_eq!(ms, vec![(0, 1), (1, 2)]);
54+
}
55+
56+
#[test]
57+
fn first_range_starts_with_left_bracket() {
58+
let re = regex!(r"([[-z])");
59+
let ms = re.find_iter("[]").collect::<Vec<(uint, uint)>>();
60+
assert_eq!(ms, vec![(0, 1), (1, 2)]);
61+
}
62+
63+
#[test]
64+
fn range_ends_with_escape() {
65+
let re = regex!(r"([\[-\x{5d}])");
66+
let ms = re.find_iter("[]").collect::<Vec<(uint, uint)>>();
67+
assert_eq!(ms, vec![(0, 1), (1, 2)]);
68+
}
69+
4670
macro_rules! replace(
4771
($name:ident, $which:ident, $re:expr,
4872
$search:expr, $replace:expr, $result:expr) => (
@@ -114,6 +138,10 @@ noparse!(fail_double_neg, "(?-i-i)")
114138
noparse!(fail_neg_empty, "(?i-)")
115139
noparse!(fail_empty_group, "()")
116140
noparse!(fail_dupe_named, "(?P<a>.)(?P<a>.)")
141+
noparse!(fail_range_end_no_class, "[a-[:lower:]]")
142+
noparse!(fail_range_end_no_begin, r"[a-\A]")
143+
noparse!(fail_range_end_no_end, r"[a-\z]")
144+
noparse!(fail_range_end_no_boundary, r"[a-\b]")
117145

118146
macro_rules! mat(
119147
($name:ident, $re:expr, $text:expr, $($loc:tt)+) => (

0 commit comments

Comments
 (0)