diff --git a/maud_macros/src/parse.rs b/maud_macros/src/parse.rs index 0df8e59..008d050 100644 --- a/maud_macros/src/parse.rs +++ b/maud_macros/src/parse.rs @@ -146,7 +146,8 @@ impl<'cx, 's, 'i> Parser<'cx, 's, 'i> { } fn if_expr(&mut self, sp: Span) { - let mut cond = vec![]; + // Parse the initial if + let mut cond_tts = vec![]; let if_body; loop { match self.input { [TtDelimited(sp, ref d), ..] if d.delim == DelimToken::Brace => { @@ -156,28 +157,39 @@ impl<'cx, 's, 'i> Parser<'cx, 's, 'i> { }, [ref tt, ..] => { self.shift(1); - cond.push(tt.clone()); + cond_tts.push(tt.clone()); }, - [] => self.render.cx.span_fatal(sp, "expected body for this $if"), + [] => self.render.cx.span_fatal(sp, "expected body for this `if`"), }} - let cond = self.new_rust_parser(cond).parse_expr(); + let if_cond = self.new_rust_parser(cond_tts).parse_expr(); + // Parse the (optional) else let else_body = match self.input { - [dollar!(), ident!(name), ..] if name.as_str() == "else" => { + [dollar!(), ident!(else_), ..] if else_.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) + match self.input { + [ident!(sp, if_), ..] if if_.as_str() == "if" => { + self.shift(1); + let else_body = { + // Parse an if expression, but capture the result + // rather than emitting it right away + let mut render = self.render.fork(); + mem::swap(&mut self.render, &mut render); + self.if_expr(sp); + mem::swap(&mut self.render, &mut render); + render.into_stmts() + }; + Some(else_body) + }, + [TtDelimited(sp, ref d), ..] if d.delim == DelimToken::Brace => { + self.shift(1); + Some(self.block(sp, &d.tts)) + }, + _ => self.render.cx.span_fatal(sp, "invalid syntax"), + } }, _ => None, }; - self.render.emit_if(cond, if_body, else_body); + self.render.emit_if(if_cond, if_body, else_body); } fn splice(&mut self, sp: Span) -> P<Expr> { diff --git a/maud_macros/src/render.rs b/maud_macros/src/render.rs index 8842abc..f415950 100644 --- a/maud_macros/src/render.rs +++ b/maud_macros/src/render.rs @@ -126,12 +126,12 @@ impl<'cx, 's> Renderer<'cx, 's> { self.write(">"); } - pub fn emit_if(&mut self, cond: P<Expr>, if_body: Vec<P<Stmt>>, + pub fn emit_if(&mut self, if_cond: P<Expr>, if_body: Vec<P<Stmt>>, else_body: Option<Vec<P<Stmt>>>) { let stmt = match else_body { - None => quote_stmt!(self.cx, if $cond { $if_body }), + None => quote_stmt!(self.cx, if $if_cond { $if_body }), Some(else_body) => - quote_stmt!(self.cx, if $cond { $if_body } else { $else_body }), + quote_stmt!(self.cx, if $if_cond { $if_body } else { $else_body }), }; self.stmts.push(stmt); } diff --git a/maud_macros/tests/tests.rs b/maud_macros/tests/tests.rs index 56c0f0c..6d03793 100644 --- a/maud_macros/tests/tests.rs +++ b/maud_macros/tests/tests.rs @@ -190,9 +190,9 @@ mod control { let s = html! { $if number == 1 { "one" - } $else $if number == 2 { + } $else if number == 2 { "two" - } $else $if number == 3 { + } $else if number == 3 { "three" } $else { "oh noes"