Skip to content

Commit

Permalink
auto merge of #18282 : pczarn/rust/regex-parse, r=burntsushi
Browse files Browse the repository at this point in the history
Fixes #18034

3 bugs fixed.
  • Loading branch information
bors committed Oct 29, 2014
2 parents dd71136 + f219773 commit 4769bca
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 24 deletions.
51 changes: 27 additions & 24 deletions src/libregex/parse.rs
Expand Up @@ -374,16 +374,12 @@ impl<'a> Parser<'a> {
let mut ranges: Vec<(char, char)> = vec!();
let mut alts: Vec<Ast> = vec!();

if self.peek_is(1, ']') {
try!(self.expect(']'))
ranges.push((']', ']'))
}
while self.peek_is(1, '-') {
try!(self.expect('-'))
try!(self.expect('-'));
ranges.push(('-', '-'))
}
loop {
try!(self.noteof("a closing ']' or a non-empty character class)"))
try!(self.noteof("a closing ']' or a non-empty character class)"));
let mut c = self.cur();
match c {
'[' =>
Expand Down Expand Up @@ -411,10 +407,7 @@ impl<'a> Parser<'a> {
ast => fail!("Unexpected AST item '{}'", ast),
}
}
_ => {},
}
match c {
']' => {
']' if ranges.len() > 0 || alts.len() > 0 => {
if ranges.len() > 0 {
let flags = negated | (self.flags & FLAG_NOCASE);
let mut ast = AstClass(combine_ranges(ranges), flags);
Expand All @@ -431,22 +424,32 @@ impl<'a> Parser<'a> {
}
return Ok(())
}
c => {
if self.peek_is(1, '-') && !self.peek_is(2, ']') {
try!(self.expect('-'))
try!(self.noteof("not a ']'"))
let c2 = self.cur();
if c2 < c {
return self.err(format!("Invalid character class \
range '{}-{}'",
c,
c2).as_slice())
}
ranges.push((c, self.cur()))
} else {
ranges.push((c, c))
_ => {}
}

if self.peek_is(1, '-') && !self.peek_is(2, ']') {
try!(self.expect('-'));
// The regex can't end here.
try!(self.noteof("not a ']'"));
// End the range with a single character or character escape.
let mut c2 = self.cur();
if c2 == '\\' {
match try!(self.parse_escape()) {
Literal(c3, _) => c2 = c3, // allow literal escapes below
ast =>
return self.err(format!("Expected a literal, but got {}.",
ast).as_slice()),
}
}
if c2 < c {
return self.err(format!("Invalid character class \
range '{}-{}'",
c,
c2).as_slice())
}
ranges.push((c, self.cur()))
} else {
ranges.push((c, c))
}
}
}
Expand Down
28 changes: 28 additions & 0 deletions src/libregex/test/tests.rs
Expand Up @@ -43,6 +43,30 @@ fn empty_regex_nonempty_match() {
assert_eq!(ms, vec![(0, 0), (1, 1), (2, 2), (3, 3)]);
}

#[test]
fn quoted_bracket_set() {
let re = regex!(r"([\x{5b}\x{5d}])");
let ms = re.find_iter("[]").collect::<Vec<(uint, uint)>>();
assert_eq!(ms, vec![(0, 1), (1, 2)]);
let re = regex!(r"([\[\]])");
let ms = re.find_iter("[]").collect::<Vec<(uint, uint)>>();
assert_eq!(ms, vec![(0, 1), (1, 2)]);
}

#[test]
fn first_range_starts_with_left_bracket() {
let re = regex!(r"([[-z])");
let ms = re.find_iter("[]").collect::<Vec<(uint, uint)>>();
assert_eq!(ms, vec![(0, 1), (1, 2)]);
}

#[test]
fn range_ends_with_escape() {
let re = regex!(r"([\[-\x{5d}])");
let ms = re.find_iter("[]").collect::<Vec<(uint, uint)>>();
assert_eq!(ms, vec![(0, 1), (1, 2)]);
}

macro_rules! replace(
($name:ident, $which:ident, $re:expr,
$search:expr, $replace:expr, $result:expr) => (
Expand Down Expand Up @@ -114,6 +138,10 @@ noparse!(fail_double_neg, "(?-i-i)")
noparse!(fail_neg_empty, "(?i-)")
noparse!(fail_empty_group, "()")
noparse!(fail_dupe_named, "(?P<a>.)(?P<a>.)")
noparse!(fail_range_end_no_class, "[a-[:lower:]]")
noparse!(fail_range_end_no_begin, r"[a-\A]")
noparse!(fail_range_end_no_end, r"[a-\z]")
noparse!(fail_range_end_no_boundary, r"[a-\b]")

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

0 comments on commit 4769bca

Please sign in to comment.