about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorPaul Stansifer <paul.stansifer@gmail.com>2012-11-08 23:12:45 -0500
committerGraydon Hoare <graydon@mozilla.com>2012-11-29 12:09:10 -0800
commitfca52554e7e3b3eff0aaf8686fe4616628577ade (patch)
treecf48e7031d7943d2bc5cd9eafc56c7abd8975a15 /src/libsyntax
parentcafea5ecb69ad9439502426a69e5d297c4525758 (diff)
downloadrust-fca52554e7e3b3eff0aaf8686fe4616628577ade.tar.gz
rust-fca52554e7e3b3eff0aaf8686fe4616628577ade.zip
Make it possible to invoke item macros without passing identifier arguments.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/base.rs15
-rw-r--r--src/libsyntax/ext/expand.rs63
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs4
-rw-r--r--src/libsyntax/parse/parser.rs6
4 files changed, 55 insertions, 33 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 9a642818a53..3701614f137 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -12,7 +12,7 @@ use ast_util::dummy_sp;
 // new-style macro! tt code:
 //
 //    syntax_expander_tt, syntax_expander_tt_item, mac_result,
-//    expr_tt, item_tt
+//    normal_tt, item_tt
 //
 // also note that ast::mac has way too many cases and can probably
 // be trimmed down substantially.
@@ -60,7 +60,10 @@ enum syntax_extension {
     item_decorator(item_decorator),
 
     // Token-tree expanders
-    expr_tt(syntax_expander_tt),
+    normal_tt(syntax_expander_tt),
+
+    // perhaps macro_rules! will lose its odd special identifier argument,
+    // and this can go away also
     item_tt(syntax_expander_tt_item),
 }
 
@@ -69,8 +72,8 @@ enum syntax_extension {
 fn syntax_expander_table() -> HashMap<~str, syntax_extension> {
     fn builtin(f: syntax_expander_) -> syntax_extension
         {normal({expander: f, span: None})}
-    fn builtin_expr_tt(f: syntax_expander_tt_) -> syntax_extension {
-        expr_tt({expander: f, span: None})
+    fn builtin_normal_tt(f: syntax_expander_tt_) -> syntax_extension {
+        normal_tt({expander: f, span: None})
     }
     fn builtin_item_tt(f: syntax_expander_tt_item_) -> syntax_extension {
         item_tt({expander: f, span: None})
@@ -94,7 +97,7 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> {
     syntax_expanders.insert(~"ident_to_str",
                             builtin(ext::ident_to_str::expand_syntax_ext));
     syntax_expanders.insert(~"log_syntax",
-                            builtin_expr_tt(
+                            builtin_normal_tt(
                                 ext::log_syntax::expand_syntax_ext));
     syntax_expanders.insert(~"ast",
                             builtin(ext::qquote::expand_ast));
@@ -139,7 +142,7 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> {
                             builtin_item_tt(ext::pipes::expand_proto));
     syntax_expanders.insert(
         ~"trace_macros",
-        builtin_expr_tt(ext::trace_macros::expand_trace_macros));
+        builtin_normal_tt(ext::trace_macros::expand_trace_macros));
     return syntax_expanders;
 }
 
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 26fbc3be16c..c296938d5d2 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -54,7 +54,7 @@ fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
                     exts.insert(named_extension.name, named_extension.ext);
                     (ast::expr_rec(~[], None), s)
                   }
-                  Some(expr_tt(_)) => {
+                  Some(normal_tt(_)) => {
                     cx.span_fatal(pth.span,
                                   fmt!("this tt-style macro should be \
                                         invoked '%s!(...)'", *extname))
@@ -78,7 +78,7 @@ fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
                     cx.span_fatal(pth.span,
                                   fmt!("macro undefined: '%s'", *extname))
                   }
-                  Some(expr_tt({expander: exp, span: exp_sp})) => {
+                  Some(normal_tt({expander: exp, span: exp_sp})) => {
                     let expanded = match exp(cx, mac.span, tts) {
                       mr_expr(e) => e,
                       mr_expr_or_item(expr_maker,_) => expr_maker(),
@@ -153,7 +153,7 @@ fn expand_mod_items(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
             };
             match exts.find(mname) {
               None | Some(normal(_)) | Some(macro_defining(_))
-              | Some(expr_tt(_)) | Some(item_tt(*)) => items,
+              | Some(normal_tt(_)) | Some(item_tt(*)) => items,
               Some(item_decorator(dec_fn)) => {
                 dec_fn(cx, attr.span, attr.node.value, items)
               }
@@ -200,34 +200,49 @@ fn expand_item_mac(exts: HashMap<~str, syntax_extension>,
     match it.node {
       item_mac({node: mac_invoc_tt(pth, tts), _}) => {
         let extname = cx.parse_sess().interner.get(pth.idents[0]);
-        match exts.find(*extname) {
+        let (expanded, ex_span) = match exts.find(*extname) {
           None => {
             cx.span_fatal(pth.span,
-                          fmt!("macro undefined: '%s'", *extname))
+                          fmt!("macro undefined: '%s!'", *extname))
+          }
+          Some(normal_tt(expand)) => {
+            if it.ident != parse::token::special_idents::invalid {
+                cx.span_fatal(pth.span,
+                              fmt!("macro %s! expects no ident argument, \
+                                    given '%s'", *extname,
+                                   *cx.parse_sess().interner.get(it.ident)));
+            }
+            (expand.expander(cx, it.span, tts), expand.span)
           }
           Some(item_tt(expand)) => {
-            let expanded = expand.expander(cx, it.span, it.ident, tts);
-            cx.bt_push(ExpandedFrom({call_site: it.span,
-                                      callie: {name: *extname,
-                                               span: expand.span}}));
-            let maybe_it = match expanded {
-              mr_item(it) => fld.fold_item(it),
-              mr_expr(_) => cx.span_fatal(pth.span,
-                                         ~"expr macro in item position: " +
-                                         *extname),
-              mr_expr_or_item(_, item_maker) =>
-                option::chain(item_maker(), |i| {fld.fold_item(i)}),
-              mr_def(mdef) => {
-                exts.insert(mdef.name, mdef.ext);
-                None
-              }
-            };
-            cx.bt_pop();
-            return maybe_it
+            if it.ident == parse::token::special_idents::invalid {
+                cx.span_fatal(pth.span,
+                              fmt!("macro %s! expects an ident argument",
+                                   *extname));
+            }
+            (expand.expander(cx, it.span, it.ident, tts), expand.span)
           }
           _ => cx.span_fatal(
               it.span, fmt!("%s! is not legal in item position", *extname))
-        }
+        };
+
+        cx.bt_push(ExpandedFrom({call_site: it.span,
+                                  callie: {name: *extname,
+                                           span: ex_span}}));
+        let maybe_it = match expanded {
+            mr_item(it) => fld.fold_item(it),
+            mr_expr(_) => cx.span_fatal(pth.span,
+                                        ~"expr macro in item position: " +
+                                        *extname),
+            mr_expr_or_item(_, item_maker) =>
+                option::chain(item_maker(), |i| {fld.fold_item(i)}),
+            mr_def(mdef) => {
+                exts.insert(mdef.name, mdef.ext);
+                None
+            }
+        };
+        cx.bt_pop();
+        return maybe_it;
       }
       _ => cx.span_bug(it.span, ~"invalid item macro invocation")
     }
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 7957cde8fdc..012e421718a 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -1,4 +1,4 @@
-use base::{ext_ctxt, mac_result, mr_expr_or_item, mr_def, expr_tt};
+use base::{ext_ctxt, mac_result, mr_expr_or_item, mr_def, normal_tt};
 use codemap::span;
 use ast::{ident, matcher_, matcher, match_tok,
              match_nonterminal, match_seq, tt_delim};
@@ -113,6 +113,6 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident,
 
     return mr_def({
         name: *cx.parse_sess().interner.get(name),
-        ext: expr_tt({expander: exp, span: Some(sp)})
+        ext: normal_tt({expander: exp, span: Some(sp)})
     });
 }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index e521a698da7..638a02775d9 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -3534,7 +3534,11 @@ impl Parser {
             // item macro.
             let pth = self.parse_path_without_tps();
             self.expect(token::NOT);
-            let id = self.parse_ident();
+            let id = if self.token == token::LPAREN {
+                token::special_idents::invalid // no special identifier
+            } else {
+                self.parse_ident()
+            };
             let tts = match self.token {
               token::LPAREN | token::LBRACE => {
                 let ket = token::flip_delimiter(copy self.token);