implement edition-specific :pat behavior for 2015/18

This commit is contained in:
mark
2020-11-10 18:00:53 -06:00
parent e461b8137f
commit 1a7d00a529
14 changed files with 193 additions and 75 deletions

View File

@@ -4,6 +4,7 @@ use rustc_ast_pretty::pprust;
use rustc_errors::PResult;
use rustc_span::symbol::{kw, Ident};
use crate::parser::pat::{GateOr, OrPatNonterminalMode, RecoverComma};
use crate::parser::{FollowedByType, Parser, PathStyle};
impl<'a> Parser<'a> {
@@ -11,7 +12,11 @@ impl<'a> Parser<'a> {
///
/// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that
/// token. Be conservative (return true) if not sure.
pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool {
pub fn nonterminal_may_begin_with(
kind: NonterminalKind,
token: &Token,
or_pat_mode: OrPatNonterminalMode,
) -> bool {
/// Checks whether the non-terminal may contain a single (non-keyword) identifier.
fn may_be_ident(nt: &token::Nonterminal) -> bool {
match *nt {
@@ -70,6 +75,8 @@ impl<'a> Parser<'a> {
token::ModSep | // path
token::Lt | // path (UFCS constant)
token::BinOp(token::Shl) => true, // path (double UFCS)
// leading vert `|` or-pattern
token::BinOp(token::Or) => matches!(or_pat_mode, OrPatNonterminalMode::TopPat),
token::Interpolated(ref nt) => may_be_ident(nt),
_ => false,
},
@@ -86,7 +93,12 @@ impl<'a> Parser<'a> {
}
}
pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonterminal> {
/// Parse a non-terminal (e.g. MBE `:pat` or `:ident`).
pub fn parse_nonterminal(
&mut self,
kind: NonterminalKind,
or_pat_mode: OrPatNonterminalMode,
) -> PResult<'a, Nonterminal> {
// Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`)
// needs to have them force-captured here.
// A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
@@ -130,7 +142,12 @@ impl<'a> Parser<'a> {
}
}
NonterminalKind::Pat => {
let (mut pat, tokens) = self.collect_tokens(|this| this.parse_pat(None))?;
let (mut pat, tokens) = self.collect_tokens(|this| match or_pat_mode {
OrPatNonterminalMode::TopPat => {
this.parse_top_pat(GateOr::Yes, RecoverComma::No)
}
OrPatNonterminalMode::NoTopAlt => this.parse_pat(None),
})?;
// We have have eaten an NtPat, which could already have tokens
if pat.tokens.is_none() {
pat.tokens = tokens;