Skip to content

Commit b1b6b33

Browse files
committed
Some basic error correction in the parser after a dot
1 parent c6ba7fe commit b1b6b33

File tree

1 file changed

+62
-42
lines changed

1 file changed

+62
-42
lines changed

src/libsyntax/parse/parser.rs

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2355,6 +2355,55 @@ impl<'a> Parser<'a> {
23552355
)
23562356
}
23572357

2358+
// Assuming we have just parsed `.foo` (i.e., a dot and an ident), continue
2359+
// parsing into an expression.
2360+
fn parse_dot_suffix(&mut self, ident: Ident, ident_span: Span, self_value: P<Expr>) -> PResult<'a, P<Expr>> {
2361+
let (_, tys, bindings) = if self.eat(&token::ModSep) {
2362+
try!(self.expect_lt());
2363+
try!(self.parse_generic_values_after_lt())
2364+
} else {
2365+
(Vec::new(), Vec::new(), Vec::new())
2366+
};
2367+
2368+
if !bindings.is_empty() {
2369+
let last_span = self.last_span;
2370+
self.span_err(last_span, "type bindings are only permitted on trait paths");
2371+
}
2372+
2373+
let lo = self_value.span.lo;
2374+
2375+
Ok(match self.token {
2376+
// expr.f() method call.
2377+
token::OpenDelim(token::Paren) => {
2378+
let mut es = try!(self.parse_unspanned_seq(
2379+
&token::OpenDelim(token::Paren),
2380+
&token::CloseDelim(token::Paren),
2381+
seq_sep_trailing_allowed(token::Comma),
2382+
|p| Ok(try!(p.parse_expr()))
2383+
));
2384+
let hi = self.last_span.hi;
2385+
2386+
es.insert(0, self_value);
2387+
let id = spanned(ident_span.lo, ident_span.hi, ident);
2388+
let nd = self.mk_method_call(id, tys, es);
2389+
self.mk_expr(lo, hi, nd, None)
2390+
}
2391+
// Field access.
2392+
_ => {
2393+
if !tys.is_empty() {
2394+
let last_span = self.last_span;
2395+
self.span_err(last_span,
2396+
"field expressions may not \
2397+
have type parameters");
2398+
}
2399+
2400+
let id = spanned(ident_span.lo, ident_span.hi, ident);
2401+
let field = self.mk_field(self_value, id);
2402+
self.mk_expr(lo, ident_span.hi, field, None)
2403+
}
2404+
})
2405+
}
2406+
23582407
fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>) -> PResult<'a, P<Expr>> {
23592408
let mut e = e0;
23602409
let lo = e.span.lo;
@@ -2364,50 +2413,11 @@ impl<'a> Parser<'a> {
23642413
if self.eat(&token::Dot) {
23652414
match self.token {
23662415
token::Ident(i, _) => {
2367-
let dot = self.last_span.hi;
2416+
let dot_pos = self.last_span.hi;
23682417
hi = self.span.hi;
23692418
self.bump();
2370-
let (_, tys, bindings) = if self.eat(&token::ModSep) {
2371-
try!(self.expect_lt());
2372-
try!(self.parse_generic_values_after_lt())
2373-
} else {
2374-
(Vec::new(), Vec::new(), Vec::new())
2375-
};
2376-
2377-
if !bindings.is_empty() {
2378-
let last_span = self.last_span;
2379-
self.span_err(last_span, "type bindings are only permitted on trait paths");
2380-
}
23812419

2382-
// expr.f() method call
2383-
match self.token {
2384-
token::OpenDelim(token::Paren) => {
2385-
let mut es = try!(self.parse_unspanned_seq(
2386-
&token::OpenDelim(token::Paren),
2387-
&token::CloseDelim(token::Paren),
2388-
seq_sep_trailing_allowed(token::Comma),
2389-
|p| Ok(try!(p.parse_expr()))
2390-
));
2391-
hi = self.last_span.hi;
2392-
2393-
es.insert(0, e);
2394-
let id = spanned(dot, hi, i);
2395-
let nd = self.mk_method_call(id, tys, es);
2396-
e = self.mk_expr(lo, hi, nd, None);
2397-
}
2398-
_ => {
2399-
if !tys.is_empty() {
2400-
let last_span = self.last_span;
2401-
self.span_err(last_span,
2402-
"field expressions may not \
2403-
have type parameters");
2404-
}
2405-
2406-
let id = spanned(dot, hi, i);
2407-
let field = self.mk_field(e, id);
2408-
e = self.mk_expr(lo, hi, field, None);
2409-
}
2410-
}
2420+
e = try!(self.parse_dot_suffix(i, mk_sp(dot_pos, hi), e));
24112421
}
24122422
token::Literal(token::Integer(n), suf) => {
24132423
let sp = self.span;
@@ -2452,7 +2462,17 @@ impl<'a> Parser<'a> {
24522462
self.abort_if_errors();
24532463

24542464
}
2455-
_ => return self.unexpected()
2465+
_ => {
2466+
// TODO special case lifetime
2467+
// FIXME Could factor this out into non_fatal_unexpected or something.
2468+
let actual = self.this_token_to_string();
2469+
self.span_err(self.span, &format!("unexpected token: `{}`", actual));
2470+
2471+
let dot_pos = self.last_span.hi;
2472+
e = try!(self.parse_dot_suffix(special_idents::invalid,
2473+
mk_sp(dot_pos, dot_pos),
2474+
e));
2475+
}
24562476
}
24572477
continue;
24582478
}

0 commit comments

Comments
 (0)