yarte_parser/
lib.rs

1#![allow(clippy::many_single_char_names, clippy::cognitive_complexity)]
2use std::ops::{Deref, DerefMut};
3use std::str;
4
5use serde::{Deserialize, Deserializer};
6use syn::parse::{Parse, ParseBuffer};
7
8#[macro_use]
9mod strnom;
10
11#[cfg(test)]
12mod test;
13
14mod error;
15mod expr_list;
16mod parse;
17mod pre_partials;
18pub mod source_map;
19mod stmt_local;
20
21use crate::source_map::S;
22
23pub use self::{
24    error::{emitter, ErrorMessage},
25    parse::*,
26    pre_partials::parse_partials,
27    stmt_local::StmtLocal,
28    strnom::Cursor,
29};
30
31pub type Ws = (bool, bool);
32
33#[derive(Debug, PartialEq, Clone, Deserialize)]
34pub struct Local(#[serde(deserialize_with = "de_local")] syn::Local);
35
36impl Deref for Local {
37    type Target = syn::Local;
38
39    fn deref(&self) -> &Self::Target {
40        &self.0
41    }
42}
43
44impl DerefMut for Local {
45    fn deref_mut(&mut self) -> &mut Self::Target {
46        &mut self.0
47    }
48}
49
50impl AsRef<syn::Local> for Local {
51    fn as_ref(&self) -> &syn::Local {
52        &self.0
53    }
54}
55
56impl AsMut<syn::Local> for Local {
57    fn as_mut(&mut self) -> &mut syn::Local {
58        &mut self.0
59    }
60}
61
62fn de_local<'de, D>(deserializer: D) -> Result<syn::Local, D::Error>
63where
64    D: Deserializer<'de>,
65{
66    <&str>::deserialize(deserializer).and_then(|x| {
67        syn::parse_str::<StmtLocal>(x)
68            .map(Into::into)
69            .map_err(|_| serde::de::Error::custom("Parse error"))
70    })
71}
72
73impl Parse for Local {
74    fn parse(input: &ParseBuffer<'_>) -> syn::Result<Self> {
75        Ok(Local(input.parse::<StmtLocal>()?.into()))
76    }
77}
78
79#[derive(Debug, PartialEq, Clone, Deserialize)]
80pub struct Expr(#[serde(deserialize_with = "de_expr")] syn::Expr);
81
82impl Deref for Expr {
83    type Target = syn::Expr;
84
85    fn deref(&self) -> &Self::Target {
86        &self.0
87    }
88}
89
90impl DerefMut for Expr {
91    fn deref_mut(&mut self) -> &mut Self::Target {
92        &mut self.0
93    }
94}
95
96impl AsRef<syn::Expr> for Expr {
97    fn as_ref(&self) -> &syn::Expr {
98        &self.0
99    }
100}
101
102impl AsMut<syn::Expr> for Expr {
103    fn as_mut(&mut self) -> &mut syn::Expr {
104        &mut self.0
105    }
106}
107
108fn de_expr<'de, D>(deserializer: D) -> Result<syn::Expr, D::Error>
109where
110    D: Deserializer<'de>,
111{
112    <&str>::deserialize(deserializer)
113        .and_then(|x| syn::parse_str(x).map_err(|_| serde::de::Error::custom("Parse error")))
114}
115
116impl Parse for Expr {
117    fn parse(input: &ParseBuffer<'_>) -> syn::Result<Self> {
118        Ok(Expr(input.parse()?))
119    }
120}
121
122pub type SExpr = S<Box<Expr>>;
123pub type SLocal = S<Box<Local>>;
124pub type SNode<'a> = S<Node<'a>>;
125pub type SStr<'a> = S<&'a str>;
126pub type SVExpr = S<Vec<Expr>>;
127
128#[derive(Debug, PartialEq, Clone, Deserialize)]
129pub struct Partial<'a>(pub Ws, #[serde(borrow)] pub SStr<'a>, pub SVExpr);
130
131#[derive(Debug, PartialEq, Clone, Deserialize)]
132pub struct PartialBlock<'a>(
133    pub (Ws, Ws),
134    #[serde(borrow)] pub SStr<'a>,
135    pub SVExpr,
136    #[serde(borrow)] pub Vec<SNode<'a>>,
137);
138
139// TODO: reduce size
140#[derive(Debug, PartialEq, Clone, Deserialize)]
141pub enum Node<'a> {
142    Comment(#[serde(borrow)] &'a str),
143    Expr(Ws, SExpr),
144    AtHelper(Ws, AtHelperKind, SVExpr),
145    RExpr(Ws, SExpr),
146    Helper(#[serde(borrow)] Box<Helper<'a>>),
147    Lit(
148        #[serde(borrow)] &'a str,
149        #[serde(borrow)] SStr<'a>,
150        #[serde(borrow)] &'a str,
151    ),
152    Local(SLocal),
153    Partial(#[serde(borrow)] Partial<'a>),
154    PartialBlock(#[serde(borrow)] PartialBlock<'a>),
155    Block(Ws),
156    Raw(
157        (Ws, Ws),
158        #[serde(borrow)] &'a str,
159        #[serde(borrow)] SStr<'a>,
160        #[serde(borrow)] &'a str,
161    ),
162    Safe(Ws, SExpr),
163    Error(SVExpr),
164}
165
166pub(crate) const JSON: &str = "json";
167pub(crate) const JSON_PRETTY: &str = "json_pretty";
168#[derive(Debug, PartialEq, Clone, Deserialize)]
169pub enum AtHelperKind {
170    Json,
171    JsonPretty,
172}
173
174#[derive(Debug, PartialEq, Clone, Deserialize)]
175pub enum Helper<'a> {
176    Each((Ws, Ws), SExpr, #[serde(borrow)] Vec<SNode<'a>>),
177    If(
178        ((Ws, Ws), SExpr, Vec<SNode<'a>>),
179        Vec<(Ws, SExpr, Vec<SNode<'a>>)>,
180        Option<(Ws, Vec<SNode<'a>>)>,
181    ),
182    With((Ws, Ws), SExpr, #[serde(borrow)] Vec<SNode<'a>>),
183    Unless((Ws, Ws), SExpr, #[serde(borrow)] Vec<SNode<'a>>),
184    // TODO:
185    Defined(
186        (Ws, Ws),
187        #[serde(borrow)] &'a str,
188        SExpr,
189        #[serde(borrow)] Vec<SNode<'a>>,
190    ),
191}