Implement if/else
This commit is contained in:
parent
bc305caf17
commit
ed28f1c1bc
2 changed files with 62 additions and 2 deletions
|
@ -4,7 +4,7 @@ use syntax::codemap::Span;
|
||||||
use syntax::ext::base::ExtCtxt;
|
use syntax::ext::base::ExtCtxt;
|
||||||
use syntax::parse;
|
use syntax::parse;
|
||||||
use syntax::parse::parser::Parser as RustParser;
|
use syntax::parse::parser::Parser as RustParser;
|
||||||
use syntax::parse::token;
|
use syntax::parse::token::{self, DelimToken};
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
|
|
||||||
use super::render::{Escape, Renderer};
|
use super::render::{Escape, Renderer};
|
||||||
|
@ -97,6 +97,11 @@ impl<'cx, 's, 'i> Parser<'cx, 's, 'i> {
|
||||||
self.shift(1);
|
self.shift(1);
|
||||||
self.literal(tt, false)
|
self.literal(tt, false)
|
||||||
},
|
},
|
||||||
|
// If
|
||||||
|
[dollar!(), ident!(sp, name), ..] if name.as_str() == "if" => {
|
||||||
|
self.shift(2);
|
||||||
|
self.if_expr(sp);
|
||||||
|
},
|
||||||
// Splice
|
// Splice
|
||||||
[ref tt @ dollar!(), dollar!(), ..] => {
|
[ref tt @ dollar!(), dollar!(), ..] => {
|
||||||
self.shift(2);
|
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> {
|
fn splice(&mut self, sp: Span) -> P<Expr> {
|
||||||
let mut tts = vec![];
|
let mut tts = vec![];
|
||||||
// First, munch a single token tree
|
// 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());
|
self.render.attribute_start(name.as_str());
|
||||||
{
|
{
|
||||||
// Parse a value under an attribute context
|
// 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);
|
mem::swap(&mut self.in_attr, &mut in_attr);
|
||||||
self.markup();
|
self.markup();
|
||||||
mem::swap(&mut self.in_attr, &mut in_attr);
|
mem::swap(&mut self.in_attr, &mut in_attr);
|
||||||
|
|
|
@ -182,3 +182,23 @@ fn issue_1() {
|
||||||
let markup = html! { "Test" };
|
let markup = html! { "Test" };
|
||||||
let _ = markup.to_string();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue