Streamline NamedMatch
.
This commit combines `MatchedTokenTree` and `MatchedNonterminal`, which are often considered together, into a single `MatchedSingle`. It shares a representation with the newly-parameterized `ParseNtResult`. This will also make things much simpler if/when variants from `Interpolated` start being moved to `ParseNtResult`.
This commit is contained in:
parent
b7f3b714da
commit
a94bb2a013
5 changed files with 42 additions and 31 deletions
|
@ -392,12 +392,7 @@ pub(super) fn count_metavar_decls(matcher: &[TokenTree]) -> usize {
|
|||
#[derive(Debug, Clone)]
|
||||
pub(crate) enum NamedMatch {
|
||||
MatchedSeq(Vec<NamedMatch>),
|
||||
|
||||
// A metavar match of type `tt`.
|
||||
MatchedTokenTree(rustc_ast::tokenstream::TokenTree),
|
||||
|
||||
// A metavar match of any type other than `tt`.
|
||||
MatchedNonterminal(Lrc<(Nonterminal, rustc_span::Span)>),
|
||||
MatchedSingle(ParseNtResult<Lrc<(Nonterminal, Span)>>),
|
||||
}
|
||||
|
||||
/// Performs a token equality check, ignoring syntax context (that is, an unhygienic comparison)
|
||||
|
@ -691,11 +686,11 @@ impl TtParser {
|
|||
}
|
||||
Ok(nt) => nt,
|
||||
};
|
||||
let m = match nt {
|
||||
ParseNtResult::Nt(nt) => MatchedNonterminal(Lrc::new((nt, span))),
|
||||
ParseNtResult::Tt(tt) => MatchedTokenTree(tt),
|
||||
};
|
||||
mp.push_match(next_metavar, seq_depth, m);
|
||||
mp.push_match(
|
||||
next_metavar,
|
||||
seq_depth,
|
||||
MatchedSingle(nt.map_nt(|nt| (Lrc::new((nt, span))))),
|
||||
);
|
||||
mp.idx += 1;
|
||||
} else {
|
||||
unreachable!()
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::mbe;
|
|||
use crate::mbe::diagnostics::{annotate_doc_comment, parse_failure_msg};
|
||||
use crate::mbe::macro_check;
|
||||
use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success, TtParser};
|
||||
use crate::mbe::macro_parser::{MatchedSeq, MatchedTokenTree, MatcherLoc};
|
||||
use crate::mbe::macro_parser::{MatcherLoc, NamedMatch::*};
|
||||
use crate::mbe::transcribe::transcribe;
|
||||
|
||||
use ast::token::IdentIsRaw;
|
||||
|
@ -22,7 +22,7 @@ use rustc_lint_defs::builtin::{
|
|||
RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
|
||||
};
|
||||
use rustc_lint_defs::BuiltinLintDiag;
|
||||
use rustc_parse::parser::{Parser, Recovery};
|
||||
use rustc_parse::parser::{ParseNtResult, Parser, Recovery};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::edition::Edition;
|
||||
|
@ -479,7 +479,7 @@ pub fn compile_declarative_macro(
|
|||
MatchedSeq(s) => s
|
||||
.iter()
|
||||
.map(|m| {
|
||||
if let MatchedTokenTree(tt) = m {
|
||||
if let MatchedSingle(ParseNtResult::Tt(tt)) = m {
|
||||
let tt = mbe::quoted::parse(
|
||||
&TokenStream::new(vec![tt.clone()]),
|
||||
true,
|
||||
|
@ -505,7 +505,7 @@ pub fn compile_declarative_macro(
|
|||
MatchedSeq(s) => s
|
||||
.iter()
|
||||
.map(|m| {
|
||||
if let MatchedTokenTree(tt) = m {
|
||||
if let MatchedSingle(ParseNtResult::Tt(tt)) = m {
|
||||
return mbe::quoted::parse(
|
||||
&TokenStream::new(vec![tt.clone()]),
|
||||
false,
|
||||
|
|
|
@ -3,14 +3,14 @@ use crate::errors::{
|
|||
CountRepetitionMisplaced, MetaVarExprUnrecognizedVar, MetaVarsDifSeqMatchers, MustRepeatOnce,
|
||||
NoSyntaxVarsExprRepeat, VarStillRepeating,
|
||||
};
|
||||
use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, MatchedTokenTree, NamedMatch};
|
||||
use crate::mbe::macro_parser::{NamedMatch, NamedMatch::*};
|
||||
use crate::mbe::{self, KleeneOp, MetaVarExpr};
|
||||
use rustc_ast::mut_visit::{self, MutVisitor};
|
||||
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::Diag;
|
||||
use rustc_errors::{pluralize, PResult};
|
||||
use rustc_errors::{pluralize, Diag, PResult};
|
||||
use rustc_parse::parser::ParseNtResult;
|
||||
use rustc_span::hygiene::{LocalExpnId, Transparency};
|
||||
use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
|
||||
use rustc_span::{with_metavar_spans, Span, SyntaxContext};
|
||||
|
@ -251,12 +251,12 @@ pub(super) fn transcribe<'a>(
|
|||
let ident = MacroRulesNormalizedIdent::new(original_ident);
|
||||
if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) {
|
||||
let tt = match cur_matched {
|
||||
MatchedTokenTree(tt) => {
|
||||
MatchedSingle(ParseNtResult::Tt(tt)) => {
|
||||
// `tt`s are emitted into the output stream directly as "raw tokens",
|
||||
// without wrapping them into groups.
|
||||
maybe_use_metavar_location(cx, &stack, sp, tt, &mut marker)
|
||||
}
|
||||
MatchedNonterminal(nt) => {
|
||||
MatchedSingle(ParseNtResult::Nt(nt)) => {
|
||||
// Other variables are emitted into the output stream as groups with
|
||||
// `Delimiter::Invisible` to maintain parsing priorities.
|
||||
// `Interpolated` is currently used for such groups in rustc parser.
|
||||
|
@ -423,7 +423,7 @@ fn lookup_cur_matched<'a>(
|
|||
interpolations.get(&ident).map(|mut matched| {
|
||||
for &(idx, _) in repeats {
|
||||
match matched {
|
||||
MatchedTokenTree(_) | MatchedNonterminal(_) => break,
|
||||
MatchedSingle(_) => break,
|
||||
MatchedSeq(ads) => matched = ads.get(idx).unwrap(),
|
||||
}
|
||||
}
|
||||
|
@ -513,7 +513,7 @@ fn lockstep_iter_size(
|
|||
let name = MacroRulesNormalizedIdent::new(*name);
|
||||
match lookup_cur_matched(name, interpolations, repeats) {
|
||||
Some(matched) => match matched {
|
||||
MatchedTokenTree(_) | MatchedNonterminal(_) => LockstepIterSize::Unconstrained,
|
||||
MatchedSingle(_) => LockstepIterSize::Unconstrained,
|
||||
MatchedSeq(ads) => LockstepIterSize::Constraint(ads.len(), name),
|
||||
},
|
||||
_ => LockstepIterSize::Unconstrained,
|
||||
|
@ -556,7 +556,7 @@ fn count_repetitions<'a>(
|
|||
// (or at the top-level of `matched` if no depth is given).
|
||||
fn count<'a>(depth_curr: usize, depth_max: usize, matched: &NamedMatch) -> PResult<'a, usize> {
|
||||
match matched {
|
||||
MatchedTokenTree(_) | MatchedNonterminal(_) => Ok(1),
|
||||
MatchedSingle(_) => Ok(1),
|
||||
MatchedSeq(named_matches) => {
|
||||
if depth_curr == depth_max {
|
||||
Ok(named_matches.len())
|
||||
|
@ -570,7 +570,7 @@ fn count_repetitions<'a>(
|
|||
/// Maximum depth
|
||||
fn depth(counter: usize, matched: &NamedMatch) -> usize {
|
||||
match matched {
|
||||
MatchedTokenTree(_) | MatchedNonterminal(_) => counter,
|
||||
MatchedSingle(_) => counter,
|
||||
MatchedSeq(named_matches) => {
|
||||
let rslt = counter + 1;
|
||||
if let Some(elem) = named_matches.first() { depth(rslt, elem) } else { rslt }
|
||||
|
@ -598,7 +598,7 @@ fn count_repetitions<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
if let MatchedTokenTree(_) | MatchedNonterminal(_) = matched {
|
||||
if let MatchedSingle(_) = matched {
|
||||
return Err(cx.dcx().create_err(CountRepetitionMisplaced { span: sp.entire() }));
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
|
|||
pub use path::PathStyle;
|
||||
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{self, Delimiter, Nonterminal, Token, TokenKind};
|
||||
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{AttributesData, DelimSpacing, DelimSpan, Spacing};
|
||||
use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
|
||||
use rustc_ast::util::case::Case;
|
||||
|
@ -1572,8 +1572,21 @@ pub enum FlatToken {
|
|||
Empty,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParseNtResult {
|
||||
Nt(Nonterminal),
|
||||
// Metavar captures of various kinds.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ParseNtResult<NtType> {
|
||||
Tt(TokenTree),
|
||||
Nt(NtType),
|
||||
}
|
||||
|
||||
impl<T> ParseNtResult<T> {
|
||||
pub fn map_nt<F, U>(self, mut f: F) -> ParseNtResult<U>
|
||||
where
|
||||
F: FnMut(T) -> U,
|
||||
{
|
||||
match self {
|
||||
ParseNtResult::Tt(tt) => ParseNtResult::Tt(tt),
|
||||
ParseNtResult::Nt(nt) => ParseNtResult::Nt(f(nt)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{self, Delimiter, Nonterminal::*, NonterminalKind, Token};
|
||||
use rustc_ast::token::{self, Delimiter, Nonterminal, Nonterminal::*, NonterminalKind, Token};
|
||||
use rustc_ast::HasTokens;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::PResult;
|
||||
|
@ -100,7 +100,10 @@ impl<'a> Parser<'a> {
|
|||
/// Parse a non-terminal (e.g. MBE `:pat` or `:ident`). Inlined because there is only one call
|
||||
/// site.
|
||||
#[inline]
|
||||
pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, ParseNtResult> {
|
||||
pub fn parse_nonterminal(
|
||||
&mut self,
|
||||
kind: NonterminalKind,
|
||||
) -> PResult<'a, ParseNtResult<Nonterminal>> {
|
||||
// A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
|
||||
// which requires having captured tokens available. Since we cannot determine
|
||||
// in advance whether or not a proc-macro will be (transitively) invoked,
|
||||
|
|
Loading…
Add table
Reference in a new issue