diff options
-rw-r--r-- | askama_shared/src/parser.rs | 32 |
1 files changed, 15 insertions, 17 deletions
diff --git a/askama_shared/src/parser.rs b/askama_shared/src/parser.rs index 6c90941..3d30549 100644 --- a/askama_shared/src/parser.rs +++ b/askama_shared/src/parser.rs @@ -8,7 +8,7 @@ use nom::combinator::{complete, cut, map, opt, recognize, value}; use nom::error::{Error, ErrorKind}; use nom::multi::{fold_many0, many0, many1, separated_list0, separated_list1}; use nom::sequence::{delimited, pair, preceded, terminated, tuple}; -use nom::{self, IResult, error_position}; +use nom::{self, error_position, AsChar, IResult, InputTakeAtPosition}; use crate::{CompileError, Syntax}; @@ -216,24 +216,22 @@ fn take_content<'a>(i: &'a [u8], s: &State<'_>) -> IResult<&'a [u8], Node<'a>> { } fn identifier(input: &[u8]) -> IResult<&[u8], &str> { - if !nom::character::is_alphabetic(input[0]) && input[0] != b'_' && !non_ascii(input[0]) { - return Err(nom::Err::Error(error_position!( - input, - ErrorKind::AlphaNumeric - ))); - } - for (i, ch) in input.iter().enumerate() { - if i == 0 || nom::character::is_alphanumeric(*ch) || *ch == b'_' || non_ascii(*ch) { - continue; - } - return Ok((&input[i..], str::from_utf8(&input[..i]).unwrap())); - } - Ok((&input[1..], str::from_utf8(&input[..1]).unwrap())) + let (i, s) = recognize(pair(identifier_start, opt(identifier_tail)))(input)?; + Ok((i, str::from_utf8(s).unwrap())) +} + +fn identifier_start(s: &[u8]) -> IResult<&[u8], &[u8]> { + s.split_at_position1_complete( + |c| !(c.is_alpha() || c == b'_' || c >= 0x80), + nom::error::ErrorKind::Alpha, + ) } -#[inline] -fn non_ascii(chr: u8) -> bool { - (0x80..=0xFD).contains(&chr) +fn identifier_tail(s: &[u8]) -> IResult<&[u8], &[u8]> { + s.split_at_position1_complete( + |c| !(c.is_alphanum() || c == b'_' || c >= 0x80), + nom::error::ErrorKind::Alpha, + ) } fn bool_lit(i: &[u8]) -> IResult<&[u8], &str> { |