1
Fork 0

Some basic error correction in the parser after a dot

This commit is contained in:
Nick Cameron 2016-01-20 17:15:03 +13:00
parent c6ba7fee97
commit b1b6b33c6d

View file

@ -2355,18 +2355,9 @@ impl<'a> Parser<'a> {
) )
} }
fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>) -> PResult<'a, P<Expr>> { // Assuming we have just parsed `.foo` (i.e., a dot and an ident), continue
let mut e = e0; // parsing into an expression.
let lo = e.span.lo; fn parse_dot_suffix(&mut self, ident: Ident, ident_span: Span, self_value: P<Expr>) -> PResult<'a, P<Expr>> {
let mut hi;
loop {
// expr.f
if self.eat(&token::Dot) {
match self.token {
token::Ident(i, _) => {
let dot = self.last_span.hi;
hi = self.span.hi;
self.bump();
let (_, tys, bindings) = if self.eat(&token::ModSep) { let (_, tys, bindings) = if self.eat(&token::ModSep) {
try!(self.expect_lt()); try!(self.expect_lt());
try!(self.parse_generic_values_after_lt()) try!(self.parse_generic_values_after_lt())
@ -2379,8 +2370,10 @@ impl<'a> Parser<'a> {
self.span_err(last_span, "type bindings are only permitted on trait paths"); self.span_err(last_span, "type bindings are only permitted on trait paths");
} }
// expr.f() method call let lo = self_value.span.lo;
match self.token {
Ok(match self.token {
// expr.f() method call.
token::OpenDelim(token::Paren) => { token::OpenDelim(token::Paren) => {
let mut es = try!(self.parse_unspanned_seq( let mut es = try!(self.parse_unspanned_seq(
&token::OpenDelim(token::Paren), &token::OpenDelim(token::Paren),
@ -2388,13 +2381,14 @@ impl<'a> Parser<'a> {
seq_sep_trailing_allowed(token::Comma), seq_sep_trailing_allowed(token::Comma),
|p| Ok(try!(p.parse_expr())) |p| Ok(try!(p.parse_expr()))
)); ));
hi = self.last_span.hi; let hi = self.last_span.hi;
es.insert(0, e); es.insert(0, self_value);
let id = spanned(dot, hi, i); let id = spanned(ident_span.lo, ident_span.hi, ident);
let nd = self.mk_method_call(id, tys, es); let nd = self.mk_method_call(id, tys, es);
e = self.mk_expr(lo, hi, nd, None); self.mk_expr(lo, hi, nd, None)
} }
// Field access.
_ => { _ => {
if !tys.is_empty() { if !tys.is_empty() {
let last_span = self.last_span; let last_span = self.last_span;
@ -2403,11 +2397,27 @@ impl<'a> Parser<'a> {
have type parameters"); have type parameters");
} }
let id = spanned(dot, hi, i); let id = spanned(ident_span.lo, ident_span.hi, ident);
let field = self.mk_field(e, id); let field = self.mk_field(self_value, id);
e = self.mk_expr(lo, hi, field, None); self.mk_expr(lo, ident_span.hi, field, None)
} }
})
} }
fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>) -> PResult<'a, P<Expr>> {
let mut e = e0;
let lo = e.span.lo;
let mut hi;
loop {
// expr.f
if self.eat(&token::Dot) {
match self.token {
token::Ident(i, _) => {
let dot_pos = self.last_span.hi;
hi = self.span.hi;
self.bump();
e = try!(self.parse_dot_suffix(i, mk_sp(dot_pos, hi), e));
} }
token::Literal(token::Integer(n), suf) => { token::Literal(token::Integer(n), suf) => {
let sp = self.span; let sp = self.span;
@ -2452,7 +2462,17 @@ impl<'a> Parser<'a> {
self.abort_if_errors(); self.abort_if_errors();
} }
_ => return self.unexpected() _ => {
// TODO special case lifetime
// FIXME Could factor this out into non_fatal_unexpected or something.
let actual = self.this_token_to_string();
self.span_err(self.span, &format!("unexpected token: `{}`", actual));
let dot_pos = self.last_span.hi;
e = try!(self.parse_dot_suffix(special_idents::invalid,
mk_sp(dot_pos, dot_pos),
e));
}
} }
continue; continue;
} }