Implement for expressions

This commit is contained in:
Chris Wong 2015-03-14 21:08:08 +13:00
parent 4da1e369cd
commit a530d73d25
3 changed files with 59 additions and 1 deletions
maud_macros

View file

@ -102,6 +102,11 @@ impl<'cx, 's, 'i> Parser<'cx, 's, 'i> {
self.shift(2);
self.if_expr(sp);
},
// For
[dollar!(), ident!(sp, name), ..] if name.as_str() == "for" => {
self.shift(2);
self.for_expr(sp);
},
// Splice
[ref tt @ dollar!(), dollar!(), ..] => {
self.shift(2);
@ -192,6 +197,38 @@ impl<'cx, 's, 'i> Parser<'cx, 's, 'i> {
self.render.emit_if(if_cond, if_body, else_body);
}
fn for_expr(&mut self, sp: Span) {
let mut pattern = vec![];
loop { match self.input {
[ident!(in_), ..] if in_.as_str() == "in" => {
self.shift(1);
break;
},
[ref tt, ..] => {
self.shift(1);
pattern.push(tt.clone());
},
_ => self.render.cx.span_fatal(sp, "invalid $for"),
}}
let pattern = self.new_rust_parser(pattern).parse_pat();
let mut iterable = vec![];
let body;
loop { match self.input {
[TtDelimited(sp, ref d), ..] if d.delim == DelimToken::Brace => {
self.shift(1);
body = self.block(sp, &d.tts);
break;
},
[ref tt, ..] => {
self.shift(1);
iterable.push(tt.clone());
},
_ => self.render.cx.span_fatal(sp, "invalid $for"),
}}
let iterable = self.new_rust_parser(iterable).parse_expr();
self.render.emit_for(pattern, iterable, body);
}
fn splice(&mut self, sp: Span) -> P<Expr> {
let mut tts = vec![];
// First, munch a single token tree

View file

@ -1,4 +1,4 @@
use syntax::ast::{Expr, Ident, Stmt};
use syntax::ast::{Expr, Ident, Pat, Stmt};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
@ -135,4 +135,9 @@ impl<'cx, 's> Renderer<'cx, 's> {
};
self.stmts.push(stmt);
}
pub fn emit_for(&mut self, pattern: P<Pat>, iterable: P<Expr>, body: Vec<P<Stmt>>) {
let stmt = quote_stmt!(self.cx, for $pattern in $iterable { $body });
self.stmts.push(stmt);
}
}

View file

@ -201,4 +201,20 @@ mod control {
assert_eq!(s, name);
}
}
#[test]
fn for_expr() {
let ponies = ["Apple Bloom", "Scootaloo", "Sweetie Belle"];
let s = html! {
ul $for pony in &ponies {
li $pony
}
}.to_string();
assert_eq!(s, concat!(
"<ul>",
"<li>Apple Bloom</li>",
"<li>Scootaloo</li>",
"<li>Sweetie Belle</li>",
"</ul>"));
}
}