about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorPaul Stansifer <paul.stansifer@gmail.com>2012-06-25 15:04:50 -0700
committerPaul Stansifer <paul.stansifer@gmail.com>2012-06-25 18:01:37 -0700
commit4df2654f828b1346dab75166ddca7222666b5939 (patch)
tree584c11a146e698538b8b6da99eb980404c8bd90e /src/libsyntax
parent4f104954a67ad736244ce212467290c836394fad (diff)
downloadrust-4df2654f828b1346dab75166ddca7222666b5939.tar.gz
rust-4df2654f828b1346dab75166ddca7222666b5939.zip
Make it possible to make built-in tt syntax extensions
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/base.rs10
-rw-r--r--src/libsyntax/ext/expand.rs36
-rw-r--r--src/libsyntax/parse/parser.rs13
3 files changed, 53 insertions, 6 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index e39f9745249..6c93dbcd7ef 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -6,19 +6,23 @@ import std::map::str_hash;
 
 type syntax_expander_ =
     fn@(ext_ctxt, span, ast::mac_arg, ast::mac_body) -> @ast::expr;
-type syntax_expander = {
-    expander: syntax_expander_,
-    span: option<span>};
+type syntax_expander = {expander: syntax_expander_, span: option<span>};
+
 type macro_def = {ident: ast::ident, ext: syntax_extension};
 type macro_definer =
     fn@(ext_ctxt, span, ast::mac_arg, ast::mac_body) -> macro_def;
 type item_decorator =
     fn@(ext_ctxt, span, ast::meta_item, [@ast::item]) -> [@ast::item];
 
+type syntax_expander_tt = {expander: syntax_expander_tt_, span: option<span>};
+type syntax_expander_tt_ = fn@(ext_ctxt, span, ast::token_tree) -> @ast::expr;
+
 enum syntax_extension {
     normal(syntax_expander),
     macro_defining(macro_definer),
     item_decorator(item_decorator),
+
+    normal_tt(syntax_expander_tt)
 }
 
 // A temporary hard-coded map of methods for expanding syntax extension
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 26313e97494..d7bb7835822 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -47,6 +47,39 @@ fn expand_expr(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
                     exts.insert(*named_extension.ident, named_extension.ext);
                     (ast::expr_rec([], none), s)
                   }
+                  some(normal_tt(_)) {
+                    cx.span_fatal(pth.span,
+                                  #fmt["this tt-style macro should be \
+                                        invoked '%s!{...}'", *extname])
+                  }
+                }
+              }
+              mac_invoc_tt(pth, tt) {
+                assert (vec::len(pth.idents) > 0u);
+                let extname = pth.idents[0];
+                alt exts.find(*extname) {
+                  none {
+                    cx.span_fatal(pth.span,
+                                  #fmt["macro undefined: '%s'", *extname])
+                  }
+                  some(normal_tt({expander: exp, span: exp_sp})) {
+                    let expanded = exp(cx, pth.span, tt);
+
+                    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,
+                                  #fmt["'%s' is not a tt-style macro",
+                                       *extname])
+                  }
+
                 }
               }
               _ { cx.span_bug(mac.span, "naked syntactic bit") }
@@ -75,7 +108,8 @@ fn expand_mod_items(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
               ast::meta_list(n, _) { n }
             };
             alt exts.find(*mname) {
-              none | some(normal(_)) | some(macro_defining(_)) {
+              none | some(normal(_)) | some(macro_defining(_))
+              | some(normal_tt(_)) {
                 items
               }
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 02d08ab5ae8..13b68b2ce70 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -883,8 +883,17 @@ class parser {
             is_ident(self.token) && !self.is_keyword("true") &&
             !self.is_keyword("false") {
             let pth = self.parse_path_with_tps(true);
-            hi = pth.span.hi;
-            ex = expr_path(pth);
+
+            /* `!`, as an operator, is prefix, so we know this isn't that */
+            if self.token == token::NOT {
+                self.bump();
+                let m_body = self.parse_token_tree();
+                let hi = self.span.hi;
+                ret pexpr(self.mk_mac_expr(lo, hi, mac_invoc_tt(pth,m_body)));
+            } else {
+                hi = pth.span.hi;
+                ex = expr_path(pth);
+            }
         } else {
             let lit = self.parse_lit();
             hi = lit.span.hi;