aboutsummaryrefslogtreecommitdiffstats
path: root/askama_parser/src/node.rs
diff options
context:
space:
mode:
authorLibravatar René Kijewski <rene.kijewski@fu-berlin.de>2023-07-14 12:46:57 +0200
committerLibravatar René Kijewski <Kijewski@users.noreply.github.com>2023-08-03 00:02:04 +0200
commit95ff27c087f9fd77e76ed069220d7b32d150a84e (patch)
tree49f9037daeec0561960aeadc3c3d4a9503ce0bdb /askama_parser/src/node.rs
parentd38e2b4e2651b7c8b1a8bf614377011d046250f6 (diff)
downloadaskama-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/node.rs')
-rw-r--r--askama_parser/src/node.rs15
1 files changed, 12 insertions, 3 deletions
diff --git a/askama_parser/src/node.rs b/askama_parser/src/node.rs
index 4c21ad1..a1aa7e2 100644
--- a/askama_parser/src/node.rs
+++ b/askama_parser/src/node.rs
@@ -3,15 +3,17 @@ use std::str;
use nom::branch::alt;
use nom::bytes::complete::{tag, take_until};
use nom::character::complete::char;
-use nom::combinator::{complete, consumed, cut, eof, map, not, opt, peek, recognize, value};
+use nom::combinator::{
+ complete, consumed, cut, eof, map, map_res, not, opt, peek, 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::{error_position, IResult};
use super::{
- bool_lit, char_lit, identifier, is_ws, keyword, num_lit, path, skip_till, str_lit, ws, Expr,
- State,
+ bool_lit, char_lit, identifier, is_ws, keyword, num_lit, path_or_identifier, skip_till,
+ str_lit, ws, Expr, PathOrIdentifier, State,
};
#[derive(Debug, PartialEq)]
@@ -161,6 +163,13 @@ impl<'a> Target<'a> {
return Ok((i, Self::Tuple(Vec::new(), targets)));
}
+ let path = |i| {
+ map_res(path_or_identifier, |v| match v {
+ PathOrIdentifier::Path(v) => Ok(v),
+ PathOrIdentifier::Identifier(v) => Err(v),
+ })(i)
+ };
+
// match structs
let (i, path) = opt(path)(i)?;
if let Some(path) = path {