Add ast parsing for for loops
Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
parent
a099c74b1b
commit
e64256b65f
3 changed files with 165 additions and 0 deletions
|
|
@ -230,6 +230,18 @@ pub enum TemplateAstExpr<'input> {
|
|||
ConditionalChain {
|
||||
chain: Vec<TemplateAstExpr<'input>>,
|
||||
},
|
||||
ForChain {
|
||||
for_block: Box<TemplateAstExpr<'input>>,
|
||||
content: Vec<TemplateAstExpr<'input>>,
|
||||
else_block: Option<Box<TemplateAstExpr<'input>>>,
|
||||
else_content: Option<Vec<TemplateAstExpr<'input>>>,
|
||||
end_block: Box<TemplateAstExpr<'input>>,
|
||||
},
|
||||
For {
|
||||
value_ident: TemplateToken,
|
||||
value_expression: Box<TemplateAstExpr<'input>>,
|
||||
},
|
||||
ForElse,
|
||||
VariableAccess(TemplateToken),
|
||||
IfConditional {
|
||||
expression: Box<TemplateAstExpr<'input>>,
|
||||
|
|
@ -316,6 +328,7 @@ fn parse_action<'input>(input: &mut Input<'input>) -> Result<TemplateAstExpr<'in
|
|||
"action",
|
||||
alt((
|
||||
parse_conditional_chain,
|
||||
parse_for_chain,
|
||||
(parse_block(
|
||||
cut_err(not(repeat_till(
|
||||
0..,
|
||||
|
|
@ -336,6 +349,67 @@ fn parse_action<'input>(input: &mut Input<'input>) -> Result<TemplateAstExpr<'in
|
|||
.parse_next(input)
|
||||
}
|
||||
|
||||
fn parse_for_chain<'input>(input: &mut Input<'input>) -> Result<TemplateAstExpr<'input>, AstError> {
|
||||
trace("for_loop", |input: &mut Input<'input>| {
|
||||
let for_block = parse_for_loop.map(Box::new).parse_next(input)?;
|
||||
|
||||
let loop_end = (
|
||||
opt((
|
||||
parse_loop_else.map(Box::new),
|
||||
repeat_till(0.., parse_ast, peek(parse_end)).map(|(val, _)| val),
|
||||
)),
|
||||
parse_end.map(Box::new),
|
||||
);
|
||||
|
||||
let (content, taken) = resume_after_cut(
|
||||
repeat_till(0.., parse_ast, loop_end),
|
||||
repeat_till(0.., any, parse_end).map(|((), _)| ()),
|
||||
)
|
||||
.with_taken()
|
||||
.parse_next(input)?;
|
||||
|
||||
let Some((content, (else_stuff, end_block))) = content else {
|
||||
return Ok(TemplateAstExpr::Invalid(taken));
|
||||
};
|
||||
|
||||
let (else_block, else_content) = else_stuff.unzip();
|
||||
|
||||
Ok(TemplateAstExpr::ForChain {
|
||||
for_block,
|
||||
content,
|
||||
else_block,
|
||||
else_content,
|
||||
end_block,
|
||||
})
|
||||
})
|
||||
.parse_next(input)
|
||||
}
|
||||
|
||||
fn parse_for_loop<'input>(input: &mut Input<'input>) -> Result<TemplateAstExpr<'input>, AstError> {
|
||||
trace(
|
||||
"for_loop_inner",
|
||||
parse_block(
|
||||
(
|
||||
ws,
|
||||
TokenKind::For,
|
||||
ws,
|
||||
TokenKind::Ident,
|
||||
ws,
|
||||
TokenKind::In,
|
||||
ws,
|
||||
parse_value_expression.map(Box::new),
|
||||
)
|
||||
.map(|(_, _for, _, value_ident, _, _in, _, value_expression)| {
|
||||
TemplateAstExpr::For {
|
||||
value_ident,
|
||||
value_expression,
|
||||
}
|
||||
}),
|
||||
),
|
||||
)
|
||||
.parse_next(input)
|
||||
}
|
||||
|
||||
fn parse_conditional_chain<'input>(
|
||||
input: &mut Input<'input>,
|
||||
) -> Result<TemplateAstExpr<'input>, AstError> {
|
||||
|
|
@ -447,6 +521,18 @@ fn parse_conditional_else<'input>(
|
|||
.parse_next(input)
|
||||
}
|
||||
|
||||
fn parse_loop_else<'input>(input: &mut Input<'input>) -> Result<TemplateAstExpr<'input>, AstError> {
|
||||
trace(
|
||||
"end",
|
||||
parse_block(
|
||||
TokenKind::ConditionalElse
|
||||
.value(TemplateAstExpr::ForElse)
|
||||
.context(AstError::ctx().msg("Expected an else block here")),
|
||||
),
|
||||
)
|
||||
.parse_next(input)
|
||||
}
|
||||
|
||||
fn parse_end<'input>(input: &mut Input<'input>) -> Result<TemplateAstExpr<'input>, AstError> {
|
||||
trace(
|
||||
"end",
|
||||
|
|
@ -815,4 +901,15 @@ mod tests {
|
|||
|
||||
insta::assert_debug_snapshot!(ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_for_loop() {
|
||||
let input = "{{ for value in array }} Hi: {{= value }} {{ else }} No Content :C {{ end }}";
|
||||
|
||||
let parsed = crate::parser::parse(input.into()).unwrap();
|
||||
|
||||
let ast = panic_pretty(input, parse(parsed.tokens()));
|
||||
|
||||
insta::assert_debug_snapshot!(ast);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue