/// Converts a `macro_rules!` invocation into a syntax extension.
Converts a `macro_rules!` invocation into a syntax extension.
Converts a ` macro_rules! ` invocation into a syntax extension .
pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
                    def: &ast::MacroDef) -> SyntaxExtension {
    let lhs_nm =  gensym_ident("lhs");
    let rhs_nm =  gensym_ident("rhs");
    // 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 match_lhs_tok = MatchNt(lhs_nm, token::str_to_ident("tt"));
    let match_rhs_tok = MatchNt(rhs_nm, token::str_to_ident("tt"));
    let argument_gram = vec![
        TokenTree::Sequence(DUMMY_SP, Rc::new(tokenstream::SequenceRepetition {
            tts: vec![
                TokenTree::Token(DUMMY_SP, match_lhs_tok),
                TokenTree::Token(DUMMY_SP, token::FatArrow),
                TokenTree::Token(DUMMY_SP, match_rhs_tok),
            ],
            separator: Some(token::Semi),
            op: tokenstream::KleeneOp::OneOrMore,
            num_captures: 2,
        })),
        // to phase into semicolon-termination instead of semicolon-separation
        TokenTree::Sequence(DUMMY_SP, Rc::new(tokenstream::SequenceRepetition {
            tts: vec![TokenTree::Token(DUMMY_SP, token::Semi)],
            separator: None,
            op: tokenstream::KleeneOp::ZeroOrMore,
            num_captures: 0
        })),
    ];
    // Parse the macro_rules! invocation (`none` is for no interpolations):
    let arg_reader = new_tt_reader(&cx.parse_sess().span_diagnostic,
                                   None,
                                   None,
                                   def.body.clone());
    let argument_map = match parse(cx.parse_sess(),
                                   cx.cfg(),
                                   arg_reader,
                                   &argument_gram) {
        Success(m) => m,
        Failure(sp, str) | Error(sp, str) => {
            panic!(cx.parse_sess().span_diagnostic
                     .span_fatal(sp.substitute_dummy(def.span), &str[..]));
        }
    };
    let mut valid = true;
    // Extract the arguments:
    let lhses = match **argument_map.get(&lhs_nm.name).unwrap() {
        MatchedSeq(ref s, _) => {
            s.iter().map(|m| match **m {
                MatchedNonterminal(NtTT(ref tt)) => {
                    valid &= check_lhs_nt_follows(cx, tt);
                    (**tt).clone()
                }
                _ => cx.span_bug(def.span, "wrong-structured lhs")
            }).collect()
        }
        _ => cx.span_bug(def.span, "wrong-structured lhs")
    };
    let rhses = match **argument_map.get(&rhs_nm.name).unwrap() {
        MatchedSeq(ref s, _) => {
            s.iter().map(|m| match **m {
                MatchedNonterminal(NtTT(ref tt)) => (**tt).clone(),
                _ => cx.span_bug(def.span, "wrong-structured rhs")
            }).collect()
        }
        _ => cx.span_bug(def.span, "wrong-structured rhs")
    };
    for rhs in &rhses {
        valid &= check_rhs(cx, rhs);
    }
    let exp: Box<_> = Box::new(MacroRulesMacroExpander {
        name: def.ident,
        imported_from: def.imported_from,
        lhses: lhses,
        rhses: rhses,
        valid: valid,
    });
    NormalTT(exp, Some(def.span), def.allow_internal_unstable)
}
pub fn compile < ' cx > ( cx : & ' cx mut ExtCtxt , def : & ast :: MacroDef ) -> SyntaxExtension { let lhs_nm = gensym_ident ( " " ) ; let rhs_nm = gensym_ident ( " " ) ; // 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 match_lhs_tok = MatchNt ( lhs_nm , token :: str_to_ident ( " " ) ) ; let match_rhs_tok = MatchNt ( rhs_nm , token :: str_to_ident ( " " ) ) ; let argument_gram = vec ! [ TokenTree Sequence ( DUMMY_SP Rc new ( tokenstream SequenceRepetition { tts vec [ TokenTree Token ( DUMMY_SP match_lhs_tok ) TokenTree Token ( DUMMY_SP token FatArrow ) TokenTree Token ( DUMMY_SP match_rhs_tok ) ] separator Some ( token Semi ) op tokenstream KleeneOp OneOrMore num_captures 2 } ) ) // to phase into semicolon-termination instead of semicolon-separation TokenTree Sequence ( DUMMY_SP Rc new ( tokenstream SequenceRepetition { tts vec [ TokenTree Token ( DUMMY_SP token Semi ) ] separator None op tokenstream KleeneOp ZeroOrMore num_captures 0 } ) ) ] ; // Parse the macro_rules! invocation (`none` is for no interpolations): let arg_reader = new_tt_reader ( & cx . parse_sess ( ) . span_diagnostic , None , None , def . body . clone ( ) ) ; let argument_map = match parse ( cx . parse_sess ( ) , cx . cfg ( ) , arg_reader , & argument_gram ) { Success ( m ) => m , Failure ( sp , str ) | Error ( sp , str ) => { panic ! ( cx parse_sess ( ) span_diagnostic span_fatal ( sp substitute_dummy ( def span ) str [ ] ) ) ; } } ; let mut valid = true ; // Extract the arguments: let lhses = match * * argument_map . get ( & lhs_nm . name ) . unwrap ( ) { MatchedSeq ( ref s , _ ) => { s . iter ( ) . map ( | m | match * * m { MatchedNonterminal ( NtTT ( ref tt ) ) => { valid &= check_lhs_nt_follows ( cx , tt ) ; ( * * tt ) . clone ( ) } _ => cx . span_bug ( def . span , " " ) } ) . collect ( ) } _ => cx . span_bug ( def . span , " " ) } ; let rhses = match * * argument_map . get ( & rhs_nm . name ) . unwrap ( ) { MatchedSeq ( ref s , _ ) => { s . iter ( ) . map ( | m | match * * m { MatchedNonterminal ( NtTT ( ref tt ) ) => ( * * tt ) . clone ( ) , _ => cx . span_bug ( def . span , " " ) } ) . collect ( ) } _ => cx . span_bug ( def . span , " " ) } ; for rhs in & rhses { valid &= check_rhs ( cx , rhs ) ; } let exp : Box < _ > = Box :: new ( MacroRulesMacroExpander { name : def . ident , imported_from : def . imported_from , lhses : lhses , rhses : rhses , valid : valid , } ) ; NormalTT ( exp , Some ( def . span ) , def . allow_internal_unstable ) }
Converts a `macro_rules!` invocation into a syntax extension.
Converts a ` macro_rules! ` invocation into a syntax extension .
cx
&'cx mut ExtCtxt
def
&ast::MacroDef