about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/comp/syntax/ext/base.rs2
-rw-r--r--src/comp/syntax/ext/expand.rs2
-rw-r--r--src/comp/syntax/ext/qquote.rs25
-rw-r--r--src/comp/syntax/parse/parser.rs14
4 files changed, 38 insertions, 5 deletions
diff --git a/src/comp/syntax/ext/base.rs b/src/comp/syntax/ext/base.rs
index 415c6cb5d9b..42ec73077f6 100644
--- a/src/comp/syntax/ext/base.rs
+++ b/src/comp/syntax/ext/base.rs
@@ -30,6 +30,8 @@ fn syntax_expander_table() -> hashmap<str, syntax_extension> {
                             normal(ext::ident_to_str::expand_syntax_ext));
     syntax_expanders.insert("log_syntax",
                             normal(ext::log_syntax::expand_syntax_ext));
+    syntax_expanders.insert("ast",
+                            normal(ext::qquote::expand_ast));
     ret syntax_expanders;
 }
 
diff --git a/src/comp/syntax/ext/expand.rs b/src/comp/syntax/ext/expand.rs
index 18dcdaf1ad1..be1fb2b3e26 100644
--- a/src/comp/syntax/ext/expand.rs
+++ b/src/comp/syntax/ext/expand.rs
@@ -47,7 +47,7 @@ fn expand_expr(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
                 }
               }
               mac_qq(sp, exp) {
-                let r = expand_qquote(cx, sp, exp);
+                let r = expand_qquote(cx, sp, none, exp);
                 // need to keep going, resuls may contain embedded qquote or
                 // macro that need expanding
                 let r2 = fld.fold_expr(r);
diff --git a/src/comp/syntax/ext/qquote.rs b/src/comp/syntax/ext/qquote.rs
index 1b17356ce91..2e2d9f7481e 100644
--- a/src/comp/syntax/ext/qquote.rs
+++ b/src/comp/syntax/ext/qquote.rs
@@ -8,7 +8,8 @@ import syntax::fold::*;
 import syntax::visit::*;
 import syntax::ext::base::*;
 import syntax::ext::build::*;
-import syntax::parse::parser::parse_expr_from_source_str;
+import syntax::parse::parser;
+import syntax::parse::parser::{parse_from_source_str};
 
 import syntax::print::*;
 import std::io::*;
@@ -42,8 +43,26 @@ fn is_space(c: char) -> bool {
     syntax::parse::lexer::is_whitespace(c)
 }
 
-fn expand_qquote(ecx: ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr {
-    let str = codemap::span_to_snippet(sp, ecx.session().parse_sess.cm);
+fn expand_ast(ecx: ext_ctxt, _sp: span, _arg: ast::mac_arg, body: ast::mac_body)
+    -> @ast::expr 
+{
+    let body = get_mac_body(ecx,_sp,body);
+    let str = @codemap::span_to_snippet(body.span, ecx.session().parse_sess.cm);
+    let {node: e, _} = parse_from_source_str(parser::parse_expr, 
+                                             "<anon>", str, 
+                                             ecx.session().opts.cfg, 
+                                             ecx.session().parse_sess);
+    ret expand_qquote(ecx, e.span, some(*str), e);
+}
+
+fn expand_qquote(ecx: ext_ctxt, sp: span, maybe_str: option::t<str>, 
+                 e: @ast::expr) 
+    -> @ast::expr 
+{
+    let str = alt(maybe_str) {
+      some(s) {s}
+      none {codemap::span_to_snippet(sp, ecx.session().parse_sess.cm)}
+    };
     let qcx = gather_anti_quotes(sp.lo, e);
     let cx = qcx;
     let prev = 0u;
diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs
index 291f820df18..7bd354c3a0c 100644
--- a/src/comp/syntax/parse/parser.rs
+++ b/src/comp/syntax/parse/parser.rs
@@ -1013,7 +1013,7 @@ fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr {
             }
             p.bump();
         }
-        let hi = p.last_span.hi;
+        let hi = p.last_span.lo;
         b = some({span: mk_sp(lo,hi)});
     }
     ret mk_mac_expr(p, lo, p.span.hi, ast::mac_invoc(pth, e, b));
@@ -2543,6 +2543,18 @@ fn parse_expr_from_source_str(name: str, source: @str, cfg: ast::crate_cfg,
     ret r;
 }
 
+fn parse_from_source_str<T>(f: fn (p: parser) -> T, 
+                            name: str, source: @str, cfg: ast::crate_cfg,
+                            sess: parse_sess) 
+    -> {node: T, fm: codemap::filemap}
+{
+    let p = new_parser_from_source_str(sess, cfg, name, source);
+    let r = f(p);
+    sess.chpos = p.reader.chpos;
+    sess.byte_pos = sess.byte_pos + p.reader.pos;
+    ret {node: r, fm: option::get(vec::last(sess.cm.files))};
+}
+
 fn parse_crate_from_source_str(name: str, source: @str, cfg: ast::crate_cfg,
                                sess: parse_sess) -> @ast::crate {
     let p = new_parser_from_source_str(sess, cfg, name, source);