From e40e93796f45d34d038c6a20c4b034eb3b384b12 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Sat, 1 Jul 2023 16:00:06 +0200 Subject: Extract askama_parser crate --- askama_derive/src/parser/expr.rs | 285 --------------------------------------- 1 file changed, 285 deletions(-) delete mode 100644 askama_derive/src/parser/expr.rs (limited to 'askama_derive/src/parser/expr.rs') diff --git a/askama_derive/src/parser/expr.rs b/askama_derive/src/parser/expr.rs deleted file mode 100644 index deefb48..0000000 --- a/askama_derive/src/parser/expr.rs +++ /dev/null @@ -1,285 +0,0 @@ -use std::str; - -use nom::branch::alt; -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::multi::{fold_many0, many0, separated_list0, separated_list1}; -use nom::sequence::{delimited, pair, preceded, terminated, tuple}; -use nom::{error_position, IResult}; - -use super::{ - bool_lit, char_lit, identifier, nested_parenthesis, not_ws, num_lit, path, str_lit, ws, -}; - -#[derive(Debug, PartialEq)] -pub(crate) enum Expr<'a> { - BoolLit(&'a str), - NumLit(&'a str), - StrLit(&'a str), - CharLit(&'a str), - Var(&'a str), - Path(Vec<&'a str>), - Array(Vec>), - Attr(Box>, &'a str), - Index(Box>, Box>), - Filter(&'a str, Vec>), - Unary(&'a str, Box>), - BinOp(&'a str, Box>, Box>), - Range(&'a str, Option>>, Option>>), - Group(Box>), - Tuple(Vec>), - Call(Box>, Vec>), - RustMacro(Vec<&'a str>, &'a str), - Try(Box>), -} - -impl Expr<'_> { - pub(super) fn parse(i: &str) -> IResult<&str, Expr<'_>> { - expr_any(i) - } - - pub(super) fn parse_arguments(i: &str) -> IResult<&str, Vec>> { - arguments(i) - } -} - -fn expr_bool_lit(i: &str) -> IResult<&str, Expr<'_>> { - map(bool_lit, Expr::BoolLit)(i) -} - -fn expr_num_lit(i: &str) -> IResult<&str, Expr<'_>> { - map(num_lit, Expr::NumLit)(i) -} - -fn expr_array_lit(i: &str) -> IResult<&str, Expr<'_>> { - delimited( - ws(char('[')), - map(separated_list1(ws(char(',')), expr_any), Expr::Array), - ws(char(']')), - )(i) -} - -fn expr_str_lit(i: &str) -> IResult<&str, Expr<'_>> { - map(str_lit, Expr::StrLit)(i) -} - -fn expr_char_lit(i: &str) -> IResult<&str, Expr<'_>> { - map(char_lit, Expr::CharLit)(i) -} - -fn expr_var(i: &str) -> IResult<&str, Expr<'_>> { - map(identifier, Expr::Var)(i) -} - -fn expr_path(i: &str) -> IResult<&str, Expr<'_>> { - let (i, path) = path(i)?; - Ok((i, Expr::Path(path))) -} - -fn expr_group(i: &str) -> IResult<&str, Expr<'_>> { - let (i, expr) = preceded(ws(char('(')), opt(expr_any))(i)?; - let expr = match expr { - Some(expr) => expr, - None => { - let (i, _) = char(')')(i)?; - return Ok((i, Expr::Tuple(vec![]))); - } - }; - - let (i, comma) = ws(opt(peek(char(','))))(i)?; - if comma.is_none() { - let (i, _) = char(')')(i)?; - return Ok((i, Expr::Group(Box::new(expr)))); - } - - let mut exprs = vec![expr]; - let (i, _) = fold_many0( - preceded(char(','), ws(expr_any)), - || (), - |_, expr| { - exprs.push(expr); - }, - )(i)?; - let (i, _) = pair(ws(opt(char(','))), char(')'))(i)?; - Ok((i, Expr::Tuple(exprs))) -} - -fn expr_single(i: &str) -> IResult<&str, Expr<'_>> { - alt(( - expr_bool_lit, - expr_num_lit, - expr_str_lit, - expr_char_lit, - expr_path, - expr_array_lit, - expr_var, - expr_group, - ))(i) -} - -enum Suffix<'a> { - Attr(&'a str), - Index(Expr<'a>), - Call(Vec>), - // The value is the arguments of the macro call. - MacroCall(&'a str), - Try, -} - -fn expr_attr(i: &str) -> IResult<&str, Suffix<'_>> { - map( - preceded( - ws(pair(char('.'), not(char('.')))), - cut(alt((num_lit, identifier))), - ), - Suffix::Attr, - )(i) -} - -fn expr_index(i: &str) -> IResult<&str, Suffix<'_>> { - map( - preceded(ws(char('[')), cut(terminated(expr_any, ws(char(']'))))), - Suffix::Index, - )(i) -} - -fn expr_call(i: &str) -> IResult<&str, Suffix<'_>> { - map(arguments, Suffix::Call)(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 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>>)> { - let (i, (_, fname, args)) = tuple((char('|'), ws(identifier), opt(arguments)))(i)?; - Ok((i, (fname, args))) -} - -fn expr_filtered(i: &str) -> IResult<&str, Expr<'_>> { - let (i, (obj, filters)) = tuple((expr_prefix, many0(filter)))(i)?; - - let mut res = obj; - for (fname, args) in filters { - res = Expr::Filter(fname, { - let mut args = match args { - Some(inner) => inner, - None => Vec::new(), - }; - args.insert(0, res); - args - }); - } - - Ok((i, res)) -} - -fn expr_prefix(i: &str) -> IResult<&str, Expr<'_>> { - let (i, (ops, mut expr)) = pair(many0(ws(alt((tag("!"), tag("-"))))), expr_suffix)(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<'_>> { - let (i, left) = $inner(i)?; - let (i, right) = many0(pair( - ws(tag($op)), - $inner, - ))(i)?; - Ok(( - i, - right.into_iter().fold(left, |left, (op, right)| { - Expr::BinOp(op, Box::new(left), Box::new(right)) - }), - )) - } - }; - ( $name:ident, $inner:ident, $( $op:expr ),+ ) => { - fn $name(i: &str) -> IResult<&str, Expr<'_>> { - let (i, left) = $inner(i)?; - let (i, right) = many0(pair( - ws(alt(($( tag($op) ),+,))), - $inner, - ))(i)?; - Ok(( - i, - right.into_iter().fold(left, |left, (op, right)| { - Expr::BinOp(op, Box::new(left), Box::new(right)) - }), - )) - } - } -} - -expr_prec_layer!(expr_muldivmod, expr_filtered, "*", "/", "%"); -expr_prec_layer!(expr_addsub, expr_muldivmod, "+", "-"); -expr_prec_layer!(expr_shifts, expr_addsub, ">>", "<<"); -expr_prec_layer!(expr_band, expr_shifts, "&"); -expr_prec_layer!(expr_bxor, expr_band, "^"); -expr_prec_layer!(expr_bor, expr_bxor, "|"); -expr_prec_layer!(expr_compare, expr_bor, "==", "!=", ">=", ">", "<=", "<"); -expr_prec_layer!(expr_and, expr_compare, "&&"); -expr_prec_layer!(expr_or, expr_and, "||"); - -fn expr_any(i: &str) -> IResult<&str, Expr<'_>> { - let range_right = |i| pair(ws(alt((tag("..="), tag("..")))), opt(expr_or))(i); - alt(( - map(range_right, |(op, right)| { - Expr::Range(op, None, right.map(Box::new)) - }), - map( - pair(expr_or, opt(range_right)), - |(left, right)| match right { - Some((op, right)) => Expr::Range(op, Some(Box::new(left)), right.map(Box::new)), - None => left, - }, - ), - ))(i) -} - -fn arguments(i: &str) -> IResult<&str, Vec>> { - delimited( - ws(char('(')), - separated_list0(char(','), ws(expr_any)), - ws(char(')')), - )(i) -} -- cgit