let mut alts: Vec<Ast> = vec!();
if self.peek_is(1, ']') {
- try!(self.expect(']'))
+ 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 {
'[' =>
}
return Ok(())
}
+ _ => {}
}
if self.peek_is(1, '-') && !self.peek_is(2, ']') {
- try!(self.expect('-'))
- try!(self.noteof("not a ']'"))
- let c2 = self.cur();
+ 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 '{}-{}'",
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) => (
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)+) => (