Epic refactor of doom
* Use `&ExtCtxt` instead of `&mut ExtCtxt` * Take statements vector by value instead of by reference * Make control structures easier to write
This commit is contained in:
parent
9ee1c76e93
commit
110930a558
2 changed files with 49 additions and 50 deletions
|
@ -40,25 +40,25 @@ macro_rules! ident {
|
|||
($sp:pat, $x:pat) => (TtToken($sp, token::Ident($x, token::IdentStyle::Plain)))
|
||||
}
|
||||
|
||||
pub fn parse(cx: &mut ExtCtxt, input: &[TokenTree], sp: Span) -> P<Expr> {
|
||||
Renderer::with(cx, |render| {
|
||||
Parser {
|
||||
in_attr: false,
|
||||
input: input,
|
||||
span: sp,
|
||||
render: render,
|
||||
}.markups();
|
||||
})
|
||||
pub fn parse(cx: &ExtCtxt, input: &[TokenTree], sp: Span) -> P<Expr> {
|
||||
let mut render = Renderer::new(cx);
|
||||
Parser {
|
||||
in_attr: false,
|
||||
input: input,
|
||||
span: sp,
|
||||
render: &mut render,
|
||||
}.markups();
|
||||
render.into_expr()
|
||||
}
|
||||
|
||||
struct Parser<'cx: 'r, 's: 'cx, 'i, 'r, 'o: 'r> {
|
||||
struct Parser<'cx: 'r, 's: 'cx, 'i, 'r> {
|
||||
in_attr: bool,
|
||||
input: &'i [TokenTree],
|
||||
span: Span,
|
||||
render: &'r mut Renderer<'cx, 's, 'o>,
|
||||
render: &'r mut Renderer<'cx, 's>,
|
||||
}
|
||||
|
||||
impl<'cx, 's, 'i, 'r, 'o> Parser<'cx, 's, 'i, 'r, 'o> {
|
||||
impl<'cx, 's, 'i, 'r> Parser<'cx, 's, 'i, 'r> {
|
||||
/// Consume `n` items from the input.
|
||||
fn shift(&mut self, n: usize) {
|
||||
self.input = &self.input[n..];
|
||||
|
@ -221,7 +221,7 @@ impl<'cx, 's, 'i, 'r, 'o> Parser<'cx, 's, 'i, 'r, 'o> {
|
|||
}
|
||||
|
||||
/// Convert a literal to a string.
|
||||
fn lit_to_string(cx: &mut ExtCtxt, lit: Lit, minus: bool) -> Option<String> {
|
||||
fn lit_to_string(cx: &ExtCtxt, lit: Lit, minus: bool) -> Option<String> {
|
||||
use syntax::ast::Lit_::*;
|
||||
let mut result = String::new();
|
||||
if minus {
|
||||
|
|
|
@ -13,27 +13,23 @@ pub enum Escape {
|
|||
Escape,
|
||||
}
|
||||
|
||||
pub struct Renderer<'cx, 's: 'cx, 'o> {
|
||||
pub cx: &'cx mut ExtCtxt<'s>,
|
||||
stmts: &'o mut Vec<P<Stmt>>,
|
||||
pub struct Renderer<'cx, 's: 'cx> {
|
||||
pub cx: &'cx ExtCtxt<'s>,
|
||||
stmts: Vec<P<Stmt>>,
|
||||
w: Ident,
|
||||
}
|
||||
|
||||
impl<'cx, 's, 'o> Renderer<'cx, 's, 'o> {
|
||||
pub fn with<F>(cx: &'cx mut ExtCtxt<'s>, f: F) -> P<Expr> where
|
||||
F: for<'o_> FnOnce(&mut Renderer<'cx, 's, 'o_>)
|
||||
{
|
||||
let mut stmts = vec![];
|
||||
let w = Ident::new(token::intern("w"));
|
||||
let cx = {
|
||||
let mut render = Renderer {
|
||||
cx: cx,
|
||||
stmts: &mut stmts,
|
||||
w: w,
|
||||
};
|
||||
f(&mut render);
|
||||
render.cx
|
||||
};
|
||||
impl<'cx, 's> Renderer<'cx, 's> {
|
||||
pub fn new(cx: &'cx ExtCtxt<'s>) -> Renderer<'cx, 's> {
|
||||
Renderer {
|
||||
cx: cx,
|
||||
stmts: vec![],
|
||||
w: Ident::new(token::intern("w")),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_expr(self) -> P<Expr> {
|
||||
let Renderer { cx, stmts, w } = self;
|
||||
quote_expr!(cx,
|
||||
::maud::rt::make_markup(|&: $w: &mut ::std::fmt::Writer| -> Result<(), ::std::fmt::Error> {
|
||||
$stmts
|
||||
|
@ -41,22 +37,29 @@ impl<'cx, 's, 'o> Renderer<'cx, 's, 'o> {
|
|||
}))
|
||||
}
|
||||
|
||||
/// Push an expression statement, also wrapping it with `try!`.
|
||||
fn push(&mut self, expr: P<Expr>) {
|
||||
let stmt = self.make_stmt(expr);
|
||||
self.stmts.push(stmt);
|
||||
fn make_stmts<F>(&self, f: F) -> Vec<P<Stmt>> where
|
||||
F: FnOnce(&mut Renderer<'cx, 's>)
|
||||
{
|
||||
let mut render = Renderer {
|
||||
cx: self.cx,
|
||||
stmts: vec![],
|
||||
w: self.w,
|
||||
};
|
||||
f(&mut render);
|
||||
render.stmts
|
||||
}
|
||||
|
||||
/// Create an expression statement, also wrapping it with `try!`.
|
||||
fn make_stmt(&mut self, expr: P<Expr>) -> P<Stmt> {
|
||||
self.cx.stmt_expr(self.cx.expr_try(expr.span, expr))
|
||||
/// Push an expression statement, also wrapping it with `try!`.
|
||||
fn push_try(&mut self, expr: P<Expr>) {
|
||||
let stmt = self.cx.stmt_expr(self.cx.expr_try(expr.span, expr));
|
||||
self.stmts.push(stmt);
|
||||
}
|
||||
|
||||
/// Append a literal pre-escaped string.
|
||||
fn write(&mut self, s: &str) {
|
||||
let w = self.w;
|
||||
let expr = quote_expr!(self.cx, $w.write_str($s));
|
||||
self.push(expr);
|
||||
self.push_try(expr);
|
||||
}
|
||||
|
||||
/// Append a literal string, with the specified escaping method.
|
||||
|
@ -80,7 +83,7 @@ impl<'cx, 's, 'o> Renderer<'cx, 's, 'o> {
|
|||
&mut ::maud::rt::Escaper { inner: $w },
|
||||
$expr)),
|
||||
};
|
||||
self.push(expr);
|
||||
self.push_try(expr);
|
||||
}
|
||||
|
||||
pub fn element_open_start(&mut self, name: &str) {
|
||||
|
@ -100,21 +103,17 @@ impl<'cx, 's, 'o> Renderer<'cx, 's, 'o> {
|
|||
}
|
||||
|
||||
pub fn attribute_empty_if(&mut self, name: &str, expr: P<Expr>) {
|
||||
let s: String = [" ", name].concat();
|
||||
let s = &s[];
|
||||
let w = self.w;
|
||||
// Silence "unnecessary parentheses" warnings
|
||||
let expr = match expr.node {
|
||||
ExprParen(ref inner) => inner.clone(),
|
||||
_ => expr.clone(),
|
||||
};
|
||||
let expr = quote_expr!(self.cx,
|
||||
if $expr {
|
||||
$w.write_str($s)
|
||||
} else {
|
||||
Ok(())
|
||||
});
|
||||
self.push(expr);
|
||||
let stmts = self.make_stmts(|r| {
|
||||
r.write(" ");
|
||||
r.write(name);
|
||||
});
|
||||
let stmt = quote_stmt!(self.cx, if $expr { $stmts });
|
||||
self.stmts.push(stmt);
|
||||
}
|
||||
|
||||
pub fn attribute_end(&mut self) {
|
||||
|
|
Loading…
Add table
Reference in a new issue