Skip to content

Commit

Permalink
Create a type alias for all IResult to simplify code reading
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillaumeGomez authored and djc committed Oct 25, 2023
1 parent 77d5d28 commit 7646225
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 108 deletions.
52 changes: 23 additions & 29 deletions askama_parser/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ use nom::bytes::complete::{tag, take_till};
use nom::character::complete::char;
use nom::combinator::{cut, map, not, opt, peek, recognize};
use nom::error::ErrorKind;
use nom::error_position;
use nom::multi::{fold_many0, many0, separated_list0};
use nom::sequence::{pair, preceded, terminated, tuple};
use nom::{error_position, IResult};

use super::{
char_lit, identifier, not_ws, num_lit, path_or_identifier, str_lit, ws, Level, PathOrIdentifier,
};
use crate::ErrorContext;
use crate::ParseResult;

macro_rules! expr_prec_layer {
( $name:ident, $inner:ident, $op:expr ) => {
fn $name(i: &'a str, level: Level) -> IResult<&'a str, Self, ErrorContext<&'a str>> {
fn $name(i: &'a str, level: Level) -> ParseResult<'a, Self> {
let (_, level) = level.nest(i)?;
let (i, left) = Self::$inner(i, level)?;
let (i, right) = many0(pair(
Expand All @@ -32,7 +32,7 @@ macro_rules! expr_prec_layer {
}
};
( $name:ident, $inner:ident, $( $op:expr ),+ ) => {
fn $name(i: &'a str, level: Level) -> IResult<&'a str, Self, ErrorContext<&'a str>> {
fn $name(i: &'a str, level: Level) -> ParseResult<'a, Self> {
let (_, level) = level.nest(i)?;
let (i, left) = Self::$inner(i, level)?;
let (i, right) = many0(pair(
Expand Down Expand Up @@ -72,10 +72,7 @@ pub enum Expr<'a> {
}

impl<'a> Expr<'a> {
pub(super) fn arguments(
i: &'a str,
level: Level,
) -> IResult<&'a str, Vec<Self>, ErrorContext<&'a str>> {
pub(super) fn arguments(i: &'a str, level: Level) -> ParseResult<'a, Vec<Self>> {
let (_, level) = level.nest(i)?;
preceded(
ws(char('(')),
Expand All @@ -86,7 +83,7 @@ impl<'a> Expr<'a> {
)(i)
}

pub(super) fn parse(i: &'a str, level: Level) -> IResult<&'a str, Self, ErrorContext<&'a str>> {
pub(super) fn parse(i: &'a str, level: Level) -> ParseResult<'a, Self> {
let (_, level) = level.nest(i)?;
let range_right = move |i| {
pair(
Expand Down Expand Up @@ -118,13 +115,10 @@ impl<'a> Expr<'a> {
expr_prec_layer!(addsub, muldivmod, "+", "-");
expr_prec_layer!(muldivmod, filtered, "*", "/", "%");

fn filtered(i: &'a str, level: Level) -> IResult<&'a str, Self, ErrorContext<&'a str>> {
fn filtered(i: &'a str, level: Level) -> ParseResult<'a, Self> {
let (_, level) = level.nest(i)?;
#[allow(clippy::type_complexity)]
fn filter(
i: &str,
level: Level,
) -> IResult<&str, (&str, Option<Vec<Expr<'_>>>), ErrorContext<&str>> {
fn filter(i: &str, level: Level) -> ParseResult<'_, (&str, Option<Vec<Expr<'_>>>)> {
let (i, (_, fname, args)) = tuple((
char('|'),
ws(identifier),
Expand All @@ -151,7 +145,7 @@ impl<'a> Expr<'a> {
Ok((i, res))
}

fn prefix(i: &'a str, level: Level) -> IResult<&'a str, Self, ErrorContext<&'a str>> {
fn prefix(i: &'a str, level: Level) -> ParseResult<'a, Self> {
let (_, level) = level.nest(i)?;
let (i, (ops, mut expr)) = pair(many0(ws(alt((tag("!"), tag("-"))))), |i| {
Suffix::parse(i, level)
Expand All @@ -162,7 +156,7 @@ impl<'a> Expr<'a> {
Ok((i, expr))
}

fn single(i: &'a str, level: Level) -> IResult<&'a str, Self, ErrorContext<&'a str>> {
fn single(i: &'a str, level: Level) -> ParseResult<'a, Self> {
let (_, level) = level.nest(i)?;
alt((
Self::num,
Expand All @@ -174,7 +168,7 @@ impl<'a> Expr<'a> {
))(i)
}

fn group(i: &'a str, level: Level) -> IResult<&'a str, Self, ErrorContext<&'a str>> {
fn group(i: &'a str, level: Level) -> ParseResult<'a, Self> {
let (_, level) = level.nest(i)?;
let (i, expr) = preceded(ws(char('(')), opt(|i| Self::parse(i, level)))(i)?;
let expr = match expr {
Expand Down Expand Up @@ -203,7 +197,7 @@ impl<'a> Expr<'a> {
Ok((i, Self::Tuple(exprs)))
}

fn array(i: &'a str, level: Level) -> IResult<&'a str, Self, ErrorContext<&'a str>> {
fn array(i: &'a str, level: Level) -> ParseResult<'a, Self> {
let (_, level) = level.nest(i)?;
preceded(
ws(char('[')),
Expand All @@ -217,7 +211,7 @@ impl<'a> Expr<'a> {
)(i)
}

fn path_var_bool(i: &'a str) -> IResult<&'a str, Self, ErrorContext<&'a str>> {
fn path_var_bool(i: &'a str) -> ParseResult<'a, Self> {
map(path_or_identifier, |v| match v {
PathOrIdentifier::Path(v) => Self::Path(v),
PathOrIdentifier::Identifier(v @ "true") => Self::BoolLit(v),
Expand All @@ -226,15 +220,15 @@ impl<'a> Expr<'a> {
})(i)
}

fn str(i: &'a str) -> IResult<&'a str, Self, ErrorContext<&'a str>> {
fn str(i: &'a str) -> ParseResult<'a, Self> {
map(str_lit, Self::StrLit)(i)
}

fn num(i: &'a str) -> IResult<&'a str, Self, ErrorContext<&'a str>> {
fn num(i: &'a str) -> ParseResult<'a, Self> {
map(num_lit, Self::NumLit)(i)
}

fn char(i: &'a str) -> IResult<&'a str, Self, ErrorContext<&'a str>> {
fn char(i: &'a str) -> ParseResult<'a, Self> {
map(char_lit, Self::CharLit)(i)
}
}
Expand All @@ -249,7 +243,7 @@ enum Suffix<'a> {
}

impl<'a> Suffix<'a> {
fn parse(i: &'a str, level: Level) -> IResult<&'a str, Expr<'a>, ErrorContext<&'a str>> {
fn parse(i: &'a str, level: Level) -> ParseResult<'a, Expr<'a>> {
let (_, level) = level.nest(i)?;
let (mut i, mut expr) = Expr::single(i, level)?;
loop {
Expand Down Expand Up @@ -279,8 +273,8 @@ impl<'a> Suffix<'a> {
Ok((i, expr))
}

fn r#macro(i: &'a str) -> IResult<&'a str, Self, ErrorContext<&'a str>> {
fn nested_parenthesis(input: &str) -> IResult<&str, (), ErrorContext<&str>> {
fn r#macro(i: &'a str) -> ParseResult<'a, Self> {
fn nested_parenthesis(input: &str) -> ParseResult<'_, ()> {
let mut nested = 0;
let mut last = 0;
let mut in_str = false;
Expand Down Expand Up @@ -337,7 +331,7 @@ impl<'a> Suffix<'a> {
)(i)
}

fn attr(i: &'a str) -> IResult<&'a str, Self, ErrorContext<&'a str>> {
fn attr(i: &'a str) -> ParseResult<'a, Self> {
map(
preceded(
ws(pair(char('.'), not(char('.')))),
Expand All @@ -347,7 +341,7 @@ impl<'a> Suffix<'a> {
)(i)
}

fn index(i: &'a str, level: Level) -> IResult<&'a str, Self, ErrorContext<&'a str>> {
fn index(i: &'a str, level: Level) -> ParseResult<'a, Self> {
let (_, level) = level.nest(i)?;
map(
preceded(
Expand All @@ -358,12 +352,12 @@ impl<'a> Suffix<'a> {
)(i)
}

fn call(i: &'a str, level: Level) -> IResult<&'a str, Self, ErrorContext<&'a str>> {
fn call(i: &'a str, level: Level) -> ParseResult<'a, Self> {
let (_, level) = level.nest(i)?;
map(move |i| Expr::arguments(i, level), Self::Call)(i)
}

fn r#try(i: &'a str) -> IResult<&'a str, Self, ErrorContext<&'a str>> {
fn r#try(i: &'a str) -> ParseResult<'a, Self> {
map(preceded(take_till(not_ws), char('?')), |_| Self::Try)(i)
}
}
71 changes: 34 additions & 37 deletions askama_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use nom::combinator::{cut, eof, map, opt, recognize};
use nom::error::{Error, ErrorKind, FromExternalError};
use nom::multi::many1;
use nom::sequence::{delimited, pair, preceded, terminated, tuple};
use nom::{error_position, AsChar, IResult, InputTakeAtPosition};
use nom::{error_position, AsChar, InputTakeAtPosition};

pub mod expr;
pub use expr::Expr;
Expand Down Expand Up @@ -129,41 +129,43 @@ impl fmt::Display for ParseError {
}
}

pub(crate) type ParseResult<'a, T = &'a str> = Result<(&'a str, T), nom::Err<ErrorContext<'a>>>;

/// This type is used to handle `nom` errors and in particular to add custom error messages.
/// It used to generate `ParserError`.
///
/// It cannot be used to replace `ParseError` because it expects a generic, which would make
/// `askama`'s users experience less good (since this generic is only needed for `nom`).
#[derive(Debug)]
pub(crate) struct ErrorContext<I> {
pub(crate) input: I,
pub(crate) struct ErrorContext<'a> {
pub(crate) input: &'a str,
pub(crate) message: Option<Cow<'static, str>>,
}

impl<I> nom::error::ParseError<I> for ErrorContext<I> {
fn from_error_kind(input: I, _code: ErrorKind) -> Self {
impl<'a> nom::error::ParseError<&'a str> for ErrorContext<'a> {
fn from_error_kind(input: &'a str, _code: ErrorKind) -> Self {
Self {
input,
message: None,
}
}

fn append(_: I, _: ErrorKind, other: Self) -> Self {
fn append(_: &'a str, _: ErrorKind, other: Self) -> Self {
other
}
}

impl<I, E: std::fmt::Display> FromExternalError<I, E> for ErrorContext<I> {
fn from_external_error(input: I, _kind: ErrorKind, e: E) -> Self {
impl<'a, E: std::fmt::Display> FromExternalError<&'a str, E> for ErrorContext<'a> {
fn from_external_error(input: &'a str, _kind: ErrorKind, e: E) -> Self {
Self {
input,
message: Some(Cow::Owned(e.to_string())),
}
}
}

impl<I> ErrorContext<I> {
pub(crate) fn from_err(error: nom::Err<Error<I>>) -> nom::Err<Self> {
impl<'a> ErrorContext<'a> {
pub(crate) fn from_err(error: nom::Err<Error<&'a str>>) -> nom::Err<Self> {
match error {
nom::Err::Incomplete(i) => nom::Err::Incomplete(i),
nom::Err::Failure(Error { input, .. }) => nom::Err::Failure(Self {
Expand All @@ -187,16 +189,16 @@ fn not_ws(c: char) -> bool {
}

fn ws<'a, O>(
inner: impl FnMut(&'a str) -> IResult<&'a str, O, ErrorContext<&'a str>>,
) -> impl FnMut(&'a str) -> IResult<&'a str, O, ErrorContext<&'a str>> {
inner: impl FnMut(&'a str) -> ParseResult<'a, O>,
) -> impl FnMut(&'a str) -> ParseResult<'a, O> {
delimited(take_till(not_ws), inner, take_till(not_ws))
}

/// Skips input until `end` was found, but does not consume it.
/// Returns tuple that would be returned when parsing `end`.
fn skip_till<'a, O>(
end: impl FnMut(&'a str) -> IResult<&'a str, O, ErrorContext<&'a str>>,
) -> impl FnMut(&'a str) -> IResult<&'a str, (&'a str, O), ErrorContext<&'a str>> {
end: impl FnMut(&'a str) -> ParseResult<'a, O>,
) -> impl FnMut(&'a str) -> ParseResult<'a, (&'a str, O)> {
enum Next<O> {
IsEnd(O),
NotEnd(char),
Expand All @@ -214,10 +216,8 @@ fn skip_till<'a, O>(
}
}

fn keyword<'a>(
k: &'a str,
) -> impl FnMut(&'a str) -> IResult<&'a str, &'a str, ErrorContext<&'a str>> {
move |i: &'a str| -> IResult<&'a str, &'a str, ErrorContext<&'a str>> {
fn keyword<'a>(k: &'a str) -> impl FnMut(&'a str) -> ParseResult<'_> {
move |i: &'a str| -> ParseResult<'a> {
let (j, v) = identifier(i)?;
if k == v {
Ok((j, v))
Expand All @@ -227,15 +227,15 @@ fn keyword<'a>(
}
}

fn identifier(input: &str) -> IResult<&str, &str, ErrorContext<&str>> {
fn start(s: &str) -> IResult<&str, &str, ErrorContext<&str>> {
fn identifier(input: &str) -> ParseResult<'_> {
fn start(s: &str) -> ParseResult<'_> {
s.split_at_position1_complete(
|c| !(c.is_alpha() || c == '_' || c >= '\u{0080}'),
nom::error::ErrorKind::Alpha,
)
}

fn tail(s: &str) -> IResult<&str, &str, ErrorContext<&str>> {
fn tail(s: &str) -> ParseResult<'_> {
s.split_at_position1_complete(
|c| !(c.is_alphanum() || c == '_' || c >= '\u{0080}'),
nom::error::ErrorKind::Alpha,
Expand All @@ -245,19 +245,19 @@ fn identifier(input: &str) -> IResult<&str, &str, ErrorContext<&str>> {
recognize(pair(start, opt(tail)))(input)
}

fn bool_lit(i: &str) -> IResult<&str, &str, ErrorContext<&str>> {
fn bool_lit(i: &str) -> ParseResult<'_> {
alt((keyword("false"), keyword("true")))(i)
}

fn num_lit(i: &str) -> IResult<&str, &str, ErrorContext<&str>> {
fn num_lit(i: &str) -> ParseResult<'_> {
recognize(tuple((
opt(char('-')),
digit1,
opt(pair(char('.'), digit1)),
)))(i)
}

fn str_lit(i: &str) -> IResult<&str, &str, ErrorContext<&str>> {
fn str_lit(i: &str) -> ParseResult<'_> {
let (i, s) = delimited(
char('"'),
opt(escaped(is_not("\\\""), '\\', anychar)),
Expand All @@ -266,7 +266,7 @@ fn str_lit(i: &str) -> IResult<&str, &str, ErrorContext<&str>> {
Ok((i, s.unwrap_or_default()))
}

fn char_lit(i: &str) -> IResult<&str, &str, ErrorContext<&str>> {
fn char_lit(i: &str) -> ParseResult<'_> {
let (i, s) = delimited(
char('\''),
opt(escaped(is_not("\\\'"), '\\', anychar)),
Expand All @@ -280,7 +280,7 @@ enum PathOrIdentifier<'a> {
Identifier(&'a str),
}

fn path_or_identifier(i: &str) -> IResult<&str, PathOrIdentifier<'_>, ErrorContext<&str>> {
fn path_or_identifier(i: &str) -> ParseResult<'_, PathOrIdentifier<'_>> {
let root = ws(opt(tag("::")));
let tail = opt(many1(preceded(ws(tag("::")), identifier)));

Expand Down Expand Up @@ -326,7 +326,7 @@ impl<'a> State<'a> {
}
}

fn nest<'b>(&self, i: &'b str) -> IResult<&'b str, (), ErrorContext<&'b str>> {
fn nest<'b>(&self, i: &'b str) -> ParseResult<'b, ()> {
let (_, level) = self.level.get().nest(i)?;
self.level.set(level);
Ok((i, ()))
Expand All @@ -336,30 +336,27 @@ impl<'a> State<'a> {
self.level.set(self.level.get().leave());
}

fn tag_block_start<'i>(&self, i: &'i str) -> IResult<&'i str, &'i str, ErrorContext<&'i str>> {
fn tag_block_start<'i>(&self, i: &'i str) -> ParseResult<'i> {
tag(self.syntax.block_start)(i)
}

fn tag_block_end<'i>(&self, i: &'i str) -> IResult<&'i str, &'i str, ErrorContext<&'i str>> {
fn tag_block_end<'i>(&self, i: &'i str) -> ParseResult<'i> {
tag(self.syntax.block_end)(i)
}

fn tag_comment_start<'i>(
&self,
i: &'i str,
) -> IResult<&'i str, &'i str, ErrorContext<&'i str>> {
fn tag_comment_start<'i>(&self, i: &'i str) -> ParseResult<'i> {
tag(self.syntax.comment_start)(i)
}

fn tag_comment_end<'i>(&self, i: &'i str) -> IResult<&'i str, &'i str, ErrorContext<&'i str>> {
fn tag_comment_end<'i>(&self, i: &'i str) -> ParseResult<'i> {
tag(self.syntax.comment_end)(i)
}

fn tag_expr_start<'i>(&self, i: &'i str) -> IResult<&'i str, &'i str, ErrorContext<&'i str>> {
fn tag_expr_start<'i>(&self, i: &'i str) -> ParseResult<'i> {
tag(self.syntax.expr_start)(i)
}

fn tag_expr_end<'i>(&self, i: &'i str) -> IResult<&'i str, &'i str, ErrorContext<&'i str>> {
fn tag_expr_end<'i>(&self, i: &'i str) -> ParseResult<'i> {
tag(self.syntax.expr_end)(i)
}

Expand Down Expand Up @@ -403,7 +400,7 @@ impl Default for Syntax<'static> {
pub(crate) struct Level(u8);

impl Level {
fn nest(self, i: &str) -> IResult<&str, Level, ErrorContext<&str>> {
fn nest(self, i: &str) -> ParseResult<'_, Level> {
if self.0 >= Self::MAX_DEPTH {
return Err(ErrorContext::from_err(nom::Err::Failure(error_position!(
i,
Expand Down
Loading

0 comments on commit 7646225

Please sign in to comment.