Add else parsing

Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
Marcel Müller 2026-03-08 20:02:33 +01:00
parent b69c659583
commit 13eb4ca1d0

View file

@ -206,6 +206,7 @@ pub enum TokenKind {
Whitespace, Whitespace,
Invalid, Invalid,
ConditionalIf, ConditionalIf,
ConditionalElse,
End, End,
Literal(TokenLiteral), Literal(TokenLiteral),
} }
@ -290,6 +291,7 @@ impl TemplateToken {
whitespace => TokenKind::Whitespace, whitespace => TokenKind::Whitespace,
invalid => TokenKind::Invalid, invalid => TokenKind::Invalid,
conditional_if => TokenKind::ConditionalIf, conditional_if => TokenKind::ConditionalIf,
conditional_else => TokenKind::ConditionalElse,
end => TokenKind::End, end => TokenKind::End,
} }
@ -344,7 +346,7 @@ fn parse_interpolate<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<T
let left_delim = "{{".map(TemplateToken::left_delim).parse_next(input)?; let left_delim = "{{".map(TemplateToken::left_delim).parse_next(input)?;
let wants_output = opt("=".map(TemplateToken::wants_output)).parse_next(input)?; let wants_output = opt("=".map(TemplateToken::wants_output)).parse_next(input)?;
let get_tokens = repeat_till(1.., parse_interpolate_token, peek("}}")); let get_tokens = repeat_till(1.., parse_block_token, peek("}}"));
let recover = take_until(0.., "}}").void(); let recover = take_until(0.., "}}").void();
let (inside_tokens, _): (Vec<_>, _) = get_tokens let (inside_tokens, _): (Vec<_>, _) = get_tokens
@ -369,13 +371,14 @@ fn parse_interpolate<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<T
Ok(tokens) Ok(tokens)
} }
fn parse_interpolate_token<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> { fn parse_block_token<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
trace( trace(
"parse_interpolate_token", "parse_block_token",
alt(( alt((
parse_ident, parse_ident,
parse_literal, parse_literal,
parse_condition, parse_condition_if,
parse_condition_else,
parse_end, parse_end,
parse_whitespace, parse_whitespace,
)), )),
@ -385,7 +388,7 @@ fn parse_interpolate_token<'input>(input: &mut Input<'input>) -> PResult<'input,
fn parse_literal<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> { fn parse_literal<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
trace( trace(
"parse_condition", "parse_literal",
alt((parse_boolean,)) alt((parse_boolean,))
.with_taken() .with_taken()
.map(|(lit, span)| TemplateToken::literal(lit, span)), .map(|(lit, span)| TemplateToken::literal(lit, span)),
@ -401,12 +404,24 @@ fn parse_boolean<'input>(input: &mut Input<'input>) -> PResult<'input, TokenLite
.parse_next(input) .parse_next(input)
} }
fn parse_condition<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> { fn parse_condition_if<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
trace("parse_condition", "if".map(TemplateToken::conditional_if)).parse_next(input) trace(
"parse_condition_if",
"if".map(TemplateToken::conditional_if),
)
.parse_next(input)
}
fn parse_condition_else<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
trace(
"parse_condition_else",
"else".map(TemplateToken::conditional_else),
)
.parse_next(input)
} }
fn parse_end<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> { fn parse_end<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
trace("parse_condition", "end".map(TemplateToken::end)).parse_next(input) trace("parse_end", "end".map(TemplateToken::end)).parse_next(input)
} }
fn parse_whitespace<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> { fn parse_whitespace<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
@ -436,7 +451,12 @@ fn parse_ident<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateTok
} }
fn ident<'input>(input: &mut Input<'input>) -> PResult<'input, NomoInput> { fn ident<'input>(input: &mut Input<'input>) -> PResult<'input, NomoInput> {
peek(not(alt((parse_literal, parse_condition, parse_end)))) peek(not(alt((
parse_literal,
parse_condition_if,
parse_condition_else,
parse_end,
))))
.context(ParseError::ctx().msg("Expected an ident, but found a literal instead")) .context(ParseError::ctx().msg("Expected an ident, but found a literal instead"))
.parse_next(input)?; .parse_next(input)?;
@ -540,7 +560,7 @@ mod tests {
#[test] #[test]
fn parse_simple_condition() { fn parse_simple_condition() {
let input = "{{ if true }} Hello! {{ end }}"; let input = "{{ if true }} Hello! {{ else }} Bye {{ end }}";
let output = parse(input.into()); let output = parse(input.into());
insta::assert_debug_snapshot!(output, @r#" insta::assert_debug_snapshot!(output, @r#"
@ -559,9 +579,17 @@ mod tests {
" " (20..21), " " (20..21),
"{{" (21..23), "{{" (21..23),
" " (23..24), " " (23..24),
"end" (24..27), "else" (24..28),
" " (27..28), " " (28..29),
"}}" (28..30), "}}" (29..31),
" " (31..32),
"Bye" (32..35),
" " (35..36),
"{{" (36..38),
" " (38..39),
"end" (39..42),
" " (42..43),
"}}" (43..45),
], ],
}, },
) )