Flatten substitutions from macro_rules expansion

This fixes a compile error with the test `misc::issue_23`.
This commit is contained in:
Chris Wong 2016-11-16 18:03:23 +13:00
parent 39602a075c
commit 4b81039d2d

View file

@ -5,9 +5,10 @@ use syntax::ext::quote::rt::ToTokens;
use syntax::codemap::Span; use syntax::codemap::Span;
use syntax::errors::{DiagnosticBuilder, FatalError}; use syntax::errors::{DiagnosticBuilder, FatalError};
use syntax::ext::base::ExtCtxt; use syntax::ext::base::ExtCtxt;
use syntax::fold::Folder;
use syntax::parse; use syntax::parse;
use syntax::parse::parser::Parser as RustParser; use syntax::parse::parser::Parser as RustParser;
use syntax::parse::token::{BinOpToken, DelimToken, Token}; use syntax::parse::token::{BinOpToken, DelimToken, Nonterminal, Token};
use syntax::parse::token::keywords; use syntax::parse::token::keywords;
use syntax::print::pprust; use syntax::print::pprust;
use syntax::ptr::P; use syntax::ptr::P;
@ -70,19 +71,35 @@ macro_rules! keyword {
} }
pub fn parse(cx: &ExtCtxt, sp: Span, input: &[TokenTree]) -> PResult<P<Expr>> { pub fn parse(cx: &ExtCtxt, sp: Span, input: &[TokenTree]) -> PResult<P<Expr>> {
let input = FlattenNtFolder.fold_tts(input);
let mut parser = Parser { let mut parser = Parser {
in_attr: false, in_attr: false,
input: input, input: &input,
span: sp, span: sp,
render: Renderer::new(cx), render: Renderer::new(cx),
}; };
parser.markups()?; parser.markups()?;
// Heuristic: the size of the resulting markup tends to correlate with the // Heuristic: the size of the resulting markup tends to correlate with the
// code size of the template itself // code size of the template itself
let size_hint = pprust::tts_to_string(input).len(); let size_hint = pprust::tts_to_string(&input).len();
Ok(parser.into_render().into_expr(size_hint)) Ok(parser.into_render().into_expr(size_hint))
} }
struct FlattenNtFolder;
impl Folder for FlattenNtFolder {
fn fold_tt(&mut self, mut tt: &TokenTree) -> TokenTree {
while let TokenTree::Token(_, Token::Interpolated(ref nt)) = *tt {
if let Nonterminal::NtTT(ref sub_tt) = **nt {
tt = sub_tt;
} else {
break;
}
}
tt.clone()
}
}
struct Parser<'cx, 'a: 'cx, 'i> { struct Parser<'cx, 'a: 'cx, 'i> {
in_attr: bool, in_attr: bool,
input: &'i [TokenTree], input: &'i [TokenTree],