diff options
Diffstat (limited to 'askama_parser/src')
-rw-r--r-- | askama_parser/src/expr.rs | 114 |
1 files changed, 61 insertions, 53 deletions
diff --git a/askama_parser/src/expr.rs b/askama_parser/src/expr.rs index c5c2351..ea00d82 100644 --- a/askama_parser/src/expr.rs +++ b/askama_parser/src/expr.rs @@ -126,35 +126,70 @@ enum Suffix<'a> { Try, } -fn expr_attr(i: &str) -> IResult<&str, Suffix<'_>> { - map( +impl<'a> Suffix<'a> { + fn parse(i: &'a str) -> IResult<&'a str, Expr<'a>> { + let (mut i, mut expr) = expr_single(i)?; + loop { + let (j, suffix) = opt(alt(( + Self::attr, + Self::index, + Self::call, + Self::r#try, + Self::r#macro, + )))(i)?; + + match suffix { + Some(Self::Attr(attr)) => expr = Expr::Attr(expr.into(), attr), + Some(Self::Index(index)) => expr = Expr::Index(expr.into(), index.into()), + Some(Self::Call(args)) => expr = Expr::Call(expr.into(), args), + Some(Self::Try) => expr = Expr::Try(expr.into()), + Some(Self::MacroCall(args)) => match expr { + Expr::Path(path) => expr = Expr::RustMacro(path, args), + Expr::Var(name) => expr = Expr::RustMacro(vec![name], args), + _ => return Err(nom::Err::Failure(error_position!(i, ErrorKind::Tag))), + }, + None => break, + } + + i = j; + } + Ok((i, expr)) + } + + fn r#macro(i: &'a str) -> IResult<&'a str, Self> { preceded( - ws(pair(char('.'), not(char('.')))), - cut(alt((num_lit, identifier))), - ), - Suffix::Attr, - )(i) -} + pair(ws(char('!')), char('(')), + cut(terminated( + map(recognize(nested_parenthesis), Self::MacroCall), + char(')'), + )), + )(i) + } -fn expr_index(i: &str) -> IResult<&str, Suffix<'_>> { - map( - preceded(ws(char('[')), cut(terminated(expr_any, ws(char(']'))))), - Suffix::Index, - )(i) -} + fn attr(i: &'a str) -> IResult<&'a str, Self> { + map( + preceded( + ws(pair(char('.'), not(char('.')))), + cut(alt((num_lit, identifier))), + ), + Self::Attr, + )(i) + } -fn expr_call(i: &str) -> IResult<&str, Suffix<'_>> { - map(arguments, Suffix::Call)(i) -} + fn index(i: &'a str) -> IResult<&'a str, Self> { + map( + preceded(ws(char('[')), cut(terminated(expr_any, ws(char(']'))))), + Self::Index, + )(i) + } -fn expr_macro(i: &str) -> IResult<&str, Suffix<'_>> { - preceded( - pair(ws(char('!')), char('(')), - cut(terminated( - map(recognize(nested_parenthesis), Suffix::MacroCall), - char(')'), - )), - )(i) + fn call(i: &'a str) -> IResult<&'a str, Self> { + map(arguments, Self::Call)(i) + } + + fn r#try(i: &'a str) -> IResult<&'a str, Self> { + map(preceded(take_till(not_ws), char('?')), |_| Self::Try)(i) + } } fn nested_parenthesis(i: &str) -> IResult<&str, ()> { @@ -205,10 +240,6 @@ fn nested_parenthesis(i: &str) -> IResult<&str, ()> { } } -fn expr_try(i: &str) -> IResult<&str, Suffix<'_>> { - map(preceded(take_till(not_ws), char('?')), |_| Suffix::Try)(i) -} - fn filter(i: &str) -> IResult<&str, (&str, Option<Vec<Expr<'_>>>)> { let (i, (_, fname, args)) = tuple((char('|'), ws(identifier), opt(arguments)))(i)?; Ok((i, (fname, args))) @@ -233,36 +264,13 @@ fn expr_filtered(i: &str) -> IResult<&str, Expr<'_>> { } fn expr_prefix(i: &str) -> IResult<&str, Expr<'_>> { - let (i, (ops, mut expr)) = pair(many0(ws(alt((tag("!"), tag("-"))))), expr_suffix)(i)?; + let (i, (ops, mut expr)) = pair(many0(ws(alt((tag("!"), tag("-"))))), Suffix::parse)(i)?; for op in ops.iter().rev() { expr = Expr::Unary(op, Box::new(expr)); } Ok((i, expr)) } -fn expr_suffix(i: &str) -> IResult<&str, Expr<'_>> { - let (mut i, mut expr) = expr_single(i)?; - loop { - let (j, suffix) = opt(alt(( - expr_attr, expr_index, expr_call, expr_try, expr_macro, - )))(i)?; - match suffix { - Some(Suffix::Attr(attr)) => expr = Expr::Attr(expr.into(), attr), - Some(Suffix::Index(index)) => expr = Expr::Index(expr.into(), index.into()), - Some(Suffix::Call(args)) => expr = Expr::Call(expr.into(), args), - Some(Suffix::Try) => expr = Expr::Try(expr.into()), - Some(Suffix::MacroCall(args)) => match expr { - Expr::Path(path) => expr = Expr::RustMacro(path, args), - Expr::Var(name) => expr = Expr::RustMacro(vec![name], args), - _ => return Err(nom::Err::Failure(error_position!(i, ErrorKind::Tag))), - }, - None => break, - } - i = j; - } - Ok((i, expr)) -} - macro_rules! expr_prec_layer { ( $name:ident, $inner:ident, $op:expr ) => { fn $name(i: &str) -> IResult<&str, Expr<'_>> { |