about summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/base.rs23
-rw-r--r--src/libsyntax/ext/source_util.rs35
2 files changed, 37 insertions, 21 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index e641abbfeee..bd6df9cb497 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -675,26 +675,19 @@ pub fn check_zero_tts(cx: &ExtCtxt,
 
 /// Extract the string literal from the first token of `tts`. If this
 /// is not a string literal, emit an error and return None.
-pub fn get_single_str_from_tts(cx: &ExtCtxt,
+pub fn get_single_str_from_tts(cx: &mut ExtCtxt,
                                sp: Span,
                                tts: &[ast::TokenTree],
                                name: &str)
                                -> Option<String> {
-    if tts.len() != 1 {
-        cx.span_err(sp, format!("{} takes 1 argument.", name).as_slice());
-    } else {
-        match tts[0] {
-            ast::TtToken(_, token::LitStr(ident)) => return Some(parse::str_lit(ident.as_str())),
-            ast::TtToken(_, token::LitStrRaw(ident, _)) => {
-                return Some(parse::raw_str_lit(ident.as_str()))
-            }
-            _ => {
-                cx.span_err(sp,
-                            format!("{} requires a string.", name).as_slice())
-            }
-        }
+    let mut p = cx.new_parser_from_tts(tts);
+    let ret = cx.expander().fold_expr(p.parse_expr());
+    if p.token != token::Eof {
+        cx.span_err(sp, format!("{} takes 1 argument", name).as_slice());
     }
-    None
+    expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| {
+        s.get().to_string()
+    })
 }
 
 /// Extract comma-separated expressions from `tts`. If there is a
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index 41967b0680c..f1923084409 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -9,14 +9,16 @@
 // except according to those terms.
 
 use ast;
-use codemap;
 use codemap::{Pos, Span};
+use codemap;
 use ext::base::*;
 use ext::base;
 use ext::build::AstBuilder;
-use parse;
 use parse::token;
+use parse;
 use print::pprust;
+use ptr::P;
+use util::small_vector::SmallVector;
 
 use std::io::File;
 use std::rc::Rc;
@@ -82,14 +84,14 @@ pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 /// include! : parse the given file as an expr
 /// This is generally a bad idea because it's going to behave
 /// unhygienically.
-pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                      -> Box<base::MacResult+'static> {
+pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+                           -> Box<base::MacResult+'cx> {
     let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
         Some(f) => f,
         None => return DummyResult::expr(sp),
     };
     // The file will be added to the code map by the parser
-    let mut p =
+    let p =
         parse::new_sub_parser_from_file(cx.parse_sess(),
                                         cx.cfg(),
                                         &res_rel_file(cx,
@@ -98,7 +100,28 @@ pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                                         true,
                                         None,
                                         sp);
-    base::MacExpr::new(p.parse_expr())
+
+    struct ExpandResult<'a> {
+        p: parse::parser::Parser<'a>,
+    }
+    impl<'a> base::MacResult for ExpandResult<'a> {
+        fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
+            Some(self.p.parse_expr())
+        }
+        fn make_items(mut self: Box<ExpandResult<'a>>)
+                      -> Option<SmallVector<P<ast::Item>>> {
+            let mut ret = SmallVector::zero();
+            loop {
+                match self.p.parse_item_with_outer_attributes() {
+                    Some(item) => ret.push(item),
+                    None => break
+                }
+            }
+            Some(ret)
+        }
+    }
+
+    box ExpandResult { p: p }
 }
 
 // include_str! : read the given file, insert it as a literal string expr