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