syntax_expanders.insert(intern("quote_attr"),
builtin_normal_expander(
ext::quote::expand_quote_attr));
+ syntax_expanders.insert(intern("quote_arg"),
+ builtin_normal_expander(
+ ext::quote::expand_quote_arg));
+ syntax_expanders.insert(intern("quote_block"),
+ builtin_normal_expander(
+ ext::quote::expand_quote_block));
+ syntax_expanders.insert(intern("quote_meta_item"),
+ builtin_normal_expander(
+ ext::quote::expand_quote_meta_item));
+ syntax_expanders.insert(intern("quote_path"),
+ builtin_normal_expander(
+ ext::quote::expand_quote_path));
}
syntax_expanders.insert(intern("line"),
}
}
+ impl ToTokens for ast::Arg {
+ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
+ vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtArg(self.clone())))]
+ }
+ }
+
+ impl ToTokens for P<ast::Block> {
+ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
+ vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtBlock(self.clone())))]
+ }
+ }
+
macro_rules! impl_to_tokens_slice {
($t: ty, $sep: expr) => {
impl ToTokens for [$t] {
impl_to_tokens_slice! { ast::Ty, [TokenTree::Token(DUMMY_SP, token::Comma)] }
impl_to_tokens_slice! { P<ast::Item>, [] }
+ impl_to_tokens_slice! { ast::Arg, [TokenTree::Token(DUMMY_SP, token::Comma)] }
impl ToTokens for P<ast::MetaItem> {
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
base::MacEager::expr(expanded)
}
+pub fn expand_quote_arg(cx: &mut ExtCtxt,
+ sp: Span,
+ tts: &[TokenTree])
+ -> Box<base::MacResult+'static> {
+ let expanded = expand_parse_call(cx, sp, "parse_arg_panic", vec!(), tts);
+ base::MacEager::expr(expanded)
+}
+
+pub fn expand_quote_block(cx: &mut ExtCtxt,
+ sp: Span,
+ tts: &[TokenTree])
+ -> Box<base::MacResult+'static> {
+ let expanded = expand_parse_call(cx, sp, "parse_block_panic", vec!(), tts);
+ base::MacEager::expr(expanded)
+}
+
+pub fn expand_quote_meta_item(cx: &mut ExtCtxt,
+ sp: Span,
+ tts: &[TokenTree])
+ -> Box<base::MacResult+'static> {
+ let expanded = expand_parse_call(cx, sp, "parse_meta_item_panic", vec!(), tts);
+ base::MacEager::expr(expanded)
+}
+
+pub fn expand_quote_path(cx: &mut ExtCtxt,
+ sp: Span,
+ tts: &[TokenTree])
+ -> Box<base::MacResult+'static> {
+ let mode = mk_parser_path(cx, sp, "LifetimeAndTypesWithoutColons");
+ let expanded = expand_parse_call(cx, sp, "parse_path_panic", vec!(mode), tts);
+ base::MacEager::expr(expanded)
+}
+
pub fn expand_quote_matcher(cx: &mut ExtCtxt,
sp: Span,
tts: &[TokenTree])
cx.expr_path(cx.path_global(sp, idents))
}
+fn mk_parser_path(cx: &ExtCtxt, sp: Span, name: &str) -> P<ast::Expr> {
+ let idents = vec!(id_ext("syntax"), id_ext("parse"), id_ext("parser"), id_ext(name));
+ cx.expr_path(cx.path_global(sp, idents))
+}
+
fn mk_binop(cx: &ExtCtxt, sp: Span, bop: token::BinOpToken) -> P<ast::Expr> {
let name = match bop {
token::Plus => "Plus",
token::NtGenerics(generics) => token::NtGenerics(fld.fold_generics(generics)),
token::NtWhereClause(where_clause) =>
token::NtWhereClause(fld.fold_where_clause(where_clause)),
+ token::NtArg(arg) => token::NtArg(fld.fold_arg(arg)),
}
}
panictry!(self.parse_attribute(permit_inner))
}
+ pub fn parse_arg_panic(&mut self) -> Arg {
+ panictry!(self.parse_arg())
+ }
+
+ pub fn parse_block_panic(&mut self) -> P<Block> {
+ panictry!(self.parse_block())
+ }
+
+ pub fn parse_meta_item_panic(&mut self) -> P<ast::MetaItem> {
+ panictry!(self.parse_meta_item())
+ }
+
+ pub fn parse_path_panic(&mut self, mode: PathParsingMode) -> ast::Path {
+ panictry!(self.parse_path(mode))
+ }
+
/// Convert a token to a string using self's reader
pub fn token_to_string(token: &token::Token) -> String {
pprust::token_to_string(token)
/// This version of parse arg doesn't necessarily require
/// identifier names.
pub fn parse_arg_general(&mut self, require_name: bool) -> PResult<Arg> {
+ maybe_whole!(no_clone self, NtArg);
+
let pat = if require_name || self.is_named_argument() {
debug!("parse_arg_general parse_pat (require_name:{})",
require_name);
NtMeta(P<ast::MetaItem>),
NtPath(Box<ast::Path>),
NtTT(P<ast::TokenTree>), // needs P'ed to break a circularity
- // These is not exposed to macros, but is used by quasiquote.
+ // These are not exposed to macros, but are used by quasiquote.
NtArm(ast::Arm),
NtImplItem(P<ast::ImplItem>),
NtTraitItem(P<ast::TraitItem>),
NtGenerics(ast::Generics),
NtWhereClause(ast::WhereClause),
+ NtArg(ast::Arg),
}
impl fmt::Debug for Nonterminal {
NtTraitItem(..) => f.pad("NtTraitItem(..)"),
NtGenerics(..) => f.pad("NtGenerics(..)"),
NtWhereClause(..) => f.pad("NtWhereClause(..)"),
+ NtArg(..) => f.pad("NtArg(..)"),
}
}
}
token::NtTraitItem(ref e) => trait_item_to_string(&**e),
token::NtGenerics(ref e) => generics_to_string(&*e),
token::NtWhereClause(ref e) => where_clause_to_string(&*e),
+ token::NtArg(ref e) => arg_to_string(&*e),
}
}
}
pub fn main() {
let ecx = &ParseSess;
- let x = quote_tokens!(ecx, 3); //~ ERROR macro undefined: 'quote_tokens!'
- let x = quote_expr!(ecx, 3); //~ ERROR macro undefined: 'quote_expr!'
- let x = quote_ty!(ecx, 3); //~ ERROR macro undefined: 'quote_ty!'
- let x = quote_method!(ecx, 3); //~ ERROR macro undefined: 'quote_method!'
- let x = quote_item!(ecx, 3); //~ ERROR macro undefined: 'quote_item!'
- let x = quote_pat!(ecx, 3); //~ ERROR macro undefined: 'quote_pat!'
- let x = quote_arm!(ecx, 3); //~ ERROR macro undefined: 'quote_arm!'
- let x = quote_stmt!(ecx, 3); //~ ERROR macro undefined: 'quote_stmt!'
- let x = quote_matcher!(ecx, 3); //~ ERROR macro undefined: 'quote_matcher!'
- let x = quote_attr!(ecx, 3); //~ ERROR macro undefined: 'quote_attr!'
+ let x = quote_tokens!(ecx, 3); //~ ERROR macro undefined: 'quote_tokens!'
+ let x = quote_expr!(ecx, 3); //~ ERROR macro undefined: 'quote_expr!'
+ let x = quote_ty!(ecx, 3); //~ ERROR macro undefined: 'quote_ty!'
+ let x = quote_method!(ecx, 3); //~ ERROR macro undefined: 'quote_method!'
+ let x = quote_item!(ecx, 3); //~ ERROR macro undefined: 'quote_item!'
+ let x = quote_pat!(ecx, 3); //~ ERROR macro undefined: 'quote_pat!'
+ let x = quote_arm!(ecx, 3); //~ ERROR macro undefined: 'quote_arm!'
+ let x = quote_stmt!(ecx, 3); //~ ERROR macro undefined: 'quote_stmt!'
+ let x = quote_matcher!(ecx, 3); //~ ERROR macro undefined: 'quote_matcher!'
+ let x = quote_attr!(ecx, 3); //~ ERROR macro undefined: 'quote_attr!'
+ let x = quote_arg!(ecx, 3); //~ ERROR macro undefined: 'quote_arg!'
+ let x = quote_block!(ecx, 3); //~ ERROR macro undefined: 'quote_block!'
+ let x = quote_meta_item!(ecx, 3); //~ ERROR macro undefined: 'quote_meta_item!'
+ let x = quote_path!(ecx, 3); //~ ERROR macro undefined: 'quote_path!'
}
let attr = quote_attr!(cx, #![cfg(foo = "bar")]);
check!(attribute_to_string, attr, quote_attr!(cx, $attr); r#"#![cfg(foo = "bar")]"#);
+
+ // quote_arg!
+
+ let arg = quote_arg!(cx, foo: i32);
+ check!(arg_to_string, arg, quote_arg!(cx, $arg); "foo: i32");
+
+ let function = quote_item!(cx, fn f($arg) { }).unwrap();
+ check!(item_to_string, function; "fn f(foo: i32) { }");
+
+ let args = vec![arg, quote_arg!(cx, bar: u32)];
+ let args = &args[..];
+ let function = quote_item!(cx, fn f($args) { }).unwrap();
+ check!(item_to_string, function; "fn f(foo: i32, bar: u32) { }");
+
+ // quote_block!
+
+ let block = quote_block!(cx, { $stmt let y = 40u32; });
+ check!(block_to_string, block, *quote_block!(cx, $block); "{ let x = 20u16; let y = 40u32; }");
+
+ let function = quote_item!(cx, fn f() $block).unwrap();
+ check!(item_to_string, function; "fn f() { let x = 20u16; let y = 40u32; }");
+
+ // quote_path!
+
+ let path = quote_path!(cx, ::syntax::ptr::P<MetaItem>);
+ check!(path_to_string, path, quote_path!(cx, $path); "::syntax::ptr::P<MetaItem>");
+
+ let ty = quote_ty!(cx, $path);
+ check!(ty_to_string, ty; "::syntax::ptr::P<MetaItem>");
+
+ // quote_meta_item!
+
+ let meta = quote_meta_item!(cx, cfg(foo = "bar"));
+ check!(meta_item_to_string, meta, *quote_meta_item!(cx, $meta); r#"cfg(foo = "bar")"#);
+
+ let attr = quote_attr!(cx, #![$meta]);
+ check!(attribute_to_string, attr; r#"#![cfg(foo = "bar")]"#);
}