diff --git a/rinja_parser/src/expr.rs b/rinja_parser/src/expr.rs index c639260c..2f6bb4c2 100644 --- a/rinja_parser/src/expr.rs +++ b/rinja_parser/src/expr.rs @@ -202,16 +202,14 @@ impl<'a> Expr<'a> { Some("as") => { let (i, target) = opt(identifier)(j)?; let target = target.unwrap_or_default(); - return match target { - "bool" | "f16" | "f32" | "f64" | "f128" | "i8" | "i16" | "i32" | "i64" - | "i128" | "isize" | "u8" | "u16" | "u32" | "u64" | "u128" | "usize" => { - Ok((i, WithSpan::new(Self::As(Box::new(lhs), target), start))) - } - _ => Err(nom::Err::Failure(ErrorContext::new( + if crate::PRIMITIVE_TYPES.contains(&target) { + return Ok((i, WithSpan::new(Self::As(Box::new(lhs), target), start))); + } else { + return Err(nom::Err::Failure(ErrorContext::new( "operator `as` expects the name of a primitive type on its right-hand side", j, - ))), - }; + ))); + } } _ => return Ok((i, lhs)), }; diff --git a/rinja_parser/src/lib.rs b/rinja_parser/src/lib.rs index fc809e24..5f6078f6 100644 --- a/rinja_parser/src/lib.rs +++ b/rinja_parser/src/lib.rs @@ -416,20 +416,15 @@ fn bool_lit(i: &str) -> ParseResult<'_> { } fn num_lit(i: &str) -> ParseResult<'_> { - const INTEGER_SUFFIX: &[&str] = &[ - "i8", "i16", "i32", "i64", "i128", "isize", "u8", "u16", "u32", "u64", "u128", "usize", - ]; - const FLOAT_SUFFIX: &[&str] = &["f16", "f32", "f64", "f128"]; - fn suffix<'a>( start: &'a str, kind: &'a str, - list: &'a [&[&str]], + list: &'a [&str], ignore: &'a [&str], ) -> impl Fn(&'a str) -> ParseResult<'a> + Copy + 'a { move |i| { let (i, suffix) = identifier(i)?; - if list.iter().flat_map(|&i| i).any(|&item| item == suffix) { + if list.contains(&suffix) { Ok((i, suffix)) } else if ignore.contains(&suffix) { // no need for a message, this case only occures in an `opt(…)` @@ -443,9 +438,9 @@ fn num_lit(i: &str) -> ParseResult<'_> { } } - let integer_suffix = suffix(i, "integer", &[INTEGER_SUFFIX], &[]); - let float_suffix = suffix(i, "float", &[FLOAT_SUFFIX], &["e"]); - let either_suffix = suffix(i, "number", &[INTEGER_SUFFIX, FLOAT_SUFFIX], &["e"]); + let integer_suffix = suffix(i, "integer", INTEGER_TYPES, &[]); + let float_suffix = suffix(i, "float", FLOAT_TYPES, &["e"]); + let either_suffix = suffix(i, "number", NUM_TYPES, &["e"]); recognize(tuple(( opt(char('-')), @@ -809,6 +804,47 @@ pub fn strip_common(base: &Path, path: &Path) -> String { } } +/// Primitive integer types. Also used as number suffixes. +const INTEGER_TYPES: &[&str] = &[ + "i8", "i16", "i32", "i64", "i128", "isize", "u8", "u16", "u32", "u64", "u128", "usize", +]; + +/// Primitive floating point types. Also used as number suffixes. +const FLOAT_TYPES: &[&str] = &["f16", "f32", "f64", "f128"]; + +/// Primitive numeric types. Also used as number suffixes. +const NUM_TYPES: &[&str] = &{ + let mut list = [""; INTEGER_TYPES.len() + FLOAT_TYPES.len()]; + let mut i = 0; + let mut o = 0; + while i < INTEGER_TYPES.len() { + list[o] = INTEGER_TYPES[i]; + i += 1; + o += 1; + } + let mut i = 0; + while i < FLOAT_TYPES.len() { + list[o] = FLOAT_TYPES[i]; + i += 1; + o += 1; + } + list +}; + +/// Complete list of named primitive types. +const PRIMITIVE_TYPES: &[&str] = &{ + let mut list = [""; NUM_TYPES.len() + 1]; + let mut i = 0; + let mut o = 0; + while i < NUM_TYPES.len() { + list[o] = NUM_TYPES[i]; + i += 1; + o += 1; + } + list[o] = "bool"; + list +}; + #[cfg(not(windows))] #[cfg(test)] mod test {