Skip to content

Commit

Permalink
Speed-up node selection
Browse files Browse the repository at this point in the history
  • Loading branch information
Kijewski committed May 16, 2024
1 parent 5ac9bed commit a9eb4b4
Showing 1 changed file with 43 additions and 23 deletions.
66 changes: 43 additions & 23 deletions askama_parser/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::borrow::Cow;
use std::str;

use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::bytes::complete::{tag, take_till};
use nom::character::complete::char;
use nom::combinator::{
complete, consumed, cut, eof, map, map_res, not, opt, peek, recognize, value,
Expand All @@ -12,7 +12,7 @@ use nom::error_position;
use nom::multi::{fold_many0, many0, many1, separated_list0, separated_list1};
use nom::sequence::{delimited, pair, preceded, terminated, tuple};

use crate::{ErrorContext, ParseResult};
use crate::{not_ws, ErrorContext, ParseResult};

use super::{
bool_lit, char_lit, filter, identifier, is_ws, keyword, num_lit, path_or_identifier, skip_till,
Expand Down Expand Up @@ -51,32 +51,52 @@ impl<'a> Node<'a> {
}

fn parse(i: &'a str, s: &State<'_>) -> ParseResult<'a, Self> {
let mut p = delimited(
#[inline]
fn wrap<'a, T>(
func: impl FnOnce(T) -> Node<'a>,
result: ParseResult<'a, T>,
) -> ParseResult<'a, Node<'a>> {
result.map(|(i, n)| (i, func(n)))
}

let (j, tag) = preceded(
|i| s.tag_block_start(i),
alt((
map(|i| Call::parse(i, s), Self::Call),
map(|i| Let::parse(i, s), Self::Let),
map(|i| If::parse(i, s), Self::If),
map(|i| Loop::parse(i, s), |l| Self::Loop(Box::new(l))),
map(|i| Match::parse(i, s), Self::Match),
map(Extends::parse, Self::Extends),
map(Include::parse, Self::Include),
map(Import::parse, Self::Import),
map(|i| BlockDef::parse(i, s), Self::BlockDef),
map(|i| Macro::parse(i, s), Self::Macro),
map(|i| Raw::parse(i, s), Self::Raw),
|i| Self::r#break(i, s),
|i| Self::r#continue(i, s),
map(|i| FilterBlock::parse(i, s), Self::FilterBlock),
peek(preceded(
pair(opt(Whitespace::parse), take_till(not_ws)),
identifier,
)),
cut(|i| s.tag_block_end(i)),
);
)(i)?;

let func = match tag {
"call" => |i, s| wrap(Self::Call, Call::parse(i, s)),
"let" => |i, s| wrap(Self::Let, Let::parse(i, s)),
"if" => |i, s| wrap(Self::If, If::parse(i, s)),
"for" => |i, s| wrap(|n| Self::Loop(Box::new(n)), Loop::parse(i, s)),
"match" => |i, s| wrap(Self::Match, Match::parse(i, s)),
"extends" => |i, _s| wrap(Self::Extends, Extends::parse(i)),
"include" => |i, _s| wrap(Self::Include, Include::parse(i)),
"import" => |i, _s| wrap(Self::Import, Import::parse(i)),
"block" => |i, s| wrap(Self::BlockDef, BlockDef::parse(i, s)),
"macro" => |i, s| wrap(Self::Macro, Macro::parse(i, s)),
"raw" => |i, s| wrap(Self::Raw, Raw::parse(i, s)),
"break" => |i, s| Self::r#break(i, s),
"continue" => |i, s| Self::r#continue(i, s),
"filter" => |i, s| wrap(Self::FilterBlock, FilterBlock::parse(i, s)),
_ => {
return Err(ErrorContext::from_err(nom::Err::Error(error_position!(
i,
ErrorKind::Tag
))));
}
};

s.nest(i)?;
let result = p(i);
let (i, _) = s.nest(j)?;
let result = func(i, s);
s.leave();

result
let (i, node) = result?;
let (i, _) = cut(|i| s.tag_block_end(i))(i)?;
Ok((i, node))
}

fn r#break(i: &'a str, s: &State<'_>) -> ParseResult<'a, Self> {
Expand Down

0 comments on commit a9eb4b4

Please sign in to comment.