diff options
Diffstat (limited to 'src/libsyntax/ext')
| -rw-r--r-- | src/libsyntax/ext/base.rs | 23 | ||||
| -rw-r--r-- | src/libsyntax/ext/source_util.rs | 35 |
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 |
