diff options
author | René Kijewski <rene.kijewski@fu-berlin.de> | 2023-07-14 12:46:57 +0200 |
---|---|---|
committer | René Kijewski <Kijewski@users.noreply.github.com> | 2023-08-03 00:02:04 +0200 |
commit | 95ff27c087f9fd77e76ed069220d7b32d150a84e (patch) | |
tree | 49f9037daeec0561960aeadc3c3d4a9503ce0bdb /askama_parser/src/expr.rs | |
parent | d38e2b4e2651b7c8b1a8bf614377011d046250f6 (diff) | |
download | askama-95ff27c087f9fd77e76ed069220d7b32d150a84e.tar.gz askama-95ff27c087f9fd77e76ed069220d7b32d150a84e.tar.bz2 askama-95ff27c087f9fd77e76ed069220d7b32d150a84e.zip |
Parse paths and identifiers only once
In the old implementation each variable in an expression would be parsed
up to three times:
* Try to parse a path because it contains a leading double colon, or
infix double colons.
* Try to parse it as path again by scanning for an identifier that
contains an upper case character.
* Fall back to scanning for any identifier.
This PR turns all three steps into one, without the need for
backtracking.
Diffstat (limited to 'askama_parser/src/expr.rs')
-rw-r--r-- | askama_parser/src/expr.rs | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/askama_parser/src/expr.rs b/askama_parser/src/expr.rs index 8331e01..248bc19 100644 --- a/askama_parser/src/expr.rs +++ b/askama_parser/src/expr.rs @@ -9,7 +9,10 @@ use nom::multi::{fold_many0, many0, separated_list0}; use nom::sequence::{pair, preceded, terminated, tuple}; use nom::{error_position, IResult}; -use super::{bool_lit, char_lit, identifier, not_ws, num_lit, path, str_lit, ws}; +use super::{ + bool_lit, char_lit, identifier, not_ws, num_lit, path_or_identifier, str_lit, ws, + PathOrIdentifier, +}; macro_rules! expr_prec_layer { ( $name:ident, $inner:ident, $op:expr ) => { @@ -141,9 +144,8 @@ impl<'a> Expr<'a> { Self::num, Self::str, Self::char, - Self::path, + Self::path_or_var, Self::array, - Self::var, Self::group, ))(i) } @@ -186,13 +188,11 @@ impl<'a> Expr<'a> { )(i) } - fn path(i: &'a str) -> IResult<&'a str, Self> { - let (i, path) = path(i)?; - Ok((i, Self::Path(path))) - } - - fn var(i: &'a str) -> IResult<&'a str, Self> { - map(identifier, Self::Var)(i) + fn path_or_var(i: &'a str) -> IResult<&'a str, Self> { + map(path_or_identifier, |v| match v { + PathOrIdentifier::Path(v) => Self::Path(v), + PathOrIdentifier::Identifier(v) => Self::Var(v), + })(i) } fn str(i: &'a str) -> IResult<&'a str, Self> { |