Split up if chains more
Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
parent
383f543119
commit
c9314a3d9b
4 changed files with 90 additions and 21 deletions
|
|
@ -228,10 +228,12 @@ pub enum TemplateAstExpr<'input> {
|
||||||
},
|
},
|
||||||
IfConditional {
|
IfConditional {
|
||||||
if_block: Box<TemplateAstExpr<'input>>,
|
if_block: Box<TemplateAstExpr<'input>>,
|
||||||
|
},
|
||||||
|
ConditionalContent {
|
||||||
content: Vec<TemplateAstExpr<'input>>,
|
content: Vec<TemplateAstExpr<'input>>,
|
||||||
},
|
},
|
||||||
ElseConditional {
|
ElseConditional {
|
||||||
expression: Vec<TemplateAstExpr<'input>>,
|
expression: Option<Box<TemplateAstExpr<'input>>>,
|
||||||
},
|
},
|
||||||
Invalid(&'input [TemplateToken]),
|
Invalid(&'input [TemplateToken]),
|
||||||
EndBlock,
|
EndBlock,
|
||||||
|
|
@ -314,21 +316,45 @@ fn parse_conditional_chain<'input>(
|
||||||
input: &mut Input<'input>,
|
input: &mut Input<'input>,
|
||||||
) -> Result<TemplateAstExpr<'input>, AstError> {
|
) -> Result<TemplateAstExpr<'input>, AstError> {
|
||||||
trace("conditional_chain", |input: &mut Input<'input>| {
|
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 mut chain = vec![];
|
||||||
|
|
||||||
let (content, end_block): (Vec<_>, _) =
|
chain.push(TemplateAstExpr::IfConditional { if_block });
|
||||||
repeat_till(0.., parse_ast, parse_end).parse_next(input)?;
|
|
||||||
|
|
||||||
chain.push(TemplateAstExpr::IfConditional { if_block, content });
|
loop {
|
||||||
chain.push(end_block);
|
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 })
|
Ok(TemplateAstExpr::ConditionalChain { chain })
|
||||||
})
|
})
|
||||||
.parse_next(input)
|
.parse_next(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_conditional<'input>(
|
fn parse_conditional_if<'input>(
|
||||||
input: &mut Input<'input>,
|
input: &mut Input<'input>,
|
||||||
) -> Result<TemplateAstExpr<'input>, AstError> {
|
) -> Result<TemplateAstExpr<'input>, AstError> {
|
||||||
trace(
|
trace(
|
||||||
|
|
@ -344,6 +370,27 @@ fn parse_conditional<'input>(
|
||||||
.parse_next(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> {
|
fn parse_end<'input>(input: &mut Input<'input>) -> Result<TemplateAstExpr<'input>, AstError> {
|
||||||
trace(
|
trace(
|
||||||
"end",
|
"end",
|
||||||
|
|
@ -440,6 +487,18 @@ mod tests {
|
||||||
use crate::ast::parse_end;
|
use crate::ast::parse_end;
|
||||||
use crate::parser::TokenKind;
|
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]
|
#[test]
|
||||||
fn check_only_content() {
|
fn check_only_content() {
|
||||||
let input = "Hello World";
|
let input = "Hello World";
|
||||||
|
|
@ -493,7 +552,7 @@ mod tests {
|
||||||
|
|
||||||
let parsed = crate::parser::parse(input.into()).unwrap();
|
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#"
|
insta::assert_debug_snapshot!(ast, @r#"
|
||||||
TemplateAst {
|
TemplateAst {
|
||||||
|
|
@ -510,6 +569,8 @@ mod tests {
|
||||||
[Whitespace]" " (12..13),
|
[Whitespace]" " (12..13),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
ConditionalContent {
|
||||||
content: [
|
content: [
|
||||||
StaticContent(
|
StaticContent(
|
||||||
[Content]"Hiii" (13..17),
|
[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]
|
#[test]
|
||||||
fn check_invalid_action() {
|
fn check_invalid_action() {
|
||||||
let input = r#"{{ value }}
|
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()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ TemplateAst {
|
||||||
[Whitespace]"\n " (12..25),
|
[Whitespace]"\n " (12..25),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
ConditionalContent {
|
||||||
content: [
|
content: [
|
||||||
ConditionalChain {
|
ConditionalChain {
|
||||||
chain: [
|
chain: [
|
||||||
|
|
@ -29,6 +31,8 @@ TemplateAst {
|
||||||
[Whitespace]"\n " (37..54),
|
[Whitespace]"\n " (37..54),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
ConditionalContent {
|
||||||
content: [
|
content: [
|
||||||
StaticContent(
|
StaticContent(
|
||||||
[Content]"Hiii" (54..58),
|
[Content]"Hiii" (54..58),
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,6 @@ fn emit_ast_expr(
|
||||||
let mut chain = chain.iter();
|
let mut chain = chain.iter();
|
||||||
let Some(TemplateAstExpr::IfConditional {
|
let Some(TemplateAstExpr::IfConditional {
|
||||||
if_block: expression,
|
if_block: expression,
|
||||||
content,
|
|
||||||
}) = chain.next()
|
}) = chain.next()
|
||||||
else {
|
else {
|
||||||
unreachable!("First element in conditional chain should be an IfConditional");
|
unreachable!("First element in conditional chain should be an IfConditional");
|
||||||
|
|
@ -107,6 +106,10 @@ fn emit_ast_expr(
|
||||||
unreachable!("The end of an IfConditional must be a Block");
|
unreachable!("The end of an IfConditional must be a Block");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let Some(TemplateAstExpr::ConditionalContent { content }) = chain.next() else {
|
||||||
|
unreachable!("The end of an IfConditional must be a Block");
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(ws) = prev_whitespace_content {
|
if let Some(ws) = prev_whitespace_content {
|
||||||
eval.push(Instruction::AppendContent {
|
eval.push(Instruction::AppendContent {
|
||||||
content: ws.source().clone(),
|
content: ws.source().clone(),
|
||||||
|
|
@ -163,6 +166,7 @@ fn emit_ast_expr(
|
||||||
TemplateAstExpr::Block { .. }
|
TemplateAstExpr::Block { .. }
|
||||||
| TemplateAstExpr::EndBlock
|
| TemplateAstExpr::EndBlock
|
||||||
| TemplateAstExpr::IfConditional { .. }
|
| TemplateAstExpr::IfConditional { .. }
|
||||||
|
| TemplateAstExpr::ConditionalContent { .. }
|
||||||
| TemplateAstExpr::ElseConditional { .. }
|
| TemplateAstExpr::ElseConditional { .. }
|
||||||
| TemplateAstExpr::Invalid { .. }
|
| TemplateAstExpr::Invalid { .. }
|
||||||
| TemplateAstExpr::VariableAccess { .. } => eval.push(Instruction::Abort),
|
| TemplateAstExpr::VariableAccess { .. } => eval.push(Instruction::Abort),
|
||||||
|
|
@ -191,6 +195,7 @@ fn emit_expr_load(
|
||||||
TemplateAstExpr::EndBlock => todo!(),
|
TemplateAstExpr::EndBlock => todo!(),
|
||||||
TemplateAstExpr::Block { .. } => todo!(),
|
TemplateAstExpr::Block { .. } => todo!(),
|
||||||
TemplateAstExpr::IfConditional { .. } => todo!(),
|
TemplateAstExpr::IfConditional { .. } => todo!(),
|
||||||
|
TemplateAstExpr::ConditionalContent { .. } => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ TemplateAst {
|
||||||
[Whitespace]"\n " (13..18),
|
[Whitespace]"\n " (13..18),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
ConditionalContent {
|
||||||
content: [
|
content: [
|
||||||
StaticContent(
|
StaticContent(
|
||||||
[Content]"Hello World!" (18..30),
|
[Content]"Hello World!" (18..30),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue