mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-04 19:29:07 +00:00
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
@ -392,12 +392,7 @@ pub(super) fn count_metavar_decls(matcher: &[TokenTree]) -> usize {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) enum NamedMatch {
|
pub(crate) enum NamedMatch {
|
||||||
MatchedSeq(Vec<NamedMatch>),
|
MatchedSeq(Vec<NamedMatch>),
|
||||||
|
MatchedSingle(ParseNtResult<Lrc<(Nonterminal, Span)>>),
|
||||||
// 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)>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs a token equality check, ignoring syntax context (that is, an unhygienic comparison)
|
/// Performs a token equality check, ignoring syntax context (that is, an unhygienic comparison)
|
||||||
@ -691,11 +686,11 @@ impl TtParser {
|
|||||||
}
|
}
|
||||||
Ok(nt) => nt,
|
Ok(nt) => nt,
|
||||||
};
|
};
|
||||||
let m = match nt {
|
mp.push_match(
|
||||||
ParseNtResult::Nt(nt) => MatchedNonterminal(Lrc::new((nt, span))),
|
next_metavar,
|
||||||
ParseNtResult::Tt(tt) => MatchedTokenTree(tt),
|
seq_depth,
|
||||||
};
|
MatchedSingle(nt.map_nt(|nt| (Lrc::new((nt, span))))),
|
||||||
mp.push_match(next_metavar, seq_depth, m);
|
);
|
||||||
mp.idx += 1;
|
mp.idx += 1;
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
@ -5,7 +5,7 @@ use crate::mbe;
|
|||||||
use crate::mbe::diagnostics::{annotate_doc_comment, parse_failure_msg};
|
use crate::mbe::diagnostics::{annotate_doc_comment, parse_failure_msg};
|
||||||
use crate::mbe::macro_check;
|
use crate::mbe::macro_check;
|
||||||
use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success, TtParser};
|
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 crate::mbe::transcribe::transcribe;
|
||||||
|
|
||||||
use ast::token::IdentIsRaw;
|
use ast::token::IdentIsRaw;
|
||||||
@ -22,7 +22,7 @@ use rustc_lint_defs::builtin::{
|
|||||||
RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
|
RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
|
||||||
};
|
};
|
||||||
use rustc_lint_defs::BuiltinLintDiag;
|
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::parse::ParseSess;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
@ -479,7 +479,7 @@ pub fn compile_declarative_macro(
|
|||||||
MatchedSeq(s) => s
|
MatchedSeq(s) => s
|
||||||
.iter()
|
.iter()
|
||||||
.map(|m| {
|
.map(|m| {
|
||||||
if let MatchedTokenTree(tt) = m {
|
if let MatchedSingle(ParseNtResult::Tt(tt)) = m {
|
||||||
let tt = mbe::quoted::parse(
|
let tt = mbe::quoted::parse(
|
||||||
&TokenStream::new(vec![tt.clone()]),
|
&TokenStream::new(vec![tt.clone()]),
|
||||||
true,
|
true,
|
||||||
@ -505,7 +505,7 @@ pub fn compile_declarative_macro(
|
|||||||
MatchedSeq(s) => s
|
MatchedSeq(s) => s
|
||||||
.iter()
|
.iter()
|
||||||
.map(|m| {
|
.map(|m| {
|
||||||
if let MatchedTokenTree(tt) = m {
|
if let MatchedSingle(ParseNtResult::Tt(tt)) = m {
|
||||||
return mbe::quoted::parse(
|
return mbe::quoted::parse(
|
||||||
&TokenStream::new(vec![tt.clone()]),
|
&TokenStream::new(vec![tt.clone()]),
|
||||||
false,
|
false,
|
||||||
|
@ -3,14 +3,14 @@ use crate::errors::{
|
|||||||
CountRepetitionMisplaced, MetaVarExprUnrecognizedVar, MetaVarsDifSeqMatchers, MustRepeatOnce,
|
CountRepetitionMisplaced, MetaVarExprUnrecognizedVar, MetaVarsDifSeqMatchers, MustRepeatOnce,
|
||||||
NoSyntaxVarsExprRepeat, VarStillRepeating,
|
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 crate::mbe::{self, KleeneOp, MetaVarExpr};
|
||||||
use rustc_ast::mut_visit::{self, MutVisitor};
|
use rustc_ast::mut_visit::{self, MutVisitor};
|
||||||
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
|
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
|
||||||
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
|
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::Diag;
|
use rustc_errors::{pluralize, Diag, PResult};
|
||||||
use rustc_errors::{pluralize, PResult};
|
use rustc_parse::parser::ParseNtResult;
|
||||||
use rustc_span::hygiene::{LocalExpnId, Transparency};
|
use rustc_span::hygiene::{LocalExpnId, Transparency};
|
||||||
use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
|
use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
|
||||||
use rustc_span::{with_metavar_spans, Span, SyntaxContext};
|
use rustc_span::{with_metavar_spans, Span, SyntaxContext};
|
||||||
@ -251,12 +251,12 @@ pub(super) fn transcribe<'a>(
|
|||||||
let ident = MacroRulesNormalizedIdent::new(original_ident);
|
let ident = MacroRulesNormalizedIdent::new(original_ident);
|
||||||
if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) {
|
if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) {
|
||||||
let tt = match cur_matched {
|
let tt = match cur_matched {
|
||||||
MatchedTokenTree(tt) => {
|
MatchedSingle(ParseNtResult::Tt(tt)) => {
|
||||||
// `tt`s are emitted into the output stream directly as "raw tokens",
|
// `tt`s are emitted into the output stream directly as "raw tokens",
|
||||||
// without wrapping them into groups.
|
// without wrapping them into groups.
|
||||||
maybe_use_metavar_location(cx, &stack, sp, tt, &mut marker)
|
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
|
// Other variables are emitted into the output stream as groups with
|
||||||
// `Delimiter::Invisible` to maintain parsing priorities.
|
// `Delimiter::Invisible` to maintain parsing priorities.
|
||||||
// `Interpolated` is currently used for such groups in rustc parser.
|
// `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| {
|
interpolations.get(&ident).map(|mut matched| {
|
||||||
for &(idx, _) in repeats {
|
for &(idx, _) in repeats {
|
||||||
match matched {
|
match matched {
|
||||||
MatchedTokenTree(_) | MatchedNonterminal(_) => break,
|
MatchedSingle(_) => break,
|
||||||
MatchedSeq(ads) => matched = ads.get(idx).unwrap(),
|
MatchedSeq(ads) => matched = ads.get(idx).unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -513,7 +513,7 @@ fn lockstep_iter_size(
|
|||||||
let name = MacroRulesNormalizedIdent::new(*name);
|
let name = MacroRulesNormalizedIdent::new(*name);
|
||||||
match lookup_cur_matched(name, interpolations, repeats) {
|
match lookup_cur_matched(name, interpolations, repeats) {
|
||||||
Some(matched) => match matched {
|
Some(matched) => match matched {
|
||||||
MatchedTokenTree(_) | MatchedNonterminal(_) => LockstepIterSize::Unconstrained,
|
MatchedSingle(_) => LockstepIterSize::Unconstrained,
|
||||||
MatchedSeq(ads) => LockstepIterSize::Constraint(ads.len(), name),
|
MatchedSeq(ads) => LockstepIterSize::Constraint(ads.len(), name),
|
||||||
},
|
},
|
||||||
_ => LockstepIterSize::Unconstrained,
|
_ => LockstepIterSize::Unconstrained,
|
||||||
@ -556,7 +556,7 @@ fn count_repetitions<'a>(
|
|||||||
// (or at the top-level of `matched` if no depth is given).
|
// (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> {
|
fn count<'a>(depth_curr: usize, depth_max: usize, matched: &NamedMatch) -> PResult<'a, usize> {
|
||||||
match matched {
|
match matched {
|
||||||
MatchedTokenTree(_) | MatchedNonterminal(_) => Ok(1),
|
MatchedSingle(_) => Ok(1),
|
||||||
MatchedSeq(named_matches) => {
|
MatchedSeq(named_matches) => {
|
||||||
if depth_curr == depth_max {
|
if depth_curr == depth_max {
|
||||||
Ok(named_matches.len())
|
Ok(named_matches.len())
|
||||||
@ -570,7 +570,7 @@ fn count_repetitions<'a>(
|
|||||||
/// Maximum depth
|
/// Maximum depth
|
||||||
fn depth(counter: usize, matched: &NamedMatch) -> usize {
|
fn depth(counter: usize, matched: &NamedMatch) -> usize {
|
||||||
match matched {
|
match matched {
|
||||||
MatchedTokenTree(_) | MatchedNonterminal(_) => counter,
|
MatchedSingle(_) => counter,
|
||||||
MatchedSeq(named_matches) => {
|
MatchedSeq(named_matches) => {
|
||||||
let rslt = counter + 1;
|
let rslt = counter + 1;
|
||||||
if let Some(elem) = named_matches.first() { depth(rslt, elem) } else { rslt }
|
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() }));
|
return Err(cx.dcx().create_err(CountRepetitionMisplaced { span: sp.entire() }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
|
|||||||
pub use path::PathStyle;
|
pub use path::PathStyle;
|
||||||
|
|
||||||
use rustc_ast::ptr::P;
|
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::{AttributesData, DelimSpacing, DelimSpan, Spacing};
|
||||||
use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
|
use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
|
||||||
use rustc_ast::util::case::Case;
|
use rustc_ast::util::case::Case;
|
||||||
@ -1572,8 +1572,21 @@ pub enum FlatToken {
|
|||||||
Empty,
|
Empty,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
// Metavar captures of various kinds.
|
||||||
pub enum ParseNtResult {
|
#[derive(Clone, Debug)]
|
||||||
Nt(Nonterminal),
|
pub enum ParseNtResult<NtType> {
|
||||||
Tt(TokenTree),
|
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::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::HasTokens;
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_errors::PResult;
|
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
|
/// Parse a non-terminal (e.g. MBE `:pat` or `:ident`). Inlined because there is only one call
|
||||||
/// site.
|
/// site.
|
||||||
#[inline]
|
#[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,
|
// A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
|
||||||
// which requires having captured tokens available. Since we cannot determine
|
// which requires having captured tokens available. Since we cannot determine
|
||||||
// in advance whether or not a proc-macro will be (transitively) invoked,
|
// in advance whether or not a proc-macro will be (transitively) invoked,
|
||||||
|
Loading…
Reference in New Issue
Block a user