Implement if/else

This commit is contained in:
Chris Wong 2015-02-27 09:27:45 +13:00
parent bc305caf17
commit ed28f1c1bc
2 changed files with 62 additions and 2 deletions
maud_macros

View file

@ -4,7 +4,7 @@ use syntax::codemap::Span;
use syntax::ext::base::ExtCtxt;
use syntax::parse;
use syntax::parse::parser::Parser as RustParser;
use syntax::parse::token;
use syntax::parse::token::{self, DelimToken};
use syntax::ptr::P;
use super::render::{Escape, Renderer};
@ -97,6 +97,11 @@ impl<'cx, 's, 'i> Parser<'cx, 's, 'i> {
self.shift(1);
self.literal(tt, false)
},
// If
[dollar!(), ident!(sp, name), ..] if name.as_str() == "if" => {
self.shift(2);
self.if_expr(sp);
},
// Splice
[ref tt @ dollar!(), dollar!(), ..] => {
self.shift(2);
@ -140,6 +145,41 @@ impl<'cx, 's, 'i> Parser<'cx, 's, 'i> {
}
}
fn if_expr(&mut self, sp: Span) {
let mut cond = vec![];
let if_body;
loop { match self.input {
[TtDelimited(sp, ref d), ..] if d.delim == DelimToken::Brace => {
self.shift(1);
if_body = self.block(sp, &d.tts);
break;
},
[ref tt, ..] => {
self.shift(1);
cond.push(tt.clone());
},
[] => self.render.cx.span_fatal(sp, "expected body for this $if"),
}}
let cond = self.new_rust_parser(cond).parse_expr();
let else_body = match self.input {
[dollar!(), ident!(name), ..] if name.as_str() == "else" => {
self.shift(2);
let else_body = {
// Parse a single markup, but capture the result rather
// than emitting it right away
let mut render = self.render.fork();
mem::swap(&mut self.render, &mut render);
self.markup();
mem::swap(&mut self.render, &mut render);
render.into_stmts()
};
Some(else_body)
},
_ => None,
};
self.render.emit_if(cond, if_body, else_body);
}
fn splice(&mut self, sp: Span) -> P<Expr> {
let mut tts = vec![];
// First, munch a single token tree
@ -194,7 +234,7 @@ impl<'cx, 's, 'i> Parser<'cx, 's, 'i> {
self.render.attribute_start(name.as_str());
{
// Parse a value under an attribute context
let in_attr = true;
let mut in_attr = true;
mem::swap(&mut self.in_attr, &mut in_attr);
self.markup();
mem::swap(&mut self.in_attr, &mut in_attr);

View file

@ -182,3 +182,23 @@ fn issue_1() {
let markup = html! { "Test" };
let _ = markup.to_string();
}
mod control {
#[test]
fn if_expr() {
for (number, &name) in (1..4).zip(["one", "two", "three"].iter()) {
let s = html! {
$if number == 1 {
"one"
} $else $if number == 2 {
"two"
} $else $if number == 3 {
"three"
} $else {
"oh noes"
}
}.to_string();
assert_eq!(s, name);
}
}
}