Fix issue with repeating {{ else }} blocks

Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
Marcel Müller 2026-03-09 16:02:55 +01:00
parent 462355b6f2
commit b0620a00d5
3 changed files with 63 additions and 28 deletions

View file

@ -345,39 +345,67 @@ fn parse_conditional_chain<'input>(
chain.push(if_block); chain.push(if_block);
loop { let content = resume_after_cut(
let (content, end_block): (Vec<_>, _) = repeat_till( inner_conditional_chain,
0.., repeat_till(0.., any, parse_end).map(|((), _)| ()),
parse_ast, )
trace( .parse_next(input)?;
"conditional_chain_else/end",
alt((parse_end, parse_conditional_else)),
),
)
.parse_next(input)?;
chain.push(TemplateAstExpr::ConditionalContent { content }); chain.extend(content.into_iter().flatten());
let is_end = if let TemplateAstExpr::Block { ref expression, .. } = end_block
&& let TemplateAstExpr::EndBlock = &**expression
{
true
} else {
false
};
chain.push(end_block);
if is_end {
break;
}
}
Ok(TemplateAstExpr::ConditionalChain { chain }) Ok(TemplateAstExpr::ConditionalChain { chain })
}) })
.parse_next(input) .parse_next(input)
} }
fn inner_conditional_chain<'input>(
input: &mut Input<'input>,
) -> Result<Vec<TemplateAstExpr<'input>>, AstError> {
let mut needs_end = false;
let mut chain = vec![];
loop {
let (content, end_block): (Vec<_>, _) = repeat_till(
0..,
parse_ast,
trace(
"conditional_chain_else/end",
alt((parse_end, parse_conditional_else)),
),
)
.parse_next(input)?;
chain.push(TemplateAstExpr::ConditionalContent { content });
let is_end = if let TemplateAstExpr::Block { ref expression, .. } = end_block
&& let TemplateAstExpr::EndBlock = &**expression
{
true
} else {
false
};
if !is_end && needs_end {
return Err(AstError::from_input(input).cut());
}
if let TemplateAstExpr::Block { expression, .. } = &end_block
&& let TemplateAstExpr::ElseConditional { expression: None } = &**expression
{
needs_end = true;
}
chain.push(end_block);
if is_end {
break;
}
}
Ok(chain)
}
fn parse_conditional_if<'input>( fn parse_conditional_if<'input>(
input: &mut Input<'input>, input: &mut Input<'input>,
) -> Result<TemplateAstExpr<'input>, AstError> { ) -> Result<TemplateAstExpr<'input>, AstError> {

View file

@ -5,9 +5,13 @@ fn check_files() {
for file in files { for file in files {
let input = std::fs::read_to_string(file.unwrap().path()).unwrap(); let input = std::fs::read_to_string(file.unwrap().path()).unwrap();
let parsed = nomo::parser::parse(input.into()).unwrap(); let Ok(parsed) = nomo::parser::parse(input.into()) else {
continue;
};
let ast = nomo::ast::parse(parsed.tokens()).unwrap(); let Ok(ast) = nomo::ast::parse(parsed.tokens()) else {
continue;
};
let _emit = nomo::emit::emit_machine(ast); let _emit = nomo::emit::emit_machine(ast);
} }

View file

@ -0,0 +1,3 @@
{{ if t }}
{{else}}{{ else }}
{{end }}