Skip to content

Commit ffd2a0b

Browse files
committed
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.
1 parent 0ef9c5f commit ffd2a0b

File tree

6 files changed

+69
-49
lines changed

6 files changed

+69
-49
lines changed

src/libsyntax/parse/parser.rs

+63-28
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ impl<'a> Parser<'a> {
598598

599599
/// Check if the next token is `tok`, and return `true` if so.
600600
///
601-
/// This method is will automatically add `tok` to `expected_tokens` if `tok` is not
601+
/// This method will automatically add `tok` to `expected_tokens` if `tok` is not
602602
/// encountered.
603603
pub fn check(&mut self, tok: &token::Token) -> bool {
604604
let is_present = self.token == *tok;
@@ -840,6 +840,12 @@ impl<'a> Parser<'a> {
840840
return Ok((v, returned));
841841
}
842842

843+
/// Eat and discard tokens until one of `kets` is encountered. Respects token trees,
844+
/// passes through any errors encountered. Used for error recovery.
845+
pub fn eat_to_tokens(&mut self, kets: &[&token::Token]) {
846+
self.parse_seq_to_before_tokens(kets, seq_sep_none(), |p| p.parse_token_tree());
847+
}
848+
843849
/// Parse a sequence, including the closing delimiter. The function
844850
/// f must consume tokens until reaching the next separator or
845851
/// closing bracket.
@@ -861,13 +867,23 @@ impl<'a> Parser<'a> {
861867
pub fn parse_seq_to_before_end<T, F>(&mut self,
862868
ket: &token::Token,
863869
sep: SeqSep,
864-
mut f: F)
870+
f: F)
865871
-> Vec<T>
866872
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
873+
{
874+
self.parse_seq_to_before_tokens(&[ket], sep, f)
875+
}
876+
877+
pub fn parse_seq_to_before_tokens<T, F>(&mut self,
878+
kets: &[&token::Token],
879+
sep: SeqSep,
880+
mut f: F)
881+
-> Vec<T>
882+
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
867883
{
868884
let mut first: bool = true;
869885
let mut v = vec!();
870-
while self.token != *ket {
886+
while !kets.contains(&&self.token) {
871887
match sep.sep {
872888
Some(ref t) => {
873889
if first {
@@ -881,7 +897,9 @@ impl<'a> Parser<'a> {
881897
}
882898
_ => ()
883899
}
884-
if sep.trailing_sep_allowed && self.check(ket) { break; }
900+
if sep.trailing_sep_allowed && kets.iter().any(|k| self.check(k)) {
901+
break;
902+
}
885903

886904
match f(self) {
887905
Ok(t) => v.push(t),
@@ -1230,7 +1248,25 @@ impl<'a> Parser<'a> {
12301248
};
12311249
(ident, TraitItemKind::Const(ty, default))
12321250
} else {
1233-
let (constness, unsafety, abi) = try!(p.parse_fn_front_matter());
1251+
let (constness, unsafety, abi) = match p.parse_fn_front_matter() {
1252+
Ok(cua) => cua,
1253+
Err(e) => {
1254+
loop {
1255+
p.bump();
1256+
if p.token == token::Semi {
1257+
p.bump();
1258+
break;
1259+
}
1260+
1261+
if p.token == token::OpenDelim(token::DelimToken::Brace) {
1262+
try!(p.parse_token_tree());
1263+
break;
1264+
}
1265+
}
1266+
1267+
return Err(e);
1268+
}
1269+
};
12341270

12351271
let ident = try!(p.parse_ident());
12361272
let mut generics = try!(p.parse_generics());
@@ -4181,8 +4217,8 @@ impl<'a> Parser<'a> {
41814217
fn forbid_lifetime(&mut self) -> PResult<'a, ()> {
41824218
if self.token.is_lifetime() {
41834219
let span = self.span;
4184-
return Err(self.span_fatal(span, "lifetime parameters must be declared \
4185-
prior to type parameters"))
4220+
return Err(self.diagnostic().struct_span_err(span, "lifetime parameters must be \
4221+
declared prior to type parameters"))
41864222
}
41874223
Ok(())
41884224
}
@@ -4310,7 +4346,8 @@ impl<'a> Parser<'a> {
43104346
fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool)
43114347
-> PResult<'a, (Vec<Arg> , bool)> {
43124348
let sp = self.span;
4313-
let mut args: Vec<Option<Arg>> =
4349+
let mut variadic = false;
4350+
let args: Vec<Option<Arg>> =
43144351
try!(self.parse_unspanned_seq(
43154352
&token::OpenDelim(token::Paren),
43164353
&token::CloseDelim(token::Paren),
@@ -4321,37 +4358,35 @@ impl<'a> Parser<'a> {
43214358
if allow_variadic {
43224359
if p.token != token::CloseDelim(token::Paren) {
43234360
let span = p.span;
4324-
return Err(p.span_fatal(span,
4325-
"`...` must be last in argument list for variadic function"))
4361+
p.span_err(span,
4362+
"`...` must be last in argument list for variadic function");
43264363
}
43274364
} else {
43284365
let span = p.span;
4329-
return Err(p.span_fatal(span,
4330-
"only foreign functions are allowed to be variadic"))
4366+
p.span_err(span,
4367+
"only foreign functions are allowed to be variadic");
43314368
}
4369+
variadic = true;
43324370
Ok(None)
43334371
} else {
4334-
Ok(Some(try!(p.parse_arg_general(named_args))))
4372+
match p.parse_arg_general(named_args) {
4373+
Ok(arg) => Ok(Some(arg)),
4374+
Err(mut e) => {
4375+
e.emit();
4376+
p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
4377+
Ok(None)
4378+
}
4379+
}
43354380
}
43364381
}
43374382
));
43384383

4339-
let variadic = match args.pop() {
4340-
Some(None) => true,
4341-
Some(x) => {
4342-
// Need to put back that last arg
4343-
args.push(x);
4344-
false
4345-
}
4346-
None => false
4347-
};
4348-
43494384
if variadic && args.is_empty() {
43504385
self.span_err(sp,
43514386
"variadic function must be declared with at least one named argument");
43524387
}
43534388

4354-
let args = args.into_iter().map(|x| x.unwrap()).collect();
4389+
let args = args.into_iter().filter_map(|x| x).collect();
43554390

43564391
Ok((args, variadic))
43574392
}
@@ -4749,8 +4784,8 @@ impl<'a> Parser<'a> {
47494784
// eat a matched-delimiter token tree:
47504785
let delim = try!(self.expect_open_delim());
47514786
let tts = try!(self.parse_seq_to_end(&token::CloseDelim(delim),
4752-
seq_sep_none(),
4753-
|p| p.parse_token_tree()));
4787+
seq_sep_none(),
4788+
|p| p.parse_token_tree()));
47544789
let m_ = Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT };
47554790
let m: ast::Mac = codemap::Spanned { node: m_,
47564791
span: mk_sp(lo,
@@ -5809,8 +5844,8 @@ impl<'a> Parser<'a> {
58095844
// eat a matched-delimiter token tree:
58105845
let delim = try!(self.expect_open_delim());
58115846
let tts = try!(self.parse_seq_to_end(&token::CloseDelim(delim),
5812-
seq_sep_none(),
5813-
|p| p.parse_token_tree()));
5847+
seq_sep_none(),
5848+
|p| p.parse_token_tree()));
58145849
// single-variant-enum... :
58155850
let m = Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT };
58165851
let m: ast::Mac = codemap::Spanned { node: m,

src/test/parse-fail/issue-14303-path.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@
1212

1313
fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {}
1414
//~^ ERROR lifetime parameters must be declared prior to type parameters
15+
//~^^ ERROR unexpected token

src/test/parse-fail/issue-2354.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
fn foo() { //~ HELP did you mean to close this delimiter?
1414
match Some(x) {
15-
Some(y) { panic!(); }
16-
None { panic!(); }
15+
Some(y) => { panic!(); }
16+
None => { panic!(); }
1717
}
1818

1919
fn bar() {

src/test/parse-fail/pat-lt-bracket-6.rs

+1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@
1010

1111
fn main() {
1212
let Test(&desc[..]) = x; //~ error: expected one of `,` or `@`, found `[`
13+
//~^ ERROR expected one of `:`, `;`, or `=`, found `..`
1314
}

src/test/parse-fail/pat-lt-bracket-7.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@
99
// except according to those terms.
1010

1111
fn main() {
12-
for thing(x[]) {} //~ error: expected one of `,` or `@`, found `[`
12+
for thing(x[]) in foo {} //~ error: expected one of `,` or `@`, found `[`
13+
//~^ ERROR: expected `in`, found `]`
1314
}

src/test/parse-fail/variadic-ffi-1.rs

-18
This file was deleted.

0 commit comments

Comments
 (0)