Merge pull request from utkarshkukreti/while

Add support for `@while` and `@while let`.
This commit is contained in:
Chris Wong 2016-10-20 12:40:56 +13:00 committed by GitHub
commit 9ff5ff4f2c
3 changed files with 58 additions and 0 deletions

View file

@ -142,6 +142,11 @@ impl<'cx, 'a, 'i> Parser<'cx, 'a, 'i> {
self.shift(2); self.shift(2);
self.if_expr(sp)?; self.if_expr(sp)?;
}, },
// While
[at!(), keyword!(sp, k), ..] if k.is_keyword(keywords::While) => {
self.shift(2);
self.while_expr(sp)?;
},
// For // For
[at!(), keyword!(sp, k), ..] if k.is_keyword(keywords::For) => { [at!(), keyword!(sp, k), ..] if k.is_keyword(keywords::For) => {
self.shift(2); self.shift(2);
@ -248,6 +253,28 @@ impl<'cx, 'a, 'i> Parser<'cx, 'a, 'i> {
Ok(()) 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. /// Parses and renders a `@for` expression.
/// ///
/// The leading `@for` should already be consumed. /// The leading `@for` should already be consumed.

View file

@ -138,6 +138,15 @@ impl<'cx, 'a> Renderer<'cx, 'a> {
self.push(stmt); 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>) { 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(); let stmt = quote_stmt!(self.cx, for $pattern in $iterable { $body }).unwrap();
self.push(stmt); self.push(stmt);

View file

@ -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] #[test]
fn for_expr() { fn for_expr() {
let ponies = ["Apple Bloom", "Scootaloo", "Sweetie Belle"]; let ponies = ["Apple Bloom", "Scootaloo", "Sweetie Belle"];