diff options
| author | Nick Cameron <ncameron@mozilla.com> | 2016-02-01 08:39:50 +1300 |
|---|---|---|
| committer | Nick Cameron <ncameron@mozilla.com> | 2016-02-15 09:30:23 +1300 |
| commit | ffd2a0b9d78191b8a3d97f687077852d15c9b7aa (patch) | |
| tree | e42abe4c33ac32d668304dff9a024d2d0ad8aa5c | |
| parent | 0ef9c5f5853ce35db142e4e2793984148df3d5f8 (diff) | |
| download | rust-ffd2a0b9d78191b8a3d97f687077852d15c9b7aa.tar.gz rust-ffd2a0b9d78191b8a3d97f687077852d15c9b7aa.zip | |
Add some simple error recovery to the parser and fix tests
Some tests just add the extra errors, others I fix by doing some simple error recovery. I've tried to avoid doing too much in the hope of doing something more principled later. In general error messages are getting worse at this stage, but I think in the long run they will get better.
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 91 | ||||
| -rw-r--r-- | src/test/parse-fail/issue-14303-path.rs | 1 | ||||
| -rw-r--r-- | src/test/parse-fail/issue-2354.rs | 4 | ||||
| -rw-r--r-- | src/test/parse-fail/pat-lt-bracket-6.rs | 1 | ||||
| -rw-r--r-- | src/test/parse-fail/pat-lt-bracket-7.rs | 3 | ||||
| -rw-r--r-- | src/test/parse-fail/variadic-ffi-1.rs | 18 |
6 files changed, 69 insertions, 49 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 5972f8f4b71..14c663b698c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -598,7 +598,7 @@ impl<'a> Parser<'a> { /// Check if the next token is `tok`, and return `true` if so. /// - /// This method is will automatically add `tok` to `expected_tokens` if `tok` is not + /// This method will automatically add `tok` to `expected_tokens` if `tok` is not /// encountered. pub fn check(&mut self, tok: &token::Token) -> bool { let is_present = self.token == *tok; @@ -840,6 +840,12 @@ impl<'a> Parser<'a> { return Ok((v, returned)); } + /// Eat and discard tokens until one of `kets` is encountered. Respects token trees, + /// passes through any errors encountered. Used for error recovery. + pub fn eat_to_tokens(&mut self, kets: &[&token::Token]) { + self.parse_seq_to_before_tokens(kets, seq_sep_none(), |p| p.parse_token_tree()); + } + /// Parse a sequence, including the closing delimiter. The function /// f must consume tokens until reaching the next separator or /// closing bracket. @@ -861,13 +867,23 @@ impl<'a> Parser<'a> { pub fn parse_seq_to_before_end<T, F>(&mut self, ket: &token::Token, sep: SeqSep, - mut f: F) + f: F) -> Vec<T> where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, { + self.parse_seq_to_before_tokens(&[ket], sep, f) + } + + pub fn parse_seq_to_before_tokens<T, F>(&mut self, + kets: &[&token::Token], + sep: SeqSep, + mut f: F) + -> Vec<T> + where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, + { let mut first: bool = true; let mut v = vec!(); - while self.token != *ket { + while !kets.contains(&&self.token) { match sep.sep { Some(ref t) => { if first { @@ -881,7 +897,9 @@ impl<'a> Parser<'a> { } _ => () } - if sep.trailing_sep_allowed && self.check(ket) { break; } + if sep.trailing_sep_allowed && kets.iter().any(|k| self.check(k)) { + break; + } match f(self) { Ok(t) => v.push(t), @@ -1230,7 +1248,25 @@ impl<'a> Parser<'a> { }; (ident, TraitItemKind::Const(ty, default)) } else { - let (constness, unsafety, abi) = try!(p.parse_fn_front_matter()); + let (constness, unsafety, abi) = match p.parse_fn_front_matter() { + Ok(cua) => cua, + Err(e) => { + loop { + p.bump(); + if p.token == token::Semi { + p.bump(); + break; + } + + if p.token == token::OpenDelim(token::DelimToken::Brace) { + try!(p.parse_token_tree()); + break; + } + } + + return Err(e); + } + }; let ident = try!(p.parse_ident()); let mut generics = try!(p.parse_generics()); @@ -4181,8 +4217,8 @@ impl<'a> Parser<'a> { fn forbid_lifetime(&mut self) -> PResult<'a, ()> { if self.token.is_lifetime() { let span = self.span; - return Err(self.span_fatal(span, "lifetime parameters must be declared \ - prior to type parameters")) + return Err(self.diagnostic().struct_span_err(span, "lifetime parameters must be \ + declared prior to type parameters")) } Ok(()) } @@ -4310,7 +4346,8 @@ impl<'a> Parser<'a> { fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool) -> PResult<'a, (Vec<Arg> , bool)> { let sp = self.span; - let mut args: Vec<Option<Arg>> = + let mut variadic = false; + let args: Vec<Option<Arg>> = try!(self.parse_unspanned_seq( &token::OpenDelim(token::Paren), &token::CloseDelim(token::Paren), @@ -4321,37 +4358,35 @@ impl<'a> Parser<'a> { if allow_variadic { if p.token != token::CloseDelim(token::Paren) { let span = p.span; - return Err(p.span_fatal(span, - "`...` must be last in argument list for variadic function")) + p.span_err(span, + "`...` must be last in argument list for variadic function"); } } else { let span = p.span; - return Err(p.span_fatal(span, - "only foreign functions are allowed to be variadic")) + p.span_err(span, + "only foreign functions are allowed to be variadic"); } + variadic = true; Ok(None) } else { - Ok(Some(try!(p.parse_arg_general(named_args)))) + match p.parse_arg_general(named_args) { + Ok(arg) => Ok(Some(arg)), + Err(mut e) => { + e.emit(); + p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]); + Ok(None) + } + } } } )); - let variadic = match args.pop() { - Some(None) => true, - Some(x) => { - // Need to put back that last arg - args.push(x); - false - } - None => false - }; - if variadic && args.is_empty() { self.span_err(sp, "variadic function must be declared with at least one named argument"); } - let args = args.into_iter().map(|x| x.unwrap()).collect(); + let args = args.into_iter().filter_map(|x| x).collect(); Ok((args, variadic)) } @@ -4749,8 +4784,8 @@ impl<'a> Parser<'a> { // eat a matched-delimiter token tree: let delim = try!(self.expect_open_delim()); let tts = try!(self.parse_seq_to_end(&token::CloseDelim(delim), - seq_sep_none(), - |p| p.parse_token_tree())); + seq_sep_none(), + |p| p.parse_token_tree())); let m_ = Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT }; let m: ast::Mac = codemap::Spanned { node: m_, span: mk_sp(lo, @@ -5809,8 +5844,8 @@ impl<'a> Parser<'a> { // eat a matched-delimiter token tree: let delim = try!(self.expect_open_delim()); let tts = try!(self.parse_seq_to_end(&token::CloseDelim(delim), - seq_sep_none(), - |p| p.parse_token_tree())); + seq_sep_none(), + |p| p.parse_token_tree())); // single-variant-enum... : let m = Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT }; let m: ast::Mac = codemap::Spanned { node: m, diff --git a/src/test/parse-fail/issue-14303-path.rs b/src/test/parse-fail/issue-14303-path.rs index f0d1feffec8..7c30b5f2629 100644 --- a/src/test/parse-fail/issue-14303-path.rs +++ b/src/test/parse-fail/issue-14303-path.rs @@ -12,3 +12,4 @@ fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {} //~^ ERROR lifetime parameters must be declared prior to type parameters +//~^^ ERROR unexpected token diff --git a/src/test/parse-fail/issue-2354.rs b/src/test/parse-fail/issue-2354.rs index 0b380d6ae88..2e799a72c81 100644 --- a/src/test/parse-fail/issue-2354.rs +++ b/src/test/parse-fail/issue-2354.rs @@ -12,8 +12,8 @@ fn foo() { //~ HELP did you mean to close this delimiter? match Some(x) { - Some(y) { panic!(); } - None { panic!(); } + Some(y) => { panic!(); } + None => { panic!(); } } fn bar() { diff --git a/src/test/parse-fail/pat-lt-bracket-6.rs b/src/test/parse-fail/pat-lt-bracket-6.rs index 72fdae82260..bc27aedb627 100644 --- a/src/test/parse-fail/pat-lt-bracket-6.rs +++ b/src/test/parse-fail/pat-lt-bracket-6.rs @@ -10,4 +10,5 @@ fn main() { let Test(&desc[..]) = x; //~ error: expected one of `,` or `@`, found `[` + //~^ ERROR expected one of `:`, `;`, or `=`, found `..` } diff --git a/src/test/parse-fail/pat-lt-bracket-7.rs b/src/test/parse-fail/pat-lt-bracket-7.rs index c7731d156ad..3e9478da44d 100644 --- a/src/test/parse-fail/pat-lt-bracket-7.rs +++ b/src/test/parse-fail/pat-lt-bracket-7.rs @@ -9,5 +9,6 @@ // except according to those terms. fn main() { - for thing(x[]) {} //~ error: expected one of `,` or `@`, found `[` + for thing(x[]) in foo {} //~ error: expected one of `,` or `@`, found `[` + //~^ ERROR: expected `in`, found `]` } diff --git a/src/test/parse-fail/variadic-ffi-1.rs b/src/test/parse-fail/variadic-ffi-1.rs deleted file mode 100644 index 63a36e98439..00000000000 --- a/src/test/parse-fail/variadic-ffi-1.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z parse-only - -extern { - fn printf(...); //~ ERROR: variadic function must be declared with at least one named argument - fn printf(..., foo: isize); //~ ERROR: `...` must be last in argument list for variadic function -} - -fn main() {} |
