aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar René Kijewski <rene.kijewski@fu-berlin.de>2023-08-01 03:45:32 +0200
committerLibravatar Dirkjan Ochtman <dirkjan@ochtman.nl>2023-08-01 13:04:41 +0200
commit7b7c38b37785b83ce28f1cc5f6e89abb89672276 (patch)
treea16abd0f5e877184837adc032db0d3e0cf66b978
parent26f598c0d189769952b11ea9fe6168718f403590 (diff)
downloadaskama-7b7c38b37785b83ce28f1cc5f6e89abb89672276.tar.gz
askama-7b7c38b37785b83ce28f1cc5f6e89abb89672276.tar.bz2
askama-7b7c38b37785b83ce28f1cc5f6e89abb89672276.zip
parser: add type for `Node::Lit`
-rw-r--r--askama_derive/src/generator.rs13
-rw-r--r--askama_parser/src/lib.rs10
-rw-r--r--askama_parser/src/node.rs77
-rw-r--r--askama_parser/src/tests.rs16
4 files changed, 61 insertions, 55 deletions
diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs
index beb3c49..5711c36 100644
--- a/askama_derive/src/generator.rs
+++ b/askama_derive/src/generator.rs
@@ -2,7 +2,7 @@ use crate::config::{get_template_source, read_config_file, Config, WhitespaceHan
use crate::heritage::{Context, Heritage};
use crate::input::{Print, Source, TemplateInput};
use crate::CompileError;
-use parser::{Call, Cond, CondTest, Expr, Loop, Match, Node, Parsed, Target, Whitespace, Ws};
+use parser::{Call, Cond, CondTest, Expr, Lit, Loop, Match, Node, Parsed, Target, Whitespace, Ws};
use proc_macro::TokenStream;
use quote::{quote, ToTokens};
@@ -626,8 +626,8 @@ impl<'a> Generator<'a> {
let mut size_hint = 0;
for n in nodes {
match *n {
- Node::Lit(lws, val, rws) => {
- self.visit_lit(lws, val, rws);
+ Node::Lit(ref lit) => {
+ self.visit_lit(lit);
}
Node::Comment(ws) => {
self.write_comment(ws);
@@ -666,9 +666,9 @@ impl<'a> Generator<'a> {
self.flush_ws(m.ws1);
self.prepare_ws(m.ws2);
}
- Node::Raw(ws1, lws, val, rws, ws2) => {
+ Node::Raw(ws1, ref lit, ws2) => {
self.handle_ws(ws1);
- self.visit_lit(lws, val, rws);
+ self.visit_lit(lit);
self.handle_ws(ws2);
}
Node::Import(ref i) => {
@@ -1274,8 +1274,9 @@ impl<'a> Generator<'a> {
Ok(size_hint)
}
- fn visit_lit(&mut self, lws: &'a str, val: &'a str, rws: &'a str) {
+ fn visit_lit(&mut self, lit: &'a Lit<'_>) {
assert!(self.next_ws.is_none());
+ let Lit { lws, val, rws } = *lit;
if !lws.is_empty() {
match self.skip_ws {
WhitespaceHandling::Suppress => {}
diff --git a/askama_parser/src/lib.rs b/askama_parser/src/lib.rs
index d095f65..8138a19 100644
--- a/askama_parser/src/lib.rs
+++ b/askama_parser/src/lib.rs
@@ -16,7 +16,8 @@ use nom::{error_position, AsChar, IResult, InputTakeAtPosition};
pub use self::expr::Expr;
pub use self::node::{
- BlockDef, Call, Cond, CondTest, Import, Loop, Macro, Match, Node, Target, When, Whitespace, Ws,
+ BlockDef, Call, Cond, CondTest, Import, Lit, Loop, Macro, Match, Node, Target, When,
+ Whitespace, Ws,
};
mod expr;
@@ -138,13 +139,6 @@ fn ws<'a, O>(
delimited(take_till(not_ws), inner, take_till(not_ws))
}
-fn split_ws_parts(s: &str) -> Node<'_> {
- let trimmed_start = s.trim_start_matches(is_ws);
- let len_start = s.len() - trimmed_start.len();
- let trimmed = trimmed_start.trim_end_matches(is_ws);
- Node::Lit(&s[..len_start], trimmed, &trimmed_start[trimmed.len()..])
-}
-
/// 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>(
diff --git a/askama_parser/src/node.rs b/askama_parser/src/node.rs
index a8325ef..a743b53 100644
--- a/askama_parser/src/node.rs
+++ b/askama_parser/src/node.rs
@@ -10,13 +10,13 @@ use nom::sequence::{delimited, pair, preceded, terminated, tuple};
use nom::{error_position, IResult};
use super::{
- bool_lit, char_lit, identifier, keyword, num_lit, path, skip_till, split_ws_parts, str_lit, ws,
- Expr, State,
+ bool_lit, char_lit, identifier, is_ws, keyword, num_lit, path, skip_till, str_lit, ws, Expr,
+ State,
};
#[derive(Debug, PartialEq)]
pub enum Node<'a> {
- Lit(&'a str, &'a str, &'a str),
+ Lit(Lit<'a>),
Comment(Ws),
Expr(Ws, Expr<'a>),
Call(Call<'a>),
@@ -30,7 +30,7 @@ pub enum Node<'a> {
Include(Ws, &'a str),
Import(Import<'a>),
Macro(Macro<'a>),
- Raw(Ws, &'a str, &'a str, &'a str, Ws),
+ Raw(Ws, Lit<'a>, Ws),
Break(Ws),
Continue(Ws),
}
@@ -38,33 +38,13 @@ pub enum Node<'a> {
impl<'a> Node<'a> {
pub(super) fn many(i: &'a str, s: &State<'_>) -> IResult<&'a str, Vec<Self>> {
many0(alt((
- complete(|i| Self::content(i, s)),
+ map(complete(|i| Lit::parse(i, s)), Self::Lit),
complete(|i| Self::comment(i, s)),
complete(|i| Self::expr(i, s)),
complete(|i| Self::parse(i, s)),
)))(i)
}
- fn content(i: &'a str, s: &State<'_>) -> IResult<&'a str, Self> {
- let p_start = alt((
- tag(s.syntax.block_start),
- tag(s.syntax.comment_start),
- tag(s.syntax.expr_start),
- ));
-
- let (i, _) = not(eof)(i)?;
- let (i, content) = opt(recognize(skip_till(p_start)))(i)?;
- let (i, content) = match content {
- Some("") => {
- // {block,comment,expr}_start follows immediately.
- return Err(nom::Err::Error(error_position!(i, ErrorKind::TakeUntil)));
- }
- Some(content) => (i, content),
- None => ("", i), // there is no {block,comment,expr}_start: take everything
- };
- Ok((i, split_ws_parts(content)))
- }
-
fn parse(i: &'a str, s: &State<'_>) -> IResult<&'a str, Self> {
let mut p = tuple((
|i| s.tag_block_start(i),
@@ -244,13 +224,10 @@ impl<'a> Node<'a> {
));
let (_, (pws1, _, (nws1, _, (contents, (i, (_, pws2, _, nws2, _)))))) = p(i)?;
- let (lws, val, rws) = match split_ws_parts(contents) {
- Node::Lit(lws, val, rws) => (lws, val, rws),
- _ => unreachable!(),
- };
+ let val = Lit::split_ws_parts(contents);
let ws1 = Ws(pws1, nws1);
let ws2 = Ws(pws2, nws2);
- Ok((i, Self::Raw(ws1, lws, val, rws, ws2)))
+ Ok((i, Self::Raw(ws1, val, ws2)))
}
fn r#break(i: &'a str, s: &State<'_>) -> IResult<&'a str, Self> {
@@ -795,6 +772,46 @@ impl<'a> BlockDef<'a> {
}
}
+#[derive(Debug, PartialEq)]
+pub struct Lit<'a> {
+ pub lws: &'a str,
+ pub val: &'a str,
+ pub rws: &'a str,
+}
+
+impl<'a> Lit<'a> {
+ fn parse(i: &'a str, s: &State<'_>) -> IResult<&'a str, Self> {
+ let p_start = alt((
+ tag(s.syntax.block_start),
+ tag(s.syntax.comment_start),
+ tag(s.syntax.expr_start),
+ ));
+
+ let (i, _) = not(eof)(i)?;
+ let (i, content) = opt(recognize(skip_till(p_start)))(i)?;
+ let (i, content) = match content {
+ Some("") => {
+ // {block,comment,expr}_start follows immediately.
+ return Err(nom::Err::Error(error_position!(i, ErrorKind::TakeUntil)));
+ }
+ Some(content) => (i, content),
+ None => ("", i), // there is no {block,comment,expr}_start: take everything
+ };
+ Ok((i, Self::split_ws_parts(content)))
+ }
+
+ pub(crate) fn split_ws_parts(s: &'a str) -> Self {
+ let trimmed_start = s.trim_start_matches(is_ws);
+ let len_start = s.len() - trimmed_start.len();
+ let trimmed = trimmed_start.trim_end_matches(is_ws);
+ Self {
+ lws: &s[..len_start],
+ val: trimmed,
+ rws: &trimmed_start[trimmed.len()..],
+ }
+ }
+}
+
/// 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".
diff --git a/askama_parser/src/tests.rs b/askama_parser/src/tests.rs
index 61aa279..4717652 100644
--- a/askama_parser/src/tests.rs
+++ b/askama_parser/src/tests.rs
@@ -1,16 +1,10 @@
-use super::{Ast, Expr, Node, Syntax, Whitespace, Ws};
+use super::{Ast, Expr, Lit, Node, Syntax, Whitespace, Ws};
fn check_ws_split(s: &str, res: &(&str, &str, &str)) {
- match super::split_ws_parts(s) {
- Node::Lit(lws, s, rws) => {
- assert_eq!(lws, res.0);
- assert_eq!(s, res.1);
- assert_eq!(rws, res.2);
- }
- _ => {
- panic!("fail");
- }
- }
+ let Lit { lws, val, rws } = Lit::split_ws_parts(s);
+ assert_eq!(lws, res.0);
+ assert_eq!(val, res.1);
+ assert_eq!(rws, res.2);
}
#[test]