Skip to content

Commit

Permalink
Add better support for rust-like number literals (#908)
Browse files Browse the repository at this point in the history
Signed-off-by: max <gmx.sht@gmail.com>
  • Loading branch information
PizzasBear authored Nov 22, 2023
1 parent 48c6cd3 commit 6965610
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 5 deletions.
70 changes: 65 additions & 5 deletions askama_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ use std::{fmt, str};

use nom::branch::alt;
use nom::bytes::complete::{escaped, is_not, tag, take_till};
use nom::character::complete::char;
use nom::character::complete::{anychar, digit1};
use nom::character::complete::{anychar, char, one_of, satisfy};
use nom::combinator::{cut, eof, map, opt, recognize};
use nom::error::{Error, ErrorKind, FromExternalError};
use nom::multi::many1;
use nom::multi::{many0_count, many1};
use nom::sequence::{delimited, pair, preceded, terminated, tuple};
use nom::{error_position, AsChar, InputTakeAtPosition};

Expand Down Expand Up @@ -250,13 +249,74 @@ fn bool_lit(i: &str) -> ParseResult<'_> {
}

fn num_lit(i: &str) -> ParseResult<'_> {
let integer_suffix = |i| {
alt((
tag("i8"),
tag("i16"),
tag("i32"),
tag("i64"),
tag("i128"),
tag("isize"),
tag("u8"),
tag("u16"),
tag("u32"),
tag("u64"),
tag("u128"),
tag("usize"),
))(i)
};
let float_suffix = |i| alt((tag("f32"), tag("f64")))(i);

recognize(tuple((
opt(char('-')),
digit1,
opt(pair(char('.'), digit1)),
alt((
recognize(tuple((
char('0'),
alt((
recognize(tuple((char('b'), separated_digits(2, false)))),
recognize(tuple((char('o'), separated_digits(8, false)))),
recognize(tuple((char('x'), separated_digits(16, false)))),
)),
opt(integer_suffix),
))),
recognize(tuple((
separated_digits(10, true),
opt(alt((
integer_suffix,
float_suffix,
recognize(tuple((
opt(tuple((char('.'), separated_digits(10, true)))),
one_of("eE"),
opt(one_of("+-")),
separated_digits(10, false),
opt(float_suffix),
))),
recognize(tuple((
char('.'),
separated_digits(10, true),
opt(float_suffix),
))),
))),
))),
)),
)))(i)
}

/// Underscore separated digits of the given base, unless `start` is true this may start
/// with an underscore.
fn separated_digits(radix: u32, start: bool) -> impl Fn(&str) -> ParseResult<'_> {
move |i| {
recognize(tuple((
|i| match start {
true => Ok((i, 0)),
false => many0_count(char('_'))(i),
},
satisfy(|ch| ch.is_digit(radix)),
many0_count(satisfy(|ch| ch == '_' || ch.is_digit(radix))),
)))(i)
}
}

fn str_lit(i: &str) -> ParseResult<'_> {
let (i, s) = delimited(
char('"'),
Expand Down
11 changes: 11 additions & 0 deletions testing/templates/num-literals.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% let plain_int = 9__0__ -%}
{% let neg_int = -9__0__isize -%}
{% let suffix_int = 9__0__i32 -%}
{% let bin_int = 0b__1__0__ -%}
{% let oct_int = 0o__7__0__ -%}
{% let hex_int = 0x__f__0__ -%}
{% let plain_float = 1__0__.5__0__ -%}
{% let suffix_float = 1__0__.5__0__f32 -%}
{% let exp_float = 1__0__e+__1__0__f32 -%}
{% let dotexp_float = 1__0__.5__0__e+__1__0__f32 -%}
[{{ plain_int }}, {{ neg_int }}, {{ suffix_int }}, {{ bin_int }}, {{ oct_int }}, {{ hex_int }}, {{ plain_float }}, {{ suffix_float }}, {{ exp_float }}, {{ dotexp_float }}]
23 changes: 23 additions & 0 deletions testing/tests/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,3 +461,26 @@ fn test_define_string_var() {
let template = DefineStringVar;
assert_eq!(template.render().unwrap(), "");
}

#[derive(askama::Template)]
#[template(source = "{% let x = 4.5 %}{{ x }}", ext = "html")]
struct SimpleFloat;

#[test]
fn test_simple_float() {
let template = SimpleFloat;
assert_eq!(template.render().unwrap(), "4.5");
}

#[derive(askama::Template)]
#[template(path = "num-literals.html")]
struct NumLiterals;

#[test]
fn test_num_literals() {
let template = NumLiterals;
assert_eq!(
template.render().unwrap(),
"[90, -90, 90, 2, 56, 240, 10.5, 10.5, 100000000000, 105000000000]",
);
}

0 comments on commit 6965610

Please sign in to comment.