use crate::ast;
use crate::attr::{self, TransparencyError};
use crate::edition::Edition;
use crate::ext::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander};
use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind};
use crate::ext::expand::{AstFragment, AstFragmentKind};
use crate::ext::tt::macro_check;
use crate::ext::tt::macro_parser::{parse, parse_failure_msg};
use crate::ext::tt::macro_parser::{Error, Failure, Success};
use crate::ext::tt::macro_parser::{MatchedNonterminal, MatchedSeq};
use crate::ext::tt::quoted;
use crate::ext::tt::transcribe::transcribe;
use crate::feature_gate::Features;
use crate::parse::parser::Parser;
use crate::parse::token::TokenKind::*;
use crate::parse::token::{self, NtTT, Token};
use crate::parse::{Directory, ParseSess};
use crate::symbol::{kw, sym, Symbol};
use crate::tokenstream::{DelimSpan, TokenStream, TokenTree};

use errors::{DiagnosticBuilder, FatalError};
use log::debug;
use syntax_pos::hygiene::Transparency;
use syntax_pos::Span;

use rustc_data_structures::fx::FxHashMap;
use std::borrow::Cow;
use std::collections::hash_map::Entry;
use std::slice;

use errors::Applicability;
use rustc_data_structures::sync::Lrc;

const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
                                        `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \
                                        `literal`, `path`, `meta`, `tt`, `item` and `vis`";

pub struct ParserAnyMacro<'a> {
    parser: Parser<'a>,

    /// Span of the expansion site of the macro this parser is for
    site_span: Span,
    /// The ident of the macro we're parsing
    macro_ident: ast::Ident,
    arm_span: Span,
}

pub fn annotate_err_with_kind(err: &mut DiagnosticBuilder<'_>, kind: AstFragmentKind, span: Span) {
    match kind {
        AstFragmentKind::Ty => {
            err.span_label(span, "this macro call doesn't expand to a type");
        }
        AstFragmentKind::Pat => {
            err.span_label(span, "this macro call doesn't expand to a pattern");
        }
        _ => {}
    };
}

impl<'a> ParserAnyMacro<'a> {
    pub fn make(mut self: Box<ParserAnyMacro<'a>>, kind: AstFragmentKind) -> AstFragment {
        let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self;
        let fragment = panictry!(parser.parse_ast_fragment(kind, true).map_err(|mut e| {
            if parser.token == token::Eof && e.message().ends_with(", found `<eof>`") {
                if !e.span.is_dummy() {
                    // early end of macro arm (#52866)
                    e.replace_span_with(parser.sess.source_map().next_point(parser.token.span));
                }
                let msg = &e.message[0];
                e.message[0] = (
                    format!(
                        "macro expansion ends with an incomplete expression: {}",
                        msg.0.replace(", found `<eof>`", ""),
                    ),
                    msg.1,
                );
            }
            if e.span.is_dummy() {
                // Get around lack of span in error (#30128)
                e.replace_span_with(site_span);
                if parser.sess.source_map().span_to_filename(arm_span).is_real() {
                    e.span_label(arm_span, "in this macro arm");
                }
            } else if !parser.sess.source_map().span_to_filename(parser.token.span).is_real() {
                e.span_label(site_span, "in this macro invocation");
            }
            match kind {
                AstFragmentKind::Pat if macro_ident.name == sym::vec => {
                    let mut suggestion = None;
                    if let Ok(code) = parser.sess.source_map().span_to_snippet(site_span) {
                        if let Some(bang) = code.find('!') {
                            suggestion = Some(code[bang + 1..].to_string());
                        }
                    }
                    if let Some(suggestion) = suggestion {
                        e.span_suggestion(
                            site_span,
                            "use a slice pattern here instead",
                            suggestion,
                            Applicability::MachineApplicable,
                        );
                    } else {
                        e.span_label(
                            site_span,
                            "use a slice pattern here instead",
                        );
                    }
                    e.help("for more information, see https://doc.rust-lang.org/edition-guide/\
                            rust-2018/slice-patterns.html");
                }
                _ => annotate_err_with_kind(&mut e, kind, site_span),
            };
            e
        }));

        // We allow semicolons at the end of expressions -- e.g., the semicolon in
        // `macro_rules! m { () => { panic!(); } }` isn't parsed by `.parse_expr()`,
        // but `m!()` is allowed in expression positions (cf. issue #34706).
        if kind == AstFragmentKind::Expr && parser.token == token::Semi {
            parser.bump();
        }

        // Make sure we don't have any tokens left to parse so we don't silently drop anything.
        let path = ast::Path::from_ident(macro_ident.with_span_pos(site_span));
        parser.ensure_complete_parse(&path, kind.name(), site_span);
        fragment
    }
}

struct MacroRulesMacroExpander {
    name: ast::Ident,
    span: Span,
    transparency: Transparency,
    lhses: Vec<quoted::TokenTree>,
    rhses: Vec<quoted::TokenTree>,
    valid: bool,
}

impl TTMacroExpander for MacroRulesMacroExpander {
    fn expand<'cx>(
        &self,
        cx: &'cx mut ExtCtxt<'_>,
        sp: Span,
        input: TokenStream,
    ) -> Box<dyn MacResult + 'cx> {
        if !self.valid {
            return DummyResult::any(sp);
        }
        generic_extension(
            cx, sp, self.span, self.name, self.transparency, input, &self.lhses, &self.rhses
        )
    }
}

fn trace_macros_note(cx: &mut ExtCtxt<'_>, sp: Span, message: String) {
    let sp = sp.macro_backtrace().last().map(|trace| trace.call_site).unwrap_or(sp);
    cx.expansions.entry(sp).or_default().push(message);
}

/// Given `lhses` and `rhses`, this is the new macro we create
fn generic_extension<'cx>(
    cx: &'cx mut ExtCtxt<'_>,
    sp: Span,
    def_span: Span,
    name: ast::Ident,
    transparency: Transparency,
    arg: TokenStream,
    lhses: &[quoted::TokenTree],
    rhses: &[quoted::TokenTree],
) -> Box<dyn MacResult + 'cx> {
    if cx.trace_macros() {
        trace_macros_note(cx, sp, format!("expanding `{}! {{ {} }}`", name, arg));
    }

    // Which arm's failure should we report? (the one furthest along)
    let mut best_failure: Option<(Token, &str)> = None;

    for (i, lhs) in lhses.iter().enumerate() {
        // try each arm's matchers
        let lhs_tt = match *lhs {
            quoted::TokenTree::Delimited(_, ref delim) => &delim.tts[..],
            _ => cx.span_bug(sp, "malformed macro lhs"),
        };

        match TokenTree::parse(cx, lhs_tt, arg.clone()) {
            Success(named_matches) => {
                let rhs = match rhses[i] {
                    // ignore delimiters
                    quoted::TokenTree::Delimited(_, ref delimed) => delimed.tts.clone(),
                    _ => cx.span_bug(sp, "malformed macro rhs"),
                };
                let arm_span = rhses[i].span();

                let rhs_spans = rhs.iter().map(|t| t.span()).collect::<Vec<_>>();
                // rhs has holes ( `$id` and `$(...)` that need filled)
                let mut tts = transcribe(cx, &named_matches, rhs, transparency);

                // Replace all the tokens for the corresponding positions in the macro, to maintain
                // proper positions in error reporting, while maintaining the macro_backtrace.
                if rhs_spans.len() == tts.len() {
                    tts = tts.map_enumerated(|i, mut tt| {
                        let mut sp = rhs_spans[i];
                        sp = sp.with_ctxt(tt.span().ctxt());
                        tt.set_span(sp);
                        tt
                    });
                }

                if cx.trace_macros() {
                    trace_macros_note(cx, sp, format!("to `{}`", tts));
                }

                let directory = Directory {
                    path: Cow::from(cx.current_expansion.module.directory.as_path()),
                    ownership: cx.current_expansion.directory_ownership,
                };
                let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false, None);
                p.root_module_name =
                    cx.current_expansion.module.mod_path.last().map(|id| id.as_str().to_string());
                p.last_type_ascription = cx.current_expansion.prior_type_ascription;

                p.process_potential_macro_variable();
                // Let the context choose how to interpret the result.
                // Weird, but useful for X-macros.
                return Box::new(ParserAnyMacro {
                    parser: p,

                    // Pass along the original expansion site and the name of the macro
                    // so we can print a useful error message if the parse of the expanded
                    // macro leaves unparsed tokens.
                    site_span: sp,
                    macro_ident: name,
                    arm_span,
                });
            }
            Failure(token, msg) => match best_failure {
                Some((ref best_token, _)) if best_token.span.lo() >= token.span.lo() => {}
                _ => best_failure = Some((token, msg)),
            },
            Error(err_sp, ref msg) => cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..]),
        }
    }

    let (token, label) = best_failure.expect("ran no matchers");
    let span = token.span.substitute_dummy(sp);
    let mut err = cx.struct_span_err(span, &parse_failure_msg(&token));
    err.span_label(span, label);
    if !def_span.is_dummy() && cx.source_map().span_to_filename(def_span).is_real() {
        err.span_label(cx.source_map().def_span(def_span), "when calling this macro");
    }

    // Check whether there's a missing comma in this macro call, like `println!("{}" a);`
    if let Some((arg, comma_span)) = arg.add_comma() {
        for lhs in lhses {
            // try each arm's matchers
            let lhs_tt = match *lhs {
                quoted::TokenTree::Delimited(_, ref delim) => &delim.tts[..],
                _ => continue,
            };
            match TokenTree::parse(cx, lhs_tt, arg.clone()) {
                Success(_) => {
                    if comma_span.is_dummy() {
                        err.note("you might be missing a comma");
                    } else {
                        err.span_suggestion_short(
                            comma_span,
                            "missing comma here",
                            ", ".to_string(),
                            Applicability::MachineApplicable,
                        );
                    }
                }
                _ => {}
            }
        }
    }
    err.emit();
    cx.trace_macros_diag();
    DummyResult::any(sp)
}

// Note that macro-by-example's input is also matched against a token tree:
//                   $( $lhs:tt => $rhs:tt );+
//
// Holy self-referential!

/// Converts a `macro_rules!` invocation into a syntax extension.
pub fn compile(
    sess: &ParseSess,
    features: &Features,
    def: &ast::Item,
    edition: Edition,
) -> SyntaxExtension {
    let diag = &sess.span_diagnostic;
    let lhs_nm = ast::Ident::new(sym::lhs, def.span);
    let rhs_nm = ast::Ident::new(sym::rhs, def.span);
    let tt_spec = ast::Ident::new(sym::tt, def.span);

    // Parse the macro_rules! invocation
    let body = match def.node {
        ast::ItemKind::MacroDef(ref body) => body,
        _ => unreachable!(),
    };

    // The pattern that macro_rules matches.
    // The grammar for macro_rules! is:
    // $( $lhs:tt => $rhs:tt );+
    // ...quasiquoting this would be nice.
    // These spans won't matter, anyways
    let argument_gram = vec![
        quoted::TokenTree::Sequence(
            DelimSpan::dummy(),
            Lrc::new(quoted::SequenceRepetition {
                tts: vec![
                    quoted::TokenTree::MetaVarDecl(def.span, lhs_nm, tt_spec),
                    quoted::TokenTree::token(token::FatArrow, def.span),
                    quoted::TokenTree::MetaVarDecl(def.span, rhs_nm, tt_spec),
                ],
                separator: Some(Token::new(
                    if body.legacy { token::Semi } else { token::Comma },
                    def.span,
                )),
                kleene: quoted::KleeneToken::new(quoted::KleeneOp::OneOrMore, def.span),
                num_captures: 2,
            }),
        ),
        // to phase into semicolon-termination instead of semicolon-separation
        quoted::TokenTree::Sequence(
            DelimSpan::dummy(),
            Lrc::new(quoted::SequenceRepetition {
                tts: vec![quoted::TokenTree::token(
                    if body.legacy { token::Semi } else { token::Comma },
                    def.span,
                )],
                separator: None,
                kleene: quoted::KleeneToken::new(quoted::KleeneOp::ZeroOrMore, def.span),
                num_captures: 0,
            }),
        ),
    ];

    let argument_map = match parse(sess, body.stream(), &argument_gram, None, true) {
        Success(m) => m,
        Failure(token, msg) => {
            let s = parse_failure_msg(&token);
            let sp = token.span.substitute_dummy(def.span);
            let mut err = sess.span_diagnostic.struct_span_fatal(sp, &s);
            err.span_label(sp, msg);
            err.emit();
            FatalError.raise();
        }
        Error(sp, s) => {
            sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s).raise();
        }
    };

    let mut valid = true;

    // Extract the arguments:
    let lhses = match argument_map[&lhs_nm] {
        MatchedSeq(ref s, _) => s
            .iter()
            .map(|m| {
                if let MatchedNonterminal(ref nt) = *m {
                    if let NtTT(ref tt) = **nt {
                        let tt = quoted::parse(
                            tt.clone().into(),
                            true,
                            sess,
                            features,
                            &def.attrs,
                            edition,
                            def.id,
                        )
                        .pop()
                        .unwrap();
                        valid &= check_lhs_nt_follows(sess, features, &def.attrs, &tt);
                        return tt;
                    }
                }
                sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs")
            })
            .collect::<Vec<quoted::TokenTree>>(),
        _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs"),
    };

    let rhses = match argument_map[&rhs_nm] {
        MatchedSeq(ref s, _) => s
            .iter()
            .map(|m| {
                if let MatchedNonterminal(ref nt) = *m {
                    if let NtTT(ref tt) = **nt {
                        return quoted::parse(
                            tt.clone().into(),
                            false,
                            sess,
                            features,
                            &def.attrs,
                            edition,
                            def.id,
                        )
                        .pop()
                        .unwrap();
                    }
                }
                sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs")
            })
            .collect::<Vec<quoted::TokenTree>>(),
        _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs"),
    };

    for rhs in &rhses {
        valid &= check_rhs(sess, rhs);
    }

    // don't abort iteration early, so that errors for multiple lhses can be reported
    for lhs in &lhses {
        valid &= check_lhs_no_empty_seq(sess, slice::from_ref(lhs));
    }

    // We use CRATE_NODE_ID instead of `def.id` otherwise we may emit buffered lints for a node id
    // that is not lint-checked and trigger the "failed to process buffered lint here" bug.
    valid &= macro_check::check_meta_variables(sess, ast::CRATE_NODE_ID, def.span, &lhses, &rhses);

    let (transparency, transparency_error) = attr::find_transparency(&def.attrs, body.legacy);
    match transparency_error {
        Some(TransparencyError::UnknownTransparency(value, span)) =>
            diag.span_err(span, &format!("unknown macro transparency: `{}`", value)),
        Some(TransparencyError::MultipleTransparencyAttrs(old_span, new_span)) =>
            diag.span_err(vec![old_span, new_span], "multiple macro transparency attributes"),
        None => {}
    }

    let expander: Box<_> = Box::new(MacroRulesMacroExpander {
        name: def.ident, span: def.span, transparency, lhses, rhses, valid
    });

    SyntaxExtension::new(
        sess,
        SyntaxExtensionKind::LegacyBang(expander),
        def.span,
        Vec::new(),
        edition,
        def.ident.name,
        &def.attrs,
    )
}

fn check_lhs_nt_follows(
    sess: &ParseSess,
    features: &Features,
    attrs: &[ast::Attribute],
    lhs: &quoted::TokenTree,
) -> bool {
    // lhs is going to be like TokenTree::Delimited(...), where the
    // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
    if let quoted::TokenTree::Delimited(_, ref tts) = *lhs {
        check_matcher(sess, features, attrs, &tts.tts)
    } else {
        let msg = "invalid macro matcher; matchers must be contained in balanced delimiters";
        sess.span_diagnostic.span_err(lhs.span(), msg);
        false
    }
    // we don't abort on errors on rejection, the driver will do that for us
    // after parsing/expansion. we can report every error in every macro this way.
}

/// Checks that the lhs contains no repetition which could match an empty token
/// tree, because then the matcher would hang indefinitely.
fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[quoted::TokenTree]) -> bool {
    use quoted::TokenTree;
    for tt in tts {
        match *tt {
            TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => (),
            TokenTree::Delimited(_, ref del) => {
                if !check_lhs_no_empty_seq(sess, &del.tts) {
                    return false;
                }
            }
            TokenTree::Sequence(span, ref seq) => {
                if seq.separator.is_none()
                    && seq.tts.iter().all(|seq_tt| match *seq_tt {
                        TokenTree::MetaVarDecl(_, _, id) => id.name == sym::vis,
                        TokenTree::Sequence(_, ref sub_seq) => {
                            sub_seq.kleene.op == quoted::KleeneOp::ZeroOrMore
                                || sub_seq.kleene.op == quoted::KleeneOp::ZeroOrOne
                        }
                        _ => false,
                    })
                {
                    let sp = span.entire();
                    sess.span_diagnostic.span_err(sp, "repetition matches empty token tree");
                    return false;
                }
                if !check_lhs_no_empty_seq(sess, &seq.tts) {
                    return false;
                }
            }
        }
    }

    true
}

fn check_rhs(sess: &ParseSess, rhs: &quoted::TokenTree) -> bool {
    match *rhs {
        quoted::TokenTree::Delimited(..) => return true,
        _ => sess.span_diagnostic.span_err(rhs.span(), "macro rhs must be delimited"),
    }
    false
}

fn check_matcher(
    sess: &ParseSess,
    features: &Features,
    attrs: &[ast::Attribute],
    matcher: &[quoted::TokenTree],
) -> bool {
    let first_sets = FirstSets::new(matcher);
    let empty_suffix = TokenSet::empty();
    let err = sess.span_diagnostic.err_count();
    check_matcher_core(sess, features, attrs, &first_sets, matcher, &empty_suffix);
    err == sess.span_diagnostic.err_count()
}

// `The FirstSets` for a matcher is a mapping from subsequences in the
// matcher to the FIRST set for that subsequence.
//
// This mapping is partially precomputed via a backwards scan over the
// token trees of the matcher, which provides a mapping from each
// repetition sequence to its *first* set.
//
// (Hypothetically, sequences should be uniquely identifiable via their
// spans, though perhaps that is false, e.g., for macro-generated macros
// that do not try to inject artificial span information. My plan is
// to try to catch such cases ahead of time and not include them in
// the precomputed mapping.)
struct FirstSets {
    // this maps each TokenTree::Sequence `$(tt ...) SEP OP` that is uniquely identified by its
    // span in the original matcher to the First set for the inner sequence `tt ...`.
    //
    // If two sequences have the same span in a matcher, then map that
    // span to None (invalidating the mapping here and forcing the code to
    // use a slow path).
    first: FxHashMap<Span, Option<TokenSet>>,
}

impl FirstSets {
    fn new(tts: &[quoted::TokenTree]) -> FirstSets {
        use quoted::TokenTree;

        let mut sets = FirstSets { first: FxHashMap::default() };
        build_recur(&mut sets, tts);
        return sets;

        // walks backward over `tts`, returning the FIRST for `tts`
        // and updating `sets` at the same time for all sequence
        // substructure we find within `tts`.
        fn build_recur(sets: &mut FirstSets, tts: &[TokenTree]) -> TokenSet {
            let mut first = TokenSet::empty();
            for tt in tts.iter().rev() {
                match *tt {
                    TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => {
                        first.replace_with(tt.clone());
                    }
                    TokenTree::Delimited(span, ref delimited) => {
                        build_recur(sets, &delimited.tts[..]);
                        first.replace_with(delimited.open_tt(span.open));
                    }
                    TokenTree::Sequence(sp, ref seq_rep) => {
                        let subfirst = build_recur(sets, &seq_rep.tts[..]);

                        match sets.first.entry(sp.entire()) {
                            Entry::Vacant(vac) => {
                                vac.insert(Some(subfirst.clone()));
                            }
                            Entry::Occupied(mut occ) => {
                                // if there is already an entry, then a span must have collided.
                                // This should not happen with typical macro_rules macros,
                                // but syntax extensions need not maintain distinct spans,
                                // so distinct syntax trees can be assigned the same span.
                                // In such a case, the map cannot be trusted; so mark this
                                // entry as unusable.
                                occ.insert(None);
                            }
                        }

                        // If the sequence contents can be empty, then the first
                        // token could be the separator token itself.

                        if let (Some(sep), true) = (&seq_rep.separator, subfirst.maybe_empty) {
                            first.add_one_maybe(TokenTree::Token(sep.clone()));
                        }

                        // Reverse scan: Sequence comes before `first`.
                        if subfirst.maybe_empty
                            || seq_rep.kleene.op == quoted::KleeneOp::ZeroOrMore
                            || seq_rep.kleene.op == quoted::KleeneOp::ZeroOrOne
                        {
                            // If sequence is potentially empty, then
                            // union them (preserving first emptiness).
                            first.add_all(&TokenSet { maybe_empty: true, ..subfirst });
                        } else {
                            // Otherwise, sequence guaranteed
                            // non-empty; replace first.
                            first = subfirst;
                        }
                    }
                }
            }

            first
        }
    }

    // walks forward over `tts` until all potential FIRST tokens are
    // identified.
    fn first(&self, tts: &[quoted::TokenTree]) -> TokenSet {
        use quoted::TokenTree;

        let mut first = TokenSet::empty();
        for tt in tts.iter() {
            assert!(first.maybe_empty);
            match *tt {
                TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => {
                    first.add_one(tt.clone());
                    return first;
                }
                TokenTree::Delimited(span, ref delimited) => {
                    first.add_one(delimited.open_tt(span.open));
                    return first;
                }
                TokenTree::Sequence(sp, ref seq_rep) => {
                    let subfirst_owned;
                    let subfirst = match self.first.get(&sp.entire()) {
                        Some(&Some(ref subfirst)) => subfirst,
                        Some(&None) => {
                            subfirst_owned = self.first(&seq_rep.tts[..]);
                            &subfirst_owned
                        }
                        None => {
                            panic!("We missed a sequence during FirstSets construction");
                        }
                    };

                    // If the sequence contents can be empty, then the first
                    // token could be the separator token itself.
                    if let (Some(sep), true) = (&seq_rep.separator, subfirst.maybe_empty) {
                        first.add_one_maybe(TokenTree::Token(sep.clone()));
                    }

                    assert!(first.maybe_empty);
                    first.add_all(subfirst);
                    if subfirst.maybe_empty
                        || seq_rep.kleene.op == quoted::KleeneOp::ZeroOrMore
                        || seq_rep.kleene.op == quoted::KleeneOp::ZeroOrOne
                    {
                        // Continue scanning for more first
                        // tokens, but also make sure we
                        // restore empty-tracking state.
                        first.maybe_empty = true;
                        continue;
                    } else {
                        return first;
                    }
                }
            }
        }

        // we only exit the loop if `tts` was empty or if every
        // element of `tts` matches the empty sequence.
        assert!(first.maybe_empty);
        first
    }
}

// A set of `quoted::TokenTree`s, which may include `TokenTree::Match`s
// (for macro-by-example syntactic variables). It also carries the
// `maybe_empty` flag; that is true if and only if the matcher can
// match an empty token sequence.
//
// The First set is computed on submatchers like `$($a:expr b),* $(c)* d`,
// which has corresponding FIRST = {$a:expr, c, d}.
// Likewise, `$($a:expr b),* $(c)+ d` has FIRST = {$a:expr, c}.
//
// (Notably, we must allow for *-op to occur zero times.)
#[derive(Clone, Debug)]
struct TokenSet {
    tokens: Vec<quoted::TokenTree>,
    maybe_empty: bool,
}

impl TokenSet {
    // Returns a set for the empty sequence.
    fn empty() -> Self {
        TokenSet { tokens: Vec::new(), maybe_empty: true }
    }

    // Returns the set `{ tok }` for the single-token (and thus
    // non-empty) sequence [tok].
    fn singleton(tok: quoted::TokenTree) -> Self {
        TokenSet { tokens: vec![tok], maybe_empty: false }
    }

    // Changes self to be the set `{ tok }`.
    // Since `tok` is always present, marks self as non-empty.
    fn replace_with(&mut self, tok: quoted::TokenTree) {
        self.tokens.clear();
        self.tokens.push(tok);
        self.maybe_empty = false;
    }

    // Changes self to be the empty set `{}`; meant for use when
    // the particular token does not matter, but we want to
    // record that it occurs.
    fn replace_with_irrelevant(&mut self) {
        self.tokens.clear();
        self.maybe_empty = false;
    }

    // Adds `tok` to the set for `self`, marking sequence as non-empy.
    fn add_one(&mut self, tok: quoted::TokenTree) {
        if !self.tokens.contains(&tok) {
            self.tokens.push(tok);
        }
        self.maybe_empty = false;
    }

    // Adds `tok` to the set for `self`. (Leaves `maybe_empty` flag alone.)
    fn add_one_maybe(&mut self, tok: quoted::TokenTree) {
        if !self.tokens.contains(&tok) {
            self.tokens.push(tok);
        }
    }

    // Adds all elements of `other` to this.
    //
    // (Since this is a set, we filter out duplicates.)
    //
    // If `other` is potentially empty, then preserves the previous
    // setting of the empty flag of `self`. If `other` is guaranteed
    // non-empty, then `self` is marked non-empty.
    fn add_all(&mut self, other: &Self) {
        for tok in &other.tokens {
            if !self.tokens.contains(tok) {
                self.tokens.push(tok.clone());
            }
        }
        if !other.maybe_empty {
            self.maybe_empty = false;
        }
    }
}

// Checks that `matcher` is internally consistent and that it
// can legally be followed by a token `N`, for all `N` in `follow`.
// (If `follow` is empty, then it imposes no constraint on
// the `matcher`.)
//
// Returns the set of NT tokens that could possibly come last in
// `matcher`. (If `matcher` matches the empty sequence, then
// `maybe_empty` will be set to true.)
//
// Requires that `first_sets` is pre-computed for `matcher`;
// see `FirstSets::new`.
fn check_matcher_core(
    sess: &ParseSess,
    features: &Features,
    attrs: &[ast::Attribute],
    first_sets: &FirstSets,
    matcher: &[quoted::TokenTree],
    follow: &TokenSet,
) -> TokenSet {
    use quoted::TokenTree;

    let mut last = TokenSet::empty();

    // 2. For each token and suffix  [T, SUFFIX] in M:
    // ensure that T can be followed by SUFFIX, and if SUFFIX may be empty,
    // then ensure T can also be followed by any element of FOLLOW.
    'each_token: for i in 0..matcher.len() {
        let token = &matcher[i];
        let suffix = &matcher[i + 1..];

        let build_suffix_first = || {
            let mut s = first_sets.first(suffix);
            if s.maybe_empty {
                s.add_all(follow);
            }
            s
        };

        // (we build `suffix_first` on demand below; you can tell
        // which cases are supposed to fall through by looking for the
        // initialization of this variable.)
        let suffix_first;

        // First, update `last` so that it corresponds to the set
        // of NT tokens that might end the sequence `... token`.
        match *token {
            TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => {
                let can_be_followed_by_any;
                if let Err(bad_frag) = has_legal_fragment_specifier(sess, features, attrs, token) {
                    let msg = format!("invalid fragment specifier `{}`", bad_frag);
                    sess.span_diagnostic
                        .struct_span_err(token.span(), &msg)
                        .help(VALID_FRAGMENT_NAMES_MSG)
                        .emit();
                    // (This eliminates false positives and duplicates
                    // from error messages.)
                    can_be_followed_by_any = true;
                } else {
                    can_be_followed_by_any = token_can_be_followed_by_any(token);
                }

                if can_be_followed_by_any {
                    // don't need to track tokens that work with any,
                    last.replace_with_irrelevant();
                    // ... and don't need to check tokens that can be
                    // followed by anything against SUFFIX.
                    continue 'each_token;
                } else {
                    last.replace_with(token.clone());
                    suffix_first = build_suffix_first();
                }
            }
            TokenTree::Delimited(span, ref d) => {
                let my_suffix = TokenSet::singleton(d.close_tt(span.close));
                check_matcher_core(sess, features, attrs, first_sets, &d.tts, &my_suffix);
                // don't track non NT tokens
                last.replace_with_irrelevant();

                // also, we don't need to check delimited sequences
                // against SUFFIX
                continue 'each_token;
            }
            TokenTree::Sequence(_, ref seq_rep) => {
                suffix_first = build_suffix_first();
                // The trick here: when we check the interior, we want
                // to include the separator (if any) as a potential
                // (but not guaranteed) element of FOLLOW. So in that
                // case, we make a temp copy of suffix and stuff
                // delimiter in there.
                //
                // FIXME: Should I first scan suffix_first to see if
                // delimiter is already in it before I go through the
                // work of cloning it? But then again, this way I may
                // get a "tighter" span?
                let mut new;
                let my_suffix = if let Some(sep) = &seq_rep.separator {
                    new = suffix_first.clone();
                    new.add_one_maybe(TokenTree::Token(sep.clone()));
                    &new
                } else {
                    &suffix_first
                };

                // At this point, `suffix_first` is built, and
                // `my_suffix` is some TokenSet that we can use
                // for checking the interior of `seq_rep`.
                let next =
                    check_matcher_core(sess, features, attrs, first_sets, &seq_rep.tts, my_suffix);
                if next.maybe_empty {
                    last.add_all(&next);
                } else {
                    last = next;
                }

                // the recursive call to check_matcher_core already ran the 'each_last
                // check below, so we can just keep going forward here.
                continue 'each_token;
            }
        }

        // (`suffix_first` guaranteed initialized once reaching here.)

        // Now `last` holds the complete set of NT tokens that could
        // end the sequence before SUFFIX. Check that every one works with `suffix`.
        'each_last: for token in &last.tokens {
            if let TokenTree::MetaVarDecl(_, name, frag_spec) = *token {
                for next_token in &suffix_first.tokens {
                    match is_in_follow(next_token, frag_spec.name) {
                        IsInFollow::Invalid(msg, help) => {
                            sess.span_diagnostic
                                .struct_span_err(next_token.span(), &msg)
                                .help(help)
                                .emit();
                            // don't bother reporting every source of
                            // conflict for a particular element of `last`.
                            continue 'each_last;
                        }
                        IsInFollow::Yes => {}
                        IsInFollow::No(possible) => {
                            let may_be = if last.tokens.len() == 1 && suffix_first.tokens.len() == 1
                            {
                                "is"
                            } else {
                                "may be"
                            };

                            let sp = next_token.span();
                            let mut err = sess.span_diagnostic.struct_span_err(
                                sp,
                                &format!(
                                    "`${name}:{frag}` {may_be} followed by `{next}`, which \
                                     is not allowed for `{frag}` fragments",
                                    name = name,
                                    frag = frag_spec,
                                    next = quoted_tt_to_string(next_token),
                                    may_be = may_be
                                ),
                            );
                            err.span_label(
                                sp,
                                format!("not allowed after `{}` fragments", frag_spec),
                            );
                            let msg = "allowed there are: ";
                            match possible {
                                &[] => {}
                                &[t] => {
                                    err.note(&format!(
                                        "only {} is allowed after `{}` fragments",
                                        t, frag_spec,
                                    ));
                                }
                                ts => {
                                    err.note(&format!(
                                        "{}{} or {}",
                                        msg,
                                        ts[..ts.len() - 1]
                                            .iter()
                                            .map(|s| *s)
                                            .collect::<Vec<_>>()
                                            .join(", "),
                                        ts[ts.len() - 1],
                                    ));
                                }
                            }
                            err.emit();
                        }
                    }
                }
            }
        }
    }
    last
}

fn token_can_be_followed_by_any(tok: &quoted::TokenTree) -> bool {
    if let quoted::TokenTree::MetaVarDecl(_, _, frag_spec) = *tok {
        frag_can_be_followed_by_any(frag_spec.name)
    } else {
        // (Non NT's can always be followed by anthing in matchers.)
        true
    }
}

/// Returns `true` if a fragment of type `frag` can be followed by any sort of
/// token. We use this (among other things) as a useful approximation
/// for when `frag` can be followed by a repetition like `$(...)*` or
/// `$(...)+`. In general, these can be a bit tricky to reason about,
/// so we adopt a conservative position that says that any fragment
/// specifier which consumes at most one token tree can be followed by
/// a fragment specifier (indeed, these fragments can be followed by
/// ANYTHING without fear of future compatibility hazards).
fn frag_can_be_followed_by_any(frag: Symbol) -> bool {
    match frag {
        sym::item     | // always terminated by `}` or `;`
        sym::block    | // exactly one token tree
        sym::ident    | // exactly one token tree
        sym::literal  | // exactly one token tree
        sym::meta     | // exactly one token tree
        sym::lifetime | // exactly one token tree
        sym::tt =>   // exactly one token tree
            true,

        _ =>
            false,
    }
}

enum IsInFollow {
    Yes,
    No(&'static [&'static str]),
    Invalid(String, &'static str),
}

/// Returns `true` if `frag` can legally be followed by the token `tok`. For
/// fragments that can consume an unbounded number of tokens, `tok`
/// must be within a well-defined follow set. This is intended to
/// guarantee future compatibility: for example, without this rule, if
/// we expanded `expr` to include a new binary operator, we might
/// break macros that were relying on that binary operator as a
/// separator.
// when changing this do not forget to update doc/book/macros.md!
fn is_in_follow(tok: &quoted::TokenTree, frag: Symbol) -> IsInFollow {
    use quoted::TokenTree;

    if let TokenTree::Token(Token { kind: token::CloseDelim(_), .. }) = *tok {
        // closing a token tree can never be matched by any fragment;
        // iow, we always require that `(` and `)` match, etc.
        IsInFollow::Yes
    } else {
        match frag {
            sym::item => {
                // since items *must* be followed by either a `;` or a `}`, we can
                // accept anything after them
                IsInFollow::Yes
            }
            sym::block => {
                // anything can follow block, the braces provide an easy boundary to
                // maintain
                IsInFollow::Yes
            }
            sym::stmt | sym::expr => {
                const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"];
                match tok {
                    TokenTree::Token(token) => match token.kind {
                        FatArrow | Comma | Semi => IsInFollow::Yes,
                        _ => IsInFollow::No(TOKENS),
                    },
                    _ => IsInFollow::No(TOKENS),
                }
            }
            sym::pat => {
                const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"];
                match tok {
                    TokenTree::Token(token) => match token.kind {
                        FatArrow | Comma | Eq | BinOp(token::Or) => IsInFollow::Yes,
                        Ident(name, false) if name == kw::If || name == kw::In => IsInFollow::Yes,
                        _ => IsInFollow::No(TOKENS),
                    },
                    _ => IsInFollow::No(TOKENS),
                }
            }
            sym::path | sym::ty => {
                const TOKENS: &[&str] = &[
                    "`{`", "`[`", "`=>`", "`,`", "`>`", "`=`", "`:`", "`;`", "`|`", "`as`",
                    "`where`",
                ];
                match tok {
                    TokenTree::Token(token) => match token.kind {
                        OpenDelim(token::DelimToken::Brace)
                        | OpenDelim(token::DelimToken::Bracket)
                        | Comma
                        | FatArrow
                        | Colon
                        | Eq
                        | Gt
                        | BinOp(token::Shr)
                        | Semi
                        | BinOp(token::Or) => IsInFollow::Yes,
                        Ident(name, false) if name == kw::As || name == kw::Where => {
                            IsInFollow::Yes
                        }
                        _ => IsInFollow::No(TOKENS),
                    },
                    TokenTree::MetaVarDecl(_, _, frag) if frag.name == sym::block => {
                        IsInFollow::Yes
                    }
                    _ => IsInFollow::No(TOKENS),
                }
            }
            sym::ident | sym::lifetime => {
                // being a single token, idents and lifetimes are harmless
                IsInFollow::Yes
            }
            sym::literal => {
                // literals may be of a single token, or two tokens (negative numbers)
                IsInFollow::Yes
            }
            sym::meta | sym::tt => {
                // being either a single token or a delimited sequence, tt is
                // harmless
                IsInFollow::Yes
            }
            sym::vis => {
                // Explicitly disallow `priv`, on the off chance it comes back.
                const TOKENS: &[&str] = &["`,`", "an ident", "a type"];
                match tok {
                    TokenTree::Token(token) => match token.kind {
                        Comma => IsInFollow::Yes,
                        Ident(name, is_raw) if is_raw || name != kw::Priv => IsInFollow::Yes,
                        _ => {
                            if token.can_begin_type() {
                                IsInFollow::Yes
                            } else {
                                IsInFollow::No(TOKENS)
                            }
                        }
                    },
                    TokenTree::MetaVarDecl(_, _, frag)
                        if frag.name == sym::ident
                            || frag.name == sym::ty
                            || frag.name == sym::path =>
                    {
                        IsInFollow::Yes
                    }
                    _ => IsInFollow::No(TOKENS),
                }
            }
            kw::Invalid => IsInFollow::Yes,
            _ => IsInFollow::Invalid(
                format!("invalid fragment specifier `{}`", frag),
                VALID_FRAGMENT_NAMES_MSG,
            ),
        }
    }
}

fn has_legal_fragment_specifier(
    sess: &ParseSess,
    features: &Features,
    attrs: &[ast::Attribute],
    tok: &quoted::TokenTree,
) -> Result<(), String> {
    debug!("has_legal_fragment_specifier({:?})", tok);
    if let quoted::TokenTree::MetaVarDecl(_, _, ref frag_spec) = *tok {
        let frag_span = tok.span();
        if !is_legal_fragment_specifier(sess, features, attrs, frag_spec.name, frag_span) {
            return Err(frag_spec.to_string());
        }
    }
    Ok(())
}

fn is_legal_fragment_specifier(
    _sess: &ParseSess,
    _features: &Features,
    _attrs: &[ast::Attribute],
    frag_name: Symbol,
    _frag_span: Span,
) -> bool {
    /*
     * If new fragment specifiers are invented in nightly, `_sess`,
     * `_features`, `_attrs`, and `_frag_span` will be useful here
     * for checking against feature gates. See past versions of
     * this function.
     */
    match frag_name {
        sym::item
        | sym::block
        | sym::stmt
        | sym::expr
        | sym::pat
        | sym::lifetime
        | sym::path
        | sym::ty
        | sym::ident
        | sym::meta
        | sym::tt
        | sym::vis
        | sym::literal
        | kw::Invalid => true,
        _ => false,
    }
}

fn quoted_tt_to_string(tt: &quoted::TokenTree) -> String {
    match *tt {
        quoted::TokenTree::Token(ref token) => crate::print::pprust::token_to_string(&token),
        quoted::TokenTree::MetaVar(_, name) => format!("${}", name),
        quoted::TokenTree::MetaVarDecl(_, name, kind) => format!("${}:{}", name, kind),
        _ => panic!(
            "unexpected quoted::TokenTree::{{Sequence or Delimited}} \
             in follow set checker"
        ),
    }
}
