Add parsing of literal numbers

Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
Marcel Müller 2026-03-12 10:43:45 +01:00
parent 09ae91c393
commit 8cc8488de4

View file

@ -8,6 +8,8 @@ use thiserror::Error;
use winnow::LocatingSlice; use winnow::LocatingSlice;
use winnow::Parser; use winnow::Parser;
use winnow::RecoverableParser; use winnow::RecoverableParser;
use winnow::ascii::alpha1;
use winnow::ascii::digit1;
use winnow::ascii::multispace0; use winnow::ascii::multispace0;
use winnow::ascii::multispace1; use winnow::ascii::multispace1;
use winnow::combinator::alt; use winnow::combinator::alt;
@ -232,6 +234,7 @@ pub enum TokenOperator {
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum TokenLiteral { pub enum TokenLiteral {
Bool(bool), Bool(bool),
Integer(u64),
} }
impl PartialEq<TokenKind> for TemplateToken { impl PartialEq<TokenKind> for TemplateToken {
@ -414,13 +417,20 @@ fn parse_block_token<'input>(input: &mut Input<'input>) -> PResult<'input, Templ
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_literal", "parse_literal",
alt((parse_boolean,)) alt((parse_boolean, parse_number))
.with_taken() .with_taken()
.map(|(lit, span)| TemplateToken::literal(lit, span)), .map(|(lit, span)| TemplateToken::literal(lit, span)),
) )
.parse_next(input) .parse_next(input)
} }
fn parse_number<'input>(input: &mut Input<'input>) -> PResult<'input, TokenLiteral> {
digit1
.verify_map(|digits: NomoInput| digits.parse::<u64>().ok())
.map(TokenLiteral::Integer)
.parse_next(input)
}
fn parse_boolean<'input>(input: &mut Input<'input>) -> PResult<'input, TokenLiteral> { fn parse_boolean<'input>(input: &mut Input<'input>) -> PResult<'input, TokenLiteral> {
alt(( alt((
"true".value(TokenLiteral::Bool(true)), "true".value(TokenLiteral::Bool(true)),
@ -525,7 +535,14 @@ fn ident<'input>(input: &mut Input<'input>) -> PResult<'input, NomoInput> {
.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)?;
take_while(1.., |c: char| c.is_alphanumeric() || "_".contains(c)).parse_next(input) let literal_start = alpha1;
(
literal_start,
take_while(0.., |c: char| c.is_alphanumeric() || "_".contains(c)),
)
.take()
.parse_next(input)
} }
fn bad_ident<'input>(input: &mut Input<'input>) -> PResult<'input, ()> { fn bad_ident<'input>(input: &mut Input<'input>) -> PResult<'input, ()> {
@ -729,7 +746,7 @@ mod tests {
#[test] #[test]
fn parse_operations() { fn parse_operations() {
let input = "{{= 5 * 4 + 3 / 2 - 1 }}{{ if foo && bar || baz }}{{ end }}"; let input = "{{= 5 * 14 + 3 / 2 - 1 }}{{ if foo && bar || baz }}{{ end }}";
let output = parse(input.into()); let output = parse(input.into());
insta::assert_debug_snapshot!(output, @r#" insta::assert_debug_snapshot!(output, @r#"
@ -739,45 +756,45 @@ mod tests {
[LeftDelim]"{{" (0..2), [LeftDelim]"{{" (0..2),
[WantsOutput]"=" (2..3), [WantsOutput]"=" (2..3),
[Whitespace]" " (3..4), [Whitespace]" " (3..4),
[Ident]"5" (4..5), [Literal(Integer(5))]"5" (4..5),
[Whitespace]" " (5..6), [Whitespace]" " (5..6),
[Operator(Times)]"*" (6..7), [Operator(Times)]"*" (6..7),
[Whitespace]" " (7..8), [Whitespace]" " (7..8),
[Ident]"4" (8..9), [Literal(Integer(14))]"14" (8..10),
[Whitespace]" " (9..10), [Whitespace]" " (10..11),
[Operator(Plus)]"+" (10..11), [Operator(Plus)]"+" (11..12),
[Whitespace]" " (11..12), [Whitespace]" " (12..13),
[Ident]"3" (12..13), [Literal(Integer(3))]"3" (13..14),
[Whitespace]" " (13..14), [Whitespace]" " (14..15),
[Operator(Divide)]"/" (14..15), [Operator(Divide)]"/" (15..16),
[Whitespace]" " (15..16), [Whitespace]" " (16..17),
[Ident]"2" (16..17), [Literal(Integer(2))]"2" (17..18),
[Whitespace]" " (17..18), [Whitespace]" " (18..19),
[Operator(Minus)]"-" (18..19), [Operator(Minus)]"-" (19..20),
[Whitespace]" " (19..20), [Whitespace]" " (20..21),
[Ident]"1" (20..21), [Literal(Integer(1))]"1" (21..22),
[Whitespace]" " (21..22), [Whitespace]" " (22..23),
[RightDelim]"}}" (22..24), [RightDelim]"}}" (23..25),
[LeftDelim]"{{" (24..26), [LeftDelim]"{{" (25..27),
[Whitespace]" " (26..27), [Whitespace]" " (27..28),
[ConditionalIf]"if" (27..29), [ConditionalIf]"if" (28..30),
[Whitespace]" " (29..30), [Whitespace]" " (30..31),
[Ident]"foo" (30..33), [Ident]"foo" (31..34),
[Whitespace]" " (33..34), [Whitespace]" " (34..35),
[Operator(And)]"&&" (34..36), [Operator(And)]"&&" (35..37),
[Whitespace]" " (36..37), [Whitespace]" " (37..38),
[Ident]"bar" (37..40), [Ident]"bar" (38..41),
[Whitespace]" " (40..41), [Whitespace]" " (41..42),
[Operator(Or)]"||" (41..43), [Operator(Or)]"||" (42..44),
[Whitespace]" " (43..44), [Whitespace]" " (44..45),
[Ident]"baz" (44..47), [Ident]"baz" (45..48),
[Whitespace]" " (47..48), [Whitespace]" " (48..49),
[RightDelim]"}}" (48..50), [RightDelim]"}}" (49..51),
[LeftDelim]"{{" (50..52), [LeftDelim]"{{" (51..53),
[Whitespace]" " (52..53), [Whitespace]" " (53..54),
[End]"end" (53..56), [End]"end" (54..57),
[Whitespace]" " (56..57), [Whitespace]" " (57..58),
[RightDelim]"}}" (57..59), [RightDelim]"}}" (58..60),
], ],
}, },
) )