From f4ef0dc3d344bd704258ac4d395709f012b41bde Mon Sep 17 00:00:00 2001 From: Paul Stansifer Date: Thu, 12 Jul 2012 17:59:59 -0700 Subject: [PATCH] Allow old-style syntax extensions to be called with new syntax. --- src/libsyntax/ext/base.rs | 37 +++++++++++++++++++++++++++ src/libsyntax/ext/expand.rs | 13 ++++++++++ src/libsyntax/ext/tt/earley_parser.rs | 10 ++++++++ 3 files changed, 60 insertions(+) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index f6b15ff19d9d..79eb71969ff8 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -244,6 +244,43 @@ fn get_mac_body(cx: ext_ctxt, sp: span, args: ast::mac_body) } } +fn tt_args_to_original_flavor(cx: ext_ctxt, sp: span, arg: ~[ast::token_tree]) + -> ast::mac_arg { + import ast::{matcher, matcher_, mtc_tok, mtc_rep, mtc_bb}; + import parse::lexer::{new_tt_reader, tt_reader_as_reader, reader}; + import tt::earley_parser::{parse_or_else, seq, leaf}; + + // these spans won't matter, anyways + fn ms(m: matcher_) -> matcher { + {node: m, span: {lo: 0u, hi: 0u, expn_info: none}} + } + + let argument_gram = ~[ms(mtc_rep(~[ + ms(mtc_bb(@"arg",@"expr", 0u)) + ], some(parse::token::COMMA), true))]; + + let arg_reader = new_tt_reader(cx.parse_sess().span_diagnostic, + cx.parse_sess().interner, none, arg); + let args = + alt parse_or_else(cx.parse_sess(), cx.cfg(), arg_reader as reader, + argument_gram).get(@"arg") { + @seq(s, _) { + do s.map() |lf| { + alt lf { + @leaf(parse::token::w_expr(arg)) { + arg /* whew! list of exprs, here we come! */ + } + _ { fail "badly-structured parse result"; } + } + } + } + _ { fail "badly-structured parse result"; } + }; + + ret some(@{id: parse::next_node_id(cx.parse_sess()), + node: ast::expr_vec(args, ast::m_imm), span: sp}); +} + // // Local Variables: // mode: rust diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 2a41afc97430..c470daaf0228 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -81,7 +81,20 @@ fn expand_expr(exts: hashmap<~str, syntax_extension>, cx: ext_ctxt, cx.bt_pop(); (fully_expanded, s) + } + some(normal({expander: exp, span: exp_sp})) { + //convert the new-style invoc for the old-style macro + let arg = base::tt_args_to_original_flavor(cx, pth.span, + tts); + let expanded = exp(cx, mac.span, arg, none); + cx.bt_push(expanded_from({call_site: s, + callie: {name: *extname, span: exp_sp}})); + //keep going, outside-in + let fully_expanded = fld.fold_expr(expanded).node; + cx.bt_pop(); + + (fully_expanded, s) } _ { cx.span_fatal(pth.span, diff --git a/src/libsyntax/ext/tt/earley_parser.rs b/src/libsyntax/ext/tt/earley_parser.rs index 152b92a4b53b..aac2bb2ddf15 100644 --- a/src/libsyntax/ext/tt/earley_parser.rs +++ b/src/libsyntax/ext/tt/earley_parser.rs @@ -101,6 +101,16 @@ enum parse_result { failure(codemap::span, ~str) } +fn parse_or_else(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, + ms: ~[matcher]) -> hashmap { + alt parse(sess, cfg, rdr, ms) { + success(m) { m } + failure(sp, str) { + sess.span_diagnostic.span_fatal(sp, str); + } + } +} + fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher]) -> parse_result { let mut cur_eis = ~[];