Try to improve format! error messages

Instead of just saying "unterminated format string" and friends, instead print
information about what was expected and what was found.

Closes #9931
This commit is contained in:
Alex Crichton 2013-10-18 10:30:40 -07:00
parent a1848bc755
commit a447c3ca16
2 changed files with 32 additions and 29 deletions

View File

@ -170,9 +170,7 @@ impl<'self> Iterator<Piece<'self>> for Parser<'self> {
Some((_, '{')) => {
self.cur.next();
let ret = Some(Argument(self.argument()));
if !self.consume('}') {
self.err(~"unterminated format string");
}
self.must_consume('}');
ret
}
Some((pos, '\\')) => {
@ -223,6 +221,25 @@ impl<'self> Parser<'self> {
}
}
/// Forces consumption of the specified character. If the character is not
/// found, an error is emitted.
fn must_consume(&mut self, c: char) {
self.ws();
match self.cur.clone().next() {
Some((_, maybe)) if c == maybe => {
self.cur.next();
}
Some((_, other)) => {
parse_error::cond.raise(
format!("expected `{}` but found `{}`", c, other));
}
None => {
parse_error::cond.raise(
format!("expected `{}` but string was terminated", c));
}
}
}
/// Attempts to consume any amount of whitespace followed by a character
fn wsconsume(&mut self, c: char) -> bool {
self.ws(); self.consume(c)
@ -386,15 +403,11 @@ impl<'self> Parser<'self> {
self.ws();
match self.word() {
"select" => {
if !self.wsconsume(',') {
self.err(~"`select` must be followed by `,`");
}
self.must_consume(',');
Some(self.select())
}
"plural" => {
if !self.wsconsume(',') {
self.err(~"`plural` must be followed by `,`");
}
self.must_consume(',');
Some(self.plural())
}
"" => {
@ -420,15 +433,11 @@ impl<'self> Parser<'self> {
self.err(~"cannot have an empty selector");
break
}
if !self.wsconsume('{') {
self.err(~"selector must be followed by `{`");
}
self.must_consume('{');
self.depth += 1;
let pieces = self.collect();
self.depth -= 1;
if !self.wsconsume('}') {
self.err(~"selector case must be terminated by `}`");
}
self.must_consume('}');
if selector == "other" {
if !other.is_none() {
self.err(~"multiple `other` statements in `select");
@ -475,9 +484,7 @@ impl<'self> Parser<'self> {
self.err(format!("expected `offset`, found `{}`",
word));
} else {
if !self.consume(':') {
self.err(~"`offset` must be followed by `:`");
}
self.must_consume(':');
match self.integer() {
Some(i) => { offset = Some(i); }
None => {
@ -524,15 +531,11 @@ impl<'self> Parser<'self> {
}
}
};
if !self.wsconsume('{') {
self.err(~"selector must be followed by `{`");
}
self.must_consume('{');
self.depth += 1;
let pieces = self.collect();
self.depth -= 1;
if !self.wsconsume('}') {
self.err(~"selector case must be terminated by `}`");
}
self.must_consume('}');
if isother {
if !other.is_none() {
self.err(~"multiple `other` statements in `select");

View File

@ -36,20 +36,20 @@ fn main() {
// bad syntax of the format string
format!("{"); //~ ERROR: unterminated format string
format!("{"); //~ ERROR: expected `}` but string was terminated
format!("\\ "); //~ ERROR: invalid escape
format!("\\"); //~ ERROR: expected an escape
format!("{0, }", 1); //~ ERROR: expected method
format!("{0, foo}", 1); //~ ERROR: unknown method
format!("{0, select}", "a"); //~ ERROR: must be followed by
format!("{0, plural}", 1); //~ ERROR: must be followed by
format!("{0, select}", "a"); //~ ERROR: expected `,` but found `}`
format!("{0, plural}", 1); //~ ERROR: expected `,` but found `}`
format!("{0, select, a{{}", 1); //~ ERROR: must be terminated
format!("{0, select, a{{}", 1); //~ ERROR: expected `}` but string was terminated
format!("{0, select, {} other{}}", "a"); //~ ERROR: empty selector
format!("{0, select, other{} other{}}", "a"); //~ ERROR: multiple `other`
format!("{0, plural, offset: other{}}", "a"); //~ ERROR: must be an integer
format!("{0, plural, offset 1 other{}}", "a"); //~ ERROR: be followed by `:`
format!("{0, plural, offset 1 other{}}", "a"); //~ ERROR: expected `:` but found `1`
format!("{0, plural, =a{} other{}}", "a"); //~ ERROR: followed by an integer
format!("{0, plural, a{} other{}}", "a"); //~ ERROR: unexpected plural
format!("{0, select, a{}}", "a"); //~ ERROR: must provide an `other`