From 913605499a2fd16acc8fff57901e1609acfc2beb Mon Sep 17 00:00:00 2001 From: Andrew Dona-Couch <hi@andrewcou.ch> Date: Tue, 28 Feb 2023 22:18:35 -0500 Subject: [PATCH] Extract askama_parser from askama_derive --- Cargo.toml | 1 + askama_derive/Cargo.toml | 1 + askama_derive/src/config.rs | 2 +- askama_derive/src/generator.rs | 4 +- askama_derive/src/heritage.rs | 4 +- askama_derive/src/input.rs | 2 +- askama_derive/src/lib.rs | 1 - askama_parser/Cargo.toml | 14 ++++++ .../src/parser => askama_parser/src}/error.rs | 2 +- .../src/parser => askama_parser/src}/expr.rs | 12 ++--- .../parser/mod.rs => askama_parser/src/lib.rs | 19 +++---- .../src/parser => askama_parser/src}/node.rs | 50 +++++++++---------- .../parser => askama_parser/src}/syntax.rs | 14 +++--- .../src/parser => askama_parser/src}/tests.rs | 0 14 files changed, 69 insertions(+), 57 deletions(-) create mode 100644 askama_parser/Cargo.toml rename {askama_derive/src/parser => askama_parser/src}/error.rs (95%) rename {askama_derive/src/parser => askama_parser/src}/expr.rs (97%) rename askama_derive/src/parser/mod.rs => askama_parser/src/lib.rs (96%) rename {askama_derive/src/parser => askama_parser/src}/node.rs (95%) rename {askama_derive/src/parser => askama_parser/src}/syntax.rs (54%) rename {askama_derive/src/parser => askama_parser/src}/tests.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index bd8b8daf5..b7f6fd6bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ members = [ "askama_derive", "askama_escape", "askama_mendes", + "askama_parser", "askama_rocket", "askama_tide", "askama_warp", diff --git a/askama_derive/Cargo.toml b/askama_derive/Cargo.toml index c13e7cafb..9715e615a 100644 --- a/askama_derive/Cargo.toml +++ b/askama_derive/Cargo.toml @@ -31,6 +31,7 @@ with-tide = [] with-warp = [] [dependencies] +askama_parser = { version = "0.1", path = "../askama_parser" } mime = "0.3" mime_guess = "2" nom = "7" diff --git a/askama_derive/src/config.rs b/askama_derive/src/config.rs index 639e3fea3..7196bb45b 100644 --- a/askama_derive/src/config.rs +++ b/askama_derive/src/config.rs @@ -6,7 +6,7 @@ use std::{env, fs}; #[cfg(feature = "serde")] use serde::Deserialize; -use crate::parser::{CompileError, Syntax}; +use askama_parser::{CompileError, Syntax}; #[derive(Debug)] pub(crate) struct Config<'a> { diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs index 95b1664a2..ebd8a8eb4 100644 --- a/askama_derive/src/generator.rs +++ b/askama_derive/src/generator.rs @@ -1,8 +1,8 @@ use crate::config::{get_template_source, read_config_file, Config, WhitespaceHandling}; use crate::heritage::{Context, Heritage}; use crate::input::{Print, Source, TemplateInput}; -use crate::parser::node::{Cond, CondTest, Loop, Node, Target, When, Whitespace, Ws}; -use crate::parser::{parse, CompileError, Expr}; +use askama_parser::node::{Cond, CondTest, Loop, Node, Target, When, Whitespace, Ws}; +use askama_parser::{parse, CompileError, Expr}; use proc_macro::TokenStream; use proc_macro2::Span; diff --git a/askama_derive/src/heritage.rs b/askama_derive/src/heritage.rs index 4ba8ec4a4..7c06d4992 100644 --- a/askama_derive/src/heritage.rs +++ b/askama_derive/src/heritage.rs @@ -2,8 +2,8 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; use crate::config::Config; -use crate::parser::error::CompileError; -use crate::parser::node::{Loop, Macro, Node}; +use askama_parser::error::CompileError; +use askama_parser::node::{Loop, Macro, Node}; pub(crate) struct Heritage<'a> { pub(crate) root: &'a Context<'a>, diff --git a/askama_derive/src/input.rs b/askama_derive/src/input.rs index 82cdd8933..5c842e0d1 100644 --- a/askama_derive/src/input.rs +++ b/askama_derive/src/input.rs @@ -1,6 +1,6 @@ use crate::config::Config; use crate::generator::TemplateArgs; -use crate::parser::{CompileError, Syntax}; +use askama_parser::{CompileError, Syntax}; use std::path::{Path, PathBuf}; use std::str::FromStr; diff --git a/askama_derive/src/lib.rs b/askama_derive/src/lib.rs index 6d7237072..439799eb4 100644 --- a/askama_derive/src/lib.rs +++ b/askama_derive/src/lib.rs @@ -8,7 +8,6 @@ mod config; mod generator; mod heritage; mod input; -mod parser; #[proc_macro_derive(Template, attributes(template))] pub fn derive_template(input: TokenStream) -> TokenStream { diff --git a/askama_parser/Cargo.toml b/askama_parser/Cargo.toml new file mode 100644 index 000000000..c38699e7e --- /dev/null +++ b/askama_parser/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "askama_parser" +version = "0.1.0" +description = "Askama template syntax parser" +homepage = "https://github.com/djc/askama" +repository = "https://github.com/djc/askama" +license = "MIT OR Apache-2.0" +workspace = ".." +readme = "../README.md" +edition = "2021" +rust-version = "1.58" + +[dependencies] +nom = "7" diff --git a/askama_derive/src/parser/error.rs b/askama_parser/src/error.rs similarity index 95% rename from askama_derive/src/parser/error.rs rename to askama_parser/src/error.rs index 27f449778..56b2060d5 100644 --- a/askama_derive/src/parser/error.rs +++ b/askama_parser/src/error.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::fmt; #[derive(Debug, Clone)] -pub(crate) struct CompileError { +pub struct CompileError { msg: Cow<'static, str>, } diff --git a/askama_derive/src/parser/expr.rs b/askama_parser/src/expr.rs similarity index 97% rename from askama_derive/src/parser/expr.rs rename to askama_parser/src/expr.rs index fabaa34cc..bb5ce48b5 100644 --- a/askama_derive/src/parser/expr.rs +++ b/askama_parser/src/expr.rs @@ -13,7 +13,7 @@ use super::{ }; #[derive(Debug, PartialEq)] -pub(crate) enum Expr<'a> { +pub enum Expr<'a> { BoolLit(&'a str), NumLit(&'a str), StrLit(&'a str), @@ -35,17 +35,17 @@ pub(crate) enum Expr<'a> { } impl Expr<'_> { - pub(super) fn parse(i: &str) -> IResult<&str, Expr<'_>> { + pub(crate) fn parse(i: &str) -> IResult<&str, Expr<'_>> { expr_any(i) } - pub(super) fn parse_arguments(i: &str) -> IResult<&str, Vec<Expr<'_>>> { + pub(crate) fn parse_arguments(i: &str) -> IResult<&str, Vec<Expr<'_>>> { arguments(i) } /// Returns `true` if enough assumptions can be made, /// to determine that `self` is copyable. - pub(crate) fn is_copyable(&self) -> bool { + pub fn is_copyable(&self) -> bool { self.is_copyable_within_op(false) } @@ -73,7 +73,7 @@ impl Expr<'_> { } /// Returns `true` if this is an `Attr` where the `obj` is `"self"`. - pub(crate) fn is_attr_self(&self) -> bool { + pub fn is_attr_self(&self) -> bool { match self { Expr::Attr(obj, _) if matches!(obj.as_ref(), Expr::Var("self")) => true, Expr::Attr(obj, _) if matches!(obj.as_ref(), Expr::Attr(..)) => obj.is_attr_self(), @@ -84,7 +84,7 @@ impl Expr<'_> { /// Returns `true` if the outcome of this expression may be used multiple times in the same /// `write!()` call, without evaluating the expression again, i.e. the expression should be /// side-effect free. - pub(crate) fn is_cacheable(&self) -> bool { + pub fn is_cacheable(&self) -> bool { match self { // Literals are the definition of pure: Expr::BoolLit(_) => true, diff --git a/askama_derive/src/parser/mod.rs b/askama_parser/src/lib.rs similarity index 96% rename from askama_derive/src/parser/mod.rs rename to askama_parser/src/lib.rs index a1d98580c..f1b2c0d3e 100644 --- a/askama_derive/src/parser/mod.rs +++ b/askama_parser/src/lib.rs @@ -11,15 +11,15 @@ use nom::multi::separated_list1; use nom::sequence::{delimited, pair, tuple}; use nom::{error_position, AsChar, IResult, InputTakeAtPosition}; -pub(crate) use self::error::CompileError; -pub(crate) use self::expr::Expr; +pub use self::error::CompileError; +pub use self::expr::Expr; use self::node::{Node, Whitespace}; -pub(crate) use self::syntax::Syntax; +pub use self::syntax::Syntax; -pub(crate) mod error; -pub(crate) mod expr; -pub(crate) mod node; -pub(crate) mod syntax; +pub mod error; +pub mod expr; +pub mod node; +pub mod syntax; #[cfg(test)] mod tests; @@ -60,10 +60,7 @@ impl From<char> for Whitespace { } } -pub(crate) fn parse<'a>( - src: &'a str, - syntax: &'a Syntax<'_>, -) -> Result<Vec<Node<'a>>, CompileError> { +pub fn parse<'a>(src: &'a str, syntax: &'a Syntax<'_>) -> Result<Vec<Node<'a>>, CompileError> { match Node::parse(src, &State::new(syntax)) { Ok((left, res)) => { if !left.is_empty() { diff --git a/askama_derive/src/parser/node.rs b/askama_parser/src/node.rs similarity index 95% rename from askama_derive/src/parser/node.rs rename to askama_parser/src/node.rs index 9f8b37ba0..7b6a009aa 100644 --- a/askama_derive/src/parser/node.rs +++ b/askama_parser/src/node.rs @@ -16,7 +16,7 @@ use super::{ }; #[derive(Debug, PartialEq)] -pub(crate) enum Node<'a> { +pub enum Node<'a> { Lit(&'a str, &'a str, &'a str), Comment(Ws), Expr(Ws, Expr<'a>), @@ -37,7 +37,7 @@ pub(crate) enum Node<'a> { } #[derive(Debug, PartialEq)] -pub(crate) enum Target<'a> { +pub enum Target<'a> { Name(&'a str), Tuple(Vec<&'a str>, Vec<Target<'a>>), Struct(Vec<&'a str>, Vec<(&'a str, Target<'a>)>), @@ -49,56 +49,56 @@ pub(crate) enum Target<'a> { } #[derive(Clone, Copy, Debug, PartialEq)] -pub(crate) enum Whitespace { +pub enum Whitespace { Preserve, Suppress, Minimize, } #[derive(Debug, PartialEq)] -pub(crate) struct Loop<'a> { - pub(crate) ws1: Ws, - pub(crate) var: Target<'a>, - pub(crate) iter: Expr<'a>, - pub(crate) cond: Option<Expr<'a>>, - pub(crate) body: Vec<Node<'a>>, - pub(crate) ws2: Ws, - pub(crate) else_block: Vec<Node<'a>>, - pub(crate) ws3: Ws, +pub struct Loop<'a> { + pub ws1: Ws, + pub var: Target<'a>, + pub iter: Expr<'a>, + pub cond: Option<Expr<'a>>, + pub body: Vec<Node<'a>>, + pub ws2: Ws, + pub else_block: Vec<Node<'a>>, + pub ws3: Ws, } -pub(crate) type When<'a> = (Ws, Target<'a>, Vec<Node<'a>>); +pub type When<'a> = (Ws, Target<'a>, Vec<Node<'a>>); #[derive(Debug, PartialEq)] -pub(crate) struct Macro<'a> { - pub(crate) ws1: Ws, - pub(crate) args: Vec<&'a str>, - pub(crate) nodes: Vec<Node<'a>>, - pub(crate) ws2: Ws, +pub struct Macro<'a> { + pub ws1: Ws, + pub args: Vec<&'a str>, + pub nodes: Vec<Node<'a>>, + pub ws2: Ws, } /// First field is "minus/plus sign was used on the left part of the item". /// /// Second field is "minus/plus sign was used on the right part of the item". #[derive(Clone, Copy, Debug, PartialEq)] -pub(crate) struct Ws(pub(crate) Option<Whitespace>, pub(crate) Option<Whitespace>); +pub struct Ws(pub Option<Whitespace>, pub Option<Whitespace>); -pub(crate) type Cond<'a> = (Ws, Option<CondTest<'a>>, Vec<Node<'a>>); +pub type Cond<'a> = (Ws, Option<CondTest<'a>>, Vec<Node<'a>>); #[derive(Debug, PartialEq)] -pub(crate) struct CondTest<'a> { - pub(crate) target: Option<Target<'a>>, - pub(crate) expr: Expr<'a>, +pub struct CondTest<'a> { + pub target: Option<Target<'a>>, + pub expr: Expr<'a>, } impl Node<'_> { - pub(super) fn parse<'a>(i: &'a str, s: &State<'_>) -> IResult<&'a str, Vec<Node<'a>>> { + pub(crate) fn parse<'a>(i: &'a str, s: &State<'_>) -> IResult<&'a str, Vec<Node<'a>>> { parse_template(i, s) } } impl Target<'_> { - pub(super) fn parse(i: &str) -> IResult<&str, Target<'_>> { + pub(crate) fn parse(i: &str) -> IResult<&str, Target<'_>> { target(i) } } diff --git a/askama_derive/src/parser/syntax.rs b/askama_parser/src/syntax.rs similarity index 54% rename from askama_derive/src/parser/syntax.rs rename to askama_parser/src/syntax.rs index 51c563a01..1ec0d448b 100644 --- a/askama_derive/src/parser/syntax.rs +++ b/askama_parser/src/syntax.rs @@ -1,11 +1,11 @@ #[derive(Debug)] -pub(crate) struct Syntax<'a> { - pub(crate) block_start: &'a str, - pub(crate) block_end: &'a str, - pub(crate) expr_start: &'a str, - pub(crate) expr_end: &'a str, - pub(crate) comment_start: &'a str, - pub(crate) comment_end: &'a str, +pub struct Syntax<'a> { + pub block_start: &'a str, + pub block_end: &'a str, + pub expr_start: &'a str, + pub expr_end: &'a str, + pub comment_start: &'a str, + pub comment_end: &'a str, } impl Default for Syntax<'static> { diff --git a/askama_derive/src/parser/tests.rs b/askama_parser/src/tests.rs similarity index 100% rename from askama_derive/src/parser/tests.rs rename to askama_parser/src/tests.rs