Split up if chains more

Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
Marcel Müller 2026-03-08 21:22:57 +01:00
parent 383f543119
commit c9314a3d9b
4 changed files with 90 additions and 21 deletions

View file

@ -228,10 +228,12 @@ pub enum TemplateAstExpr<'input> {
},
IfConditional {
if_block: Box<TemplateAstExpr<'input>>,
},
ConditionalContent {
content: Vec<TemplateAstExpr<'input>>,
},
ElseConditional {
expression: Vec<TemplateAstExpr<'input>>,
expression: Option<Box<TemplateAstExpr<'input>>>,
},
Invalid(&'input [TemplateToken]),
EndBlock,
@ -314,21 +316,45 @@ fn parse_conditional_chain<'input>(
input: &mut Input<'input>,
) -> Result<TemplateAstExpr<'input>, AstError> {
trace("conditional_chain", |input: &mut Input<'input>| {
let if_block = parse_conditional.map(Box::new).parse_next(input)?;
let if_block = parse_conditional_if.map(Box::new).parse_next(input)?;
let mut chain = vec![];
let (content, end_block): (Vec<_>, _) =
repeat_till(0.., parse_ast, parse_end).parse_next(input)?;
chain.push(TemplateAstExpr::IfConditional { if_block });
chain.push(TemplateAstExpr::IfConditional { if_block, content });
chain.push(end_block);
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
};
chain.push(end_block);
if dbg!(is_end) {
break;
}
}
Ok(TemplateAstExpr::ConditionalChain { chain })
})
.parse_next(input)
}
fn parse_conditional<'input>(
fn parse_conditional_if<'input>(
input: &mut Input<'input>,
) -> Result<TemplateAstExpr<'input>, AstError> {
trace(
@ -344,6 +370,27 @@ fn parse_conditional<'input>(
.parse_next(input)
}
fn parse_conditional_else<'input>(
input: &mut Input<'input>,
) -> Result<TemplateAstExpr<'input>, AstError> {
trace(
"conditional_else",
parse_block(
preceded(
surrounded(ws, TokenKind::ConditionalElse),
opt(preceded(
TokenKind::ConditionalIf,
cut_err(surrounded(ws, parse_value_expression)).map(Box::new),
)),
)
.map(|else_expr| TemplateAstExpr::ElseConditional {
expression: else_expr,
}),
),
)
.parse_next(input)
}
fn parse_end<'input>(input: &mut Input<'input>) -> Result<TemplateAstExpr<'input>, AstError> {
trace(
"end",
@ -440,6 +487,18 @@ mod tests {
use crate::ast::parse_end;
use crate::parser::TokenKind;
fn panic_pretty<'a>(
input: &'_ str,
tokens: Result<TemplateAst<'a>, AstFailure>,
) -> TemplateAst<'a> {
match tokens {
Ok(ast) => ast,
Err(failure) => {
panic!("{}", failure.to_report(input));
}
}
}
#[test]
fn check_only_content() {
let input = "Hello World";
@ -493,7 +552,7 @@ mod tests {
let parsed = crate::parser::parse(input.into()).unwrap();
let ast = parse(parsed.tokens()).unwrap();
let ast = panic_pretty(input, parse(parsed.tokens()));
insta::assert_debug_snapshot!(ast, @r#"
TemplateAst {
@ -510,6 +569,8 @@ mod tests {
[Whitespace]" " (12..13),
),
},
},
ConditionalContent {
content: [
StaticContent(
[Content]"Hiii" (13..17),
@ -530,18 +591,6 @@ mod tests {
"#);
}
fn panic_pretty<'a>(
input: &'_ str,
tokens: Result<TemplateAst<'a>, AstFailure>,
) -> TemplateAst<'a> {
match tokens {
Ok(ast) => ast,
Err(failure) => {
panic!("{}", failure.to_report(input));
}
}
}
#[test]
fn check_invalid_action() {
let input = r#"{{ value }}
@ -624,4 +673,13 @@ mod tests {
)
"#);
}
#[test]
fn check_empty_output() {
let input = "{{ if foo }}{{ end }}";
let parsed = crate::parser::parse(input.into()).unwrap();
panic_pretty(input, parse(parsed.tokens()));
}
}