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