diff --git a/maud_macros/src/parse.rs b/maud_macros/src/parse.rs index b33942f..4299647 100644 --- a/maud_macros/src/parse.rs +++ b/maud_macros/src/parse.rs @@ -95,9 +95,28 @@ impl Parser { /// Parses and renders multiple blocks of markup. fn markups(&mut self, builder: &mut Builder) -> ParseResult<()> { loop { - match self.peek() { + match self.peek2() { None => return Ok(()), - Some(TokenTree { kind: TokenNode::Op(';', _), .. }) => self.advance(), + Some((TokenTree { kind: TokenNode::Op(';', _), .. }, _)) => self.advance(), + Some(( + TokenTree { kind: TokenNode::Op('@', _), .. }, + Some(TokenTree { kind: TokenNode::Term(term), span }), + )) if term.as_str() == "let" => { + // When emitting a `@let`, wrap the rest of the block in a + // new block to avoid scoping issues + let keyword = TokenTree { kind: TokenNode::Term(term), span }; + self.advance2(); + builder.push({ + let mut builder = self.builder(); + builder.push(keyword); + self.let_expr(&mut builder)?; + self.markups(&mut builder)?; + TokenTree { + kind: TokenNode::Group(Delimiter::Brace, builder.build()), + span, + } + }); + }, _ => self.markup(builder)?, } } @@ -127,7 +146,7 @@ impl Parser { "while" => self.while_expr(builder)?, "for" => self.for_expr(builder)?, "match" => self.match_expr(builder)?, - "let" => self.let_expr(builder)?, + "let" => return self.error(format!("@let only works inside a block")), other => return self.error(format!("unknown keyword `@{}`", other)), } }, @@ -145,10 +164,9 @@ impl Parser { builder.splice(expr); } // Block - TokenTree { kind: TokenNode::Group(Delimiter::Brace, block), span } => { + TokenTree { kind: TokenNode::Group(Delimiter::Brace, block), .. } => { self.advance(); - let block = self.block(block, span)?; - builder.push(block); + self.with_input(block).markups(builder)?; }, // ??? _ => return self.error("invalid syntax"),