syntax: put helpers of parse_self_param in the method.

This commit is contained in:
Mazdak Farrokhzad 2019-10-01 05:45:41 +02:00
parent df298b49f2
commit 30647d1a85

View File

@ -1268,27 +1268,71 @@ impl<'a> Parser<'a> {
/// ///
/// See `parse_self_param_with_attrs` to collect attributes. /// See `parse_self_param_with_attrs` to collect attributes.
fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> { fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
// Extract an identifier *after* having confirmed that the token is one.
let expect_self_ident = |this: &mut Self| {
match this.token.kind {
// Preserve hygienic context.
token::Ident(name, _) => {
let span = this.token.span;
this.bump();
Ident::new(name, span)
}
_ => unreachable!(),
}
};
// Is `self` `n` tokens ahead?
let is_isolated_self = |this: &Self, n| {
this.is_keyword_ahead(n, &[kw::SelfLower])
&& this.look_ahead(n + 1, |t| t != &token::ModSep)
};
// Is `mut self` `n` tokens ahead?
let is_isolated_mut_self = |this: &Self, n| {
this.is_keyword_ahead(n, &[kw::Mut])
&& is_isolated_self(this, n + 1)
};
// Parse `self` or `self: TYPE`. We already know the current token is `self`.
let parse_self_possibly_typed = |this: &mut Self, m| {
let eself_ident = expect_self_ident(this);
let eself_hi = this.prev_span;
let eself = if this.eat(&token::Colon) {
SelfKind::Explicit(this.parse_ty()?, m)
} else {
SelfKind::Value(m)
};
Ok((eself, eself_ident, eself_hi))
};
// Recover for the grammar `*self`, `*const self`, and `*mut self`.
let recover_self_ptr = |this: &mut Self| {
let msg = "cannot pass `self` by raw pointer";
let span = this.token.span;
this.struct_span_err(span, msg)
.span_label(span, msg)
.emit();
Ok((SelfKind::Value(Mutability::Immutable), expect_self_ident(this), this.prev_span))
};
// Parse optional `self` parameter of a method. // Parse optional `self` parameter of a method.
// Only a limited set of initial token sequences is considered `self` parameters; anything // Only a limited set of initial token sequences is considered `self` parameters; anything
// else is parsed as a normal function parameter list, so some lookahead is required. // else is parsed as a normal function parameter list, so some lookahead is required.
let eself_lo = self.token.span; let eself_lo = self.token.span;
let (eself, eself_ident, eself_hi) = match self.token.kind { let (eself, eself_ident, eself_hi) = match self.token.kind {
token::BinOp(token::And) => { token::BinOp(token::And) => {
let eself = if self.is_isolated_self(1) { let eself = if is_isolated_self(self, 1) {
// `&self` // `&self`
self.bump(); self.bump();
SelfKind::Region(None, Mutability::Immutable) SelfKind::Region(None, Mutability::Immutable)
} else if self.is_isolated_mut_self(1) { } else if is_isolated_mut_self(self, 1) {
// `&mut self` // `&mut self`
self.bump(); self.bump();
self.bump(); self.bump();
SelfKind::Region(None, Mutability::Mutable) SelfKind::Region(None, Mutability::Mutable)
} else if self.look_ahead(1, |t| t.is_lifetime()) && self.is_isolated_self(2) { } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_self(self, 2) {
// `&'lt self` // `&'lt self`
self.bump(); self.bump();
let lt = self.expect_lifetime(); let lt = self.expect_lifetime();
SelfKind::Region(Some(lt), Mutability::Immutable) SelfKind::Region(Some(lt), Mutability::Immutable)
} else if self.look_ahead(1, |t| t.is_lifetime()) && self.is_isolated_mut_self(2) { } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_mut_self(self, 2) {
// `&'lt mut self` // `&'lt mut self`
self.bump(); self.bump();
let lt = self.expect_lifetime(); let lt = self.expect_lifetime();
@ -1298,30 +1342,30 @@ impl<'a> Parser<'a> {
// `&not_self` // `&not_self`
return Ok(None); return Ok(None);
}; };
(eself, self.expect_self_ident(), self.prev_span) (eself, expect_self_ident(self), self.prev_span)
} }
// `*self` // `*self`
token::BinOp(token::Star) if self.is_isolated_self(1) => { token::BinOp(token::Star) if is_isolated_self(self, 1) => {
self.bump(); self.bump();
self.recover_self_ptr()? recover_self_ptr(self)?
} }
// `*mut self` and `*const self` // `*mut self` and `*const self`
token::BinOp(token::Star) if token::BinOp(token::Star) if
self.look_ahead(1, |t| t.is_mutability()) self.look_ahead(1, |t| t.is_mutability())
&& self.is_isolated_self(2) => && is_isolated_self(self, 2) =>
{ {
self.bump(); self.bump();
self.bump(); self.bump();
self.recover_self_ptr()? recover_self_ptr(self)?
} }
// `self` and `self: TYPE` // `self` and `self: TYPE`
token::Ident(..) if self.is_isolated_self(0) => { token::Ident(..) if is_isolated_self(self, 0) => {
self.parse_self_possibly_typed(Mutability::Immutable)? parse_self_possibly_typed(self, Mutability::Immutable)?
} }
// `mut self` and `mut self: TYPE` // `mut self` and `mut self: TYPE`
token::Ident(..) if self.is_isolated_mut_self(0) => { token::Ident(..) if is_isolated_mut_self(self, 0) => {
self.bump(); self.bump();
self.parse_self_possibly_typed(Mutability::Mutable)? parse_self_possibly_typed(self, Mutability::Mutable)?
} }
_ => return Ok(None), _ => return Ok(None),
}; };
@ -1345,51 +1389,6 @@ impl<'a> Parser<'a> {
self.look_ahead(offset + 1, |t| t == &token::Colon) self.look_ahead(offset + 1, |t| t == &token::Colon)
} }
fn is_isolated_self(&self, n: usize) -> bool {
self.is_keyword_ahead(n, &[kw::SelfLower])
&& self.look_ahead(n + 1, |t| t != &token::ModSep)
}
fn is_isolated_mut_self(&self, n: usize) -> bool {
self.is_keyword_ahead(n, &[kw::Mut])
&& self.is_isolated_self(n + 1)
}
fn expect_self_ident(&mut self) -> Ident {
match self.token.kind {
// Preserve hygienic context.
token::Ident(name, _) => {
let span = self.token.span;
self.bump();
Ident::new(name, span)
}
_ => unreachable!(),
}
}
/// Recover for the grammar `*self`, `*const self`, and `*mut self`.
fn recover_self_ptr(&mut self) -> PResult<'a, (ast::SelfKind, Ident, Span)> {
let msg = "cannot pass `self` by raw pointer";
let span = self.token.span;
self.struct_span_err(span, msg)
.span_label(span, msg)
.emit();
Ok((SelfKind::Value(Mutability::Immutable), self.expect_self_ident(), self.prev_span))
}
/// Parse `self` or `self: TYPE`. We already know the current token is `self`.
fn parse_self_possibly_typed(&mut self, m: Mutability) -> PResult<'a, (SelfKind, Ident, Span)> {
let eself_ident = self.expect_self_ident();
let eself_hi = self.prev_span;
let eself = if self.eat(&token::Colon) {
SelfKind::Explicit(self.parse_ty()?, m)
} else {
SelfKind::Value(m)
};
Ok((eself, eself_ident, eself_hi))
}
fn is_crate_vis(&self) -> bool { fn is_crate_vis(&self) -> bool {
self.token.is_keyword(kw::Crate) && self.look_ahead(1, |t| t != &token::ModSep) self.token.is_keyword(kw::Crate) && self.look_ahead(1, |t| t != &token::ModSep)
} }