Merge pull request #55 from utkarshkukreti/while
Add support for `@while` and `@while let`.
This commit is contained in:
commit
9ff5ff4f2c
3 changed files with 58 additions and 0 deletions
maud_macros
|
@ -142,6 +142,11 @@ impl<'cx, 'a, 'i> Parser<'cx, 'a, 'i> {
|
|||
self.shift(2);
|
||||
self.if_expr(sp)?;
|
||||
},
|
||||
// While
|
||||
[at!(), keyword!(sp, k), ..] if k.is_keyword(keywords::While) => {
|
||||
self.shift(2);
|
||||
self.while_expr(sp)?;
|
||||
},
|
||||
// For
|
||||
[at!(), keyword!(sp, k), ..] if k.is_keyword(keywords::For) => {
|
||||
self.shift(2);
|
||||
|
@ -248,6 +253,28 @@ impl<'cx, 'a, 'i> Parser<'cx, 'a, 'i> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Parses and renders an `@while` expression.
|
||||
///
|
||||
/// The leading `@while` should already be consumed.
|
||||
fn while_expr(&mut self, sp: Span) -> PResult<()> {
|
||||
let mut cond = vec![];
|
||||
let body;
|
||||
loop { match *self.input {
|
||||
[TokenTree::Delimited(sp, ref d), ..] if d.delim == DelimToken::Brace => {
|
||||
self.shift(1);
|
||||
body = self.block(sp, &d.tts)?;
|
||||
break;
|
||||
},
|
||||
[ref tt, ..] => {
|
||||
self.shift(1);
|
||||
cond.push(tt.clone());
|
||||
},
|
||||
[] => parse_error!(self, sp, "expected body for this @while"),
|
||||
}}
|
||||
self.render.emit_while(cond, body);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Parses and renders a `@for` expression.
|
||||
///
|
||||
/// The leading `@for` should already be consumed.
|
||||
|
|
|
@ -138,6 +138,15 @@ impl<'cx, 'a> Renderer<'cx, 'a> {
|
|||
self.push(stmt);
|
||||
}
|
||||
|
||||
/// Emits an `while` expression.
|
||||
///
|
||||
/// The condition is a token tree (not an expression) so we don't
|
||||
/// need to special-case `while let`.
|
||||
pub fn emit_while(&mut self, cond: Vec<TokenTree>, body: Vec<Stmt>) {
|
||||
let stmt = quote_stmt!(self.cx, while $cond { $body }).unwrap();
|
||||
self.push(stmt);
|
||||
}
|
||||
|
||||
pub fn emit_for(&mut self, pattern: P<Pat>, iterable: P<Expr>, body: Vec<Stmt>) {
|
||||
let stmt = quote_stmt!(self.cx, for $pattern in $iterable { $body }).unwrap();
|
||||
self.push(stmt);
|
||||
|
|
|
@ -35,6 +35,28 @@ fn if_let() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn while_expr() {
|
||||
let mut numbers = (0..3).into_iter().peekable();
|
||||
let s = html! {
|
||||
ul @while numbers.peek().is_some() {
|
||||
li (numbers.next().unwrap())
|
||||
}
|
||||
}.into_string();
|
||||
assert_eq!(s, "<ul><li>0</li><li>1</li><li>2</li></ul>");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn while_let_expr() {
|
||||
let mut numbers = (0..3).into_iter();
|
||||
let s = html! {
|
||||
ul @while let Some(n) = numbers.next() {
|
||||
li (n)
|
||||
}
|
||||
}.into_string();
|
||||
assert_eq!(s, "<ul><li>0</li><li>1</li><li>2</li></ul>");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn for_expr() {
|
||||
let ponies = ["Apple Bloom", "Scootaloo", "Sweetie Belle"];
|
||||
|
|
Loading…
Add table
Reference in a new issue