Skip to main content

oak_django/parser/
element_type.rs

1use oak_core::{ElementType, UniversalElementRole};
2
3/// Element types for Django templates.
4#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub enum DjangoElementType {
7    /// The root element.
8    Root,
9    /// An identifier.
10    Identifier,
11    /// A variable expression: `{{ ... }}`.
12    Variable,
13    /// A tag: `{% ... %}`.
14    Tag,
15    /// A comment: `{# ... #}`.
16    Comment,
17    /// Plain HTML content.
18    HtmlContent,
19
20    /// `if` keyword.
21    If,
22    /// `elif` keyword.
23    Elif,
24    /// `else` keyword.
25    Else,
26    /// `endif` keyword.
27    Endif,
28    /// `for` keyword.
29    For,
30    /// `empty` keyword.
31    Empty,
32    /// `endfor` keyword.
33    Endfor,
34    /// `block` keyword.
35    Block,
36    /// `endblock` keyword.
37    Endblock,
38    /// `extends` keyword.
39    Extends,
40    /// `include` keyword.
41    Include,
42    /// `load` keyword.
43    Load,
44    /// `with` keyword.
45    With,
46    /// `endwith` keyword.
47    Endwith,
48    /// `autoescape` keyword.
49    Autoescape,
50    /// `endautoescape` keyword.
51    Endautoescape,
52    /// `csrf_token` keyword.
53    Csrf,
54    /// `url` keyword.
55    Url,
56    /// `static` keyword.
57    Static,
58    /// `now` keyword.
59    Now,
60    /// `cycle` keyword.
61    Cycle,
62    /// `filter` keyword.
63    Filter,
64    /// `endfilter` keyword.
65    Endfilter,
66    /// `spaceless` keyword.
67    Spaceless,
68    /// `endspaceless` keyword.
69    Endspaceless,
70    /// `verbatim` keyword.
71    Verbatim,
72    /// `endverbatim` keyword.
73    Endverbatim,
74    /// `and` operator.
75    And,
76    /// `or` operator.
77    Or,
78    /// `not` operator.
79    Not,
80    /// `in` operator.
81    In,
82
83    /// `+`.
84    Plus,
85    /// `-`.
86    Minus,
87    /// `*`.
88    Star,
89    /// `/`.
90    Slash,
91    /// `(`.
92    LeftParen,
93    /// `)`.
94    RightParen,
95    /// `[`.
96    LeftBracket,
97    /// `]`.
98    RightBracket,
99    /// `;`.
100    Semicolon,
101    /// `.`.
102    Dot,
103    /// `,`.
104    Comma,
105    /// `=`.
106    Equal,
107
108    // Grammar constructs
109    /// If statement node.
110    IfStatement,
111    /// For statement node.
112    ForStatement,
113    /// Block statement node.
114    BlockStatement,
115    /// Filter expression node.
116    FilterExpression,
117    /// Binary expression node.
118    BinaryExpression,
119    /// Literal node.
120    Literal,
121
122    /// Whitespace.
123    Whitespace,
124    /// Newline.
125    Newline,
126    /// Error token.
127    Error,
128}
129
130impl DjangoElementType {
131    /// Returns true if the element type is a keyword.
132    pub fn is_keyword(&self) -> bool {
133        matches!(
134            self,
135            Self::If
136                | Self::Elif
137                | Self::Else
138                | Self::Endif
139                | Self::For
140                | Self::Empty
141                | Self::Endfor
142                | Self::Block
143                | Self::Endblock
144                | Self::Extends
145                | Self::Include
146                | Self::Load
147                | Self::With
148                | Self::Endwith
149                | Self::Autoescape
150                | Self::Endautoescape
151                | Self::Csrf
152                | Self::Url
153                | Self::Static
154                | Self::Now
155                | Self::Cycle
156                | Self::Filter
157                | Self::Endfilter
158                | Self::Spaceless
159                | Self::Endspaceless
160                | Self::Verbatim
161                | Self::Endverbatim
162                | Self::And
163                | Self::Or
164                | Self::Not
165                | Self::In
166        )
167    }
168
169    /// Returns true if the element type is trivia (whitespace, newline, or comment).
170    pub fn is_trivia(&self) -> bool {
171        matches!(self, Self::Whitespace | Self::Newline | Self::Comment)
172    }
173}
174
175impl ElementType for DjangoElementType {
176    type Role = UniversalElementRole;
177
178    fn role(&self) -> Self::Role {
179        match self {
180            Self::Root => UniversalElementRole::Root,
181            Self::Variable => UniversalElementRole::Expression,
182            Self::Tag => UniversalElementRole::Statement,
183            Self::Comment => UniversalElementRole::Documentation,
184            Self::HtmlContent => UniversalElementRole::Embedded,
185            Self::If
186            | Self::Elif
187            | Self::Else
188            | Self::Endif
189            | Self::For
190            | Self::Empty
191            | Self::Endfor
192            | Self::Block
193            | Self::Endblock
194            | Self::Extends
195            | Self::Include
196            | Self::Load
197            | Self::With
198            | Self::Endwith
199            | Self::Autoescape
200            | Self::Endautoescape
201            | Self::Csrf
202            | Self::Url
203            | Self::Static
204            | Self::Now
205            | Self::Cycle
206            | Self::Filter
207            | Self::Endfilter
208            | Self::Spaceless
209            | Self::Endspaceless
210            | Self::Verbatim
211            | Self::Endverbatim
212            | Self::And
213            | Self::Or
214            | Self::Not
215            | Self::In => UniversalElementRole::Statement,
216            Self::Error => UniversalElementRole::Error,
217            _ => UniversalElementRole::None,
218        }
219    }
220}
221
222impl From<crate::lexer::token_type::DjangoTokenType> for DjangoElementType {
223    fn from(token: crate::lexer::token_type::DjangoTokenType) -> Self {
224        use crate::lexer::token_type::DjangoTokenType as T;
225        match token {
226            T::If => Self::If,
227            T::Elif => Self::Elif,
228            T::Else => Self::Else,
229            T::Endif => Self::Endif,
230            T::For => Self::For,
231            T::Empty => Self::Empty,
232            T::Endfor => Self::Endfor,
233            T::Block => Self::Block,
234            T::Endblock => Self::Endblock,
235            T::Extends => Self::Extends,
236            T::Include => Self::Include,
237            T::Load => Self::Load,
238            T::With => Self::With,
239            T::Endwith => Self::Endwith,
240            T::Autoescape => Self::Autoescape,
241            T::Endautoescape => Self::Endautoescape,
242            T::Csrf => Self::Csrf,
243            T::Url => Self::Url,
244            T::Static => Self::Static,
245            T::Now => Self::Now,
246            T::Cycle => Self::Cycle,
247            T::Filter => Self::Filter,
248            T::Endfilter => Self::Endfilter,
249            T::Spaceless => Self::Spaceless,
250            T::Endspaceless => Self::Endspaceless,
251            T::Verbatim => Self::Verbatim,
252            T::Endverbatim => Self::Endverbatim,
253            T::And => Self::And,
254            T::Or => Self::Or,
255            T::Not => Self::Not,
256            T::In => Self::In,
257            T::Whitespace => Self::Whitespace,
258            T::Newline => Self::Newline,
259            T::Comment => Self::Comment,
260            T::HtmlContent => Self::HtmlContent,
261            _ => Self::Error,
262        }
263    }
264}