impl fmt::Show for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "Regex syntax error near position {}: {}",
+ write!(f, "Regex syntax error near position {}: {:?}",
self.pos, self.msg)
}
}
///
/// Note that this representation prevents one from reproducing the regex as
/// it was typed. (But it could be used to reproduce an equivalent regex.)
-#[deriving(Show, Clone)]
+#[derive(Show, Clone)]
pub enum Ast {
Nothing,
Literal(char, Flags),
Rep(Box<Ast>, Repeater, Greed),
}
-#[deriving(Show, PartialEq, Clone)]
+#[derive(Show, PartialEq, Clone)]
pub enum Repeater {
ZeroOne,
ZeroMore,
OneMore,
}
-#[deriving(Copy, Show, Clone)]
+#[derive(Copy, Show, Clone)]
pub enum Greed {
Greedy,
Ungreedy,
/// constructing an abstract syntax tree. Its central purpose is to facilitate
/// parsing groups and alternations while also maintaining a stack of flag
/// state.
-#[deriving(Show)]
+#[derive(Show)]
enum BuildAst {
Expr(Ast),
Paren(Flags, uint, String), // '('
fn flags(&self) -> Flags {
match *self {
Paren(flags, _, _) => flags,
- _ => panic!("Cannot get flags from {}", self),
+ _ => panic!("Cannot get flags from {:?}", self),
}
}
match *self {
Paren(_, 0, _) => None,
Paren(_, c, _) => Some(c),
- _ => panic!("Cannot get capture group from {}", self),
+ _ => panic!("Cannot get capture group from {:?}", self),
}
}
Some(name.clone())
}
}
- _ => panic!("Cannot get capture name from {}", self),
+ _ => panic!("Cannot get capture name from {:?}", self),
}
}
fn unwrap(self) -> Result<Ast, Error> {
match self {
Expr(x) => Ok(x),
- _ => panic!("Tried to unwrap non-AST item: {}", self),
+ _ => panic!("Tried to unwrap non-AST item: {:?}", self),
}
}
}
match self.next_char() {
true => Ok(()),
false => {
- self.err(format!("Expected {} but got EOF.",
- expected)[])
+ self.err(&format!("Expected {:?} but got EOF.",
+ expected)[])
}
}
}
fn expect(&mut self, expected: char) -> Result<(), Error> {
match self.next_char() {
true if self.cur() == expected => Ok(()),
- true => self.err(format!("Expected '{}' but got '{}'.",
- expected, self.cur())[]),
+ true => self.err(&format!("Expected '{:?}' but got '{:?}'.",
+ expected, self.cur())[]),
false => {
- self.err(format!("Expected '{}' but got EOF.",
- expected)[])
+ self.err(&format!("Expected '{:?}' but got EOF.",
+ expected)[])
}
}
}
continue
}
Some(ast) =>
- panic!("Expected Class AST but got '{}'", ast),
+ panic!("Expected Class AST but got '{:?}'", ast),
// Just drop down and try to add as a regular character.
None => {},
},
return self.err(
"\\A, \\z, \\b and \\B are not valid escape \
sequences inside a character class."),
- ast => panic!("Unexpected AST item '{}'", ast),
+ ast => panic!("Unexpected AST item '{:?}'", ast),
}
}
']' if ranges.len() > 0 || alts.len() > 0 => {
match try!(self.parse_escape()) {
Literal(c3, _) => c2 = c3, // allow literal escapes below
ast =>
- return self.err(format!("Expected a literal, but got {}.",
- ast)[]),
+ return self.err(&format!("Expected a literal, but got {:?}.",
+ ast)[]),
}
}
if c2 < c {
- return self.err(format!("Invalid character class \
- range '{}-{}'",
- c,
- c2)[])
+ return self.err(&format!("Invalid character class \
+ range '{}-{}'",
+ c,
+ c2)[])
}
ranges.push((c, self.cur()))
} else {
FLAG_EMPTY
};
let name = self.slice(name_start, closer - 1);
- match find_class(ASCII_CLASSES, name[]) {
+ match find_class(ASCII_CLASSES, &name[]) {
None => None,
Some(ranges) => {
self.chari = closer;
match self.pos('}') {
Some(i) => i,
None => {
- return self.err(format!("No closing brace for counted \
- repetition starting at position \
- {}.",
- start)[])
+ return self.err(&format!("No closing brace for counted \
+ repetition starting at position \
+ {:?}.",
+ start)[])
}
};
self.chari = closer;
// Parse the min and max values from the regex.
let (mut min, mut max): (uint, Option<uint>);
if !inner.contains(",") {
- min = try!(self.parse_uint(inner[]));
+ min = try!(self.parse_uint(&inner[]));
max = Some(min);
} else {
let pieces: Vec<&str> = inner.splitn(1, ',').collect();
// Do some bounds checking and make sure max >= min.
if min > MAX_REPEAT {
- return self.err(format!(
+ return self.err(&format!(
"{} exceeds maximum allowed repetitions ({})",
min, MAX_REPEAT)[]);
}
if max.is_some() {
let m = max.unwrap();
if m > MAX_REPEAT {
- return self.err(format!(
+ return self.err(&format!(
"{} exceeds maximum allowed repetitions ({})",
m, MAX_REPEAT)[]);
}
if m < min {
- return self.err(format!(
+ return self.err(&format!(
"Max repetitions ({}) cannot be smaller than min \
repetitions ({}).", m, min)[]);
}
Ok(AstClass(ranges, flags))
}
_ => {
- self.err(format!("Invalid escape sequence '\\\\{}'", c)[])
+ self.err(&format!("Invalid escape sequence '\\\\{}'", c)[])
}
}
}
let closer =
match self.pos('}') {
Some(i) => i,
- None => return self.err(format!(
+ None => return self.err(&format!(
"Missing '}}' for unclosed '{{' at position {}",
self.chari)[]),
};
name = self.slice(self.chari + 1, self.chari + 2);
self.chari += 1;
}
- match find_class(UNICODE_CLASSES, name[]) {
+ match find_class(UNICODE_CLASSES, &name[]) {
None => {
- return self.err(format!("Could not find Unicode class '{}'",
+ return self.err(&format!("Could not find Unicode class '{}'",
name)[])
}
Some(ranges) => {
}
}
let s = self.slice(start, end);
- match num::from_str_radix::<u32>(s[], 8) {
+ match num::from_str_radix::<u32>(&s[], 8) {
Some(n) => Ok(Literal(try!(self.char_from_u32(n)), FLAG_EMPTY)),
None => {
- self.err(format!("Could not parse '{}' as octal number.",
+ self.err(&format!("Could not parse '{:?}' as octal number.",
s)[])
}
}
let closer =
match self.pos('}') {
None => {
- return self.err(format!("Missing '}}' for unclosed \
+ return self.err(&format!("Missing '}}' for unclosed \
'{{' at position {}",
start)[])
}
Some(i) => i,
};
self.chari = closer;
- self.parse_hex_digits(self.slice(start, closer)[])
+ self.parse_hex_digits(&self.slice(start, closer)[])
}
// Parses a two-digit hex number.
match num::from_str_radix::<u32>(s, 16) {
Some(n) => Ok(Literal(try!(self.char_from_u32(n)), FLAG_EMPTY)),
None => {
- self.err(format!("Could not parse '{}' as hex number.", s)[])
+ self.err(&format!("Could not parse '{}' as hex number.", s)[])
}
}
}
"Capture names can only have underscores, letters and digits.")
}
if self.names.contains(&name) {
- return self.err(format!("Duplicate capture group name '{}'.",
+ return self.err(&format!("Duplicate capture group name '{}'.",
name)[])
}
self.names.push(name.clone());
'U' => { flags = flags | FLAG_SWAP_GREED; saw_flag = true},
'-' => {
if sign < 0 {
- return self.err(format!(
+ return self.err(&format!(
"Cannot negate flags twice in '{}'.",
self.slice(start, self.chari + 1))[])
}
':' | ')' => {
if sign < 0 {
if !saw_flag {
- return self.err(format!(
+ return self.err(&format!(
"A valid flag does not follow negation in '{}'",
self.slice(start, self.chari + 1))[])
}
self.flags = flags;
return Ok(())
}
- _ => return self.err(format!(
+ _ => return self.err(&format!(
"Unrecognized flag '{}'.", self.cur())[]),
}
}
match s.parse::<uint>() {
Some(i) => Ok(i),
None => {
- self.err(format!("Expected an unsigned integer but got '{}'.",
+ self.err(&format!("Expected an unsigned integer but got '{}'.",
s)[])
}
}
match char::from_u32(n) {
Some(c) => Ok(c),
None => {
- self.err(format!("Could not decode '{}' to unicode \
+ self.err(&format!("Could not decode '{}' to unicode \
character.", n)[])
}
}