Skip to content

Commit c8c547a

Browse files
cleanup and refactor
1 parent 7f1f75a commit c8c547a

File tree

1 file changed

+100
-108
lines changed

1 file changed

+100
-108
lines changed

crates/djls-template-ast/src/parser.rs

Lines changed: 100 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::ast::{Ast, AstError, Block, DjangoFilter, LineOffsets, Node, Span, Tag};
2-
use crate::tagspecs::{TagType, TagSpecs};
2+
use crate::tagspecs::{TagSpec, TagSpecs, TagType};
33
use crate::tokens::{Token, TokenStream, TokenType};
44
use thiserror::Error;
55

@@ -84,7 +84,7 @@ impl Parser {
8484
})
8585
}
8686

87-
fn parse_django_block(&mut self) -> Result<Node, ParserError> {
87+
pub fn parse_django_block(&mut self) -> Result<Node, ParserError> {
8888
let token = self.peek_previous()?;
8989

9090
let bits: Vec<String> = token
@@ -104,121 +104,101 @@ impl Parser {
104104
};
105105

106106
let specs = TagSpecs::load_builtin_specs()?;
107-
let spec = match specs.get(&tag_name) {
108-
Some(spec) => spec,
109-
None => return Ok(Node::Block(Block::Tag { tag })),
110-
};
107+
let spec = specs.get(&tag_name);
108+
109+
match spec {
110+
Some(spec) => match spec.tag_type {
111+
TagType::Block => self.parse_block_tag(tag, spec),
112+
TagType::Tag => Ok(Node::Block(Block::Tag { tag })),
113+
TagType::Variable => Ok(Node::Block(Block::Variable { tag })),
114+
TagType::Inclusion => {
115+
let template_name = tag.bits.get(1).cloned().unwrap_or_default();
116+
Ok(Node::Block(Block::Inclusion { tag, template_name }))
117+
}
118+
},
119+
120+
None => Ok(Node::Block(Block::Tag { tag })),
121+
}
122+
}
111123

112-
let block = match spec.tag_type {
113-
TagType::Block => {
114-
let mut nodes = Vec::new();
115-
let mut closing = None;
116-
117-
while !self.is_at_end() {
118-
match self.next_node() {
119-
Ok(Node::Block(Block::Tag { tag })) => {
120-
if let Some(expected_closing) = &spec.closing {
121-
if tag.name == *expected_closing {
122-
closing = Some(Box::new(Block::Closing { tag }));
123-
break;
124-
}
125-
}
126-
// If we get here, either there was no expected closing tag or it didn't match
127-
if let Some(branches) = &spec.branches {
128-
if branches.iter().any(|b| b == &tag.name) {
129-
let mut branch_tag = tag.clone();
130-
let mut branch_nodes = Vec::new();
131-
let mut found_closing = false;
132-
while let Ok(node) = self.next_node() {
133-
match &node {
134-
Node::Block(Block::Tag { tag: next_tag }) => {
135-
if let Some(expected_closing) = &spec.closing {
136-
if next_tag.name == *expected_closing {
137-
// Found the closing tag
138-
nodes.push(Node::Block(Block::Branch {
139-
tag: branch_tag.clone(),
140-
nodes: branch_nodes.clone(),
141-
}));
142-
closing = Some(Box::new(Block::Closing {
143-
tag: next_tag.clone(),
144-
}));
145-
found_closing = true;
146-
break;
147-
}
148-
}
149-
// Check if this is another branch tag
150-
if branches.iter().any(|b| b == &next_tag.name) {
151-
// Push the current branch and start a new one
152-
nodes.push(Node::Block(Block::Branch {
153-
tag: branch_tag.clone(),
154-
nodes: branch_nodes.clone(),
155-
}));
156-
branch_nodes = Vec::new();
157-
branch_tag = next_tag.clone();
158-
continue;
159-
}
160-
branch_nodes.push(node);
161-
}
162-
_ => branch_nodes.push(node),
163-
}
164-
}
165-
if !found_closing {
166-
// Push the last branch if we didn't find a closing tag
167-
nodes.push(Node::Block(Block::Branch {
168-
tag: branch_tag.clone(),
169-
nodes: branch_nodes.clone(),
170-
}));
171-
// Add error for unclosed tag
172-
self.errors.push(ParserError::Ast(AstError::UnclosedTag(
173-
tag_name.clone(),
174-
)));
175-
}
176-
if found_closing {
177-
break;
178-
}
179-
continue;
180-
}
181-
}
182-
nodes.push(Node::Block(Block::Tag { tag }));
183-
}
184-
Ok(node) => nodes.push(node),
185-
Err(e) => {
186-
self.errors.push(e);
187-
break;
188-
}
124+
fn parse_block_tag(&mut self, tag: Tag, spec: &TagSpec) -> Result<Node, ParserError> {
125+
let mut nodes = Vec::new();
126+
let mut closing = None;
127+
128+
while !self.is_at_end() {
129+
match self.next_node() {
130+
Ok(Node::Block(Block::Tag { tag: inner_tag })) => {
131+
if self.is_closing_tag(&inner_tag, spec) {
132+
closing = Some(Box::new(Block::Closing { tag: inner_tag }));
133+
break;
134+
} else if self.is_branch_tag(&inner_tag, spec) {
135+
nodes.push(self.parse_branch_tag(inner_tag, spec)?);
136+
} else {
137+
nodes.push(Node::Block(Block::Tag { tag: inner_tag }));
189138
}
190139
}
191-
192-
Block::Block {
193-
tag,
194-
nodes,
195-
closing,
196-
assignments: None,
140+
Ok(node) => nodes.push(node),
141+
Err(e) => {
142+
self.errors.push(e);
143+
break;
197144
}
198145
}
199-
TagType::Tag => Block::Tag { tag },
200-
TagType::Variable => Block::Variable { tag },
201-
TagType::Inclusion => {
202-
let template_name = bits.get(1).cloned().unwrap_or_default();
203-
Block::Inclusion { tag, template_name }
204-
}
205-
};
146+
}
147+
148+
if spec.closing.is_some() && closing.is_none() {
149+
self.errors
150+
.push(ParserError::Ast(AstError::UnclosedTag(tag.name.clone())));
151+
}
152+
153+
Ok(Node::Block(Block::Block {
154+
tag,
155+
nodes,
156+
closing,
157+
assignments: None,
158+
}))
159+
}
160+
161+
fn parse_branch_tag(&mut self, branch_tag: Tag, spec: &TagSpec) -> Result<Node, ParserError> {
162+
let mut branch_nodes = Vec::new();
206163

207-
// Add error if we didn't find a closing tag for a block
208-
if let Block::Block {
209-
closing: None,
210-
tag: tag_ref,
211-
..
212-
} = &block
213-
{
214-
if let Some(_expected_closing) = &spec.closing {
215-
self.errors.push(ParserError::Ast(AstError::UnclosedTag(
216-
tag_ref.name.clone(),
217-
)));
164+
while !self.is_at_end() {
165+
match self.next_node() {
166+
Ok(Node::Block(Block::Tag { tag: inner_tag })) => {
167+
if self.is_closing_tag(&inner_tag, spec) || self.is_branch_tag(&inner_tag, spec)
168+
{
169+
self.backtrack(1)?;
170+
break;
171+
} else {
172+
branch_nodes.push(Node::Block(Block::Tag { tag: inner_tag }));
173+
}
174+
}
175+
Ok(node) => branch_nodes.push(node),
176+
Err(e) => {
177+
self.errors.push(e);
178+
break;
179+
}
218180
}
219181
}
220182

221-
Ok(Node::Block(block))
183+
Ok(Node::Block(Block::Branch {
184+
tag: branch_tag,
185+
nodes: branch_nodes,
186+
}))
187+
}
188+
189+
fn is_closing_tag(&self, tag: &Tag, spec: &TagSpec) -> bool {
190+
match &spec.closing {
191+
Some(expected_closing) => &tag.name == expected_closing,
192+
None => false,
193+
}
194+
}
195+
196+
fn is_branch_tag(&self, tag: &Tag, spec: &TagSpec) -> bool {
197+
if let Some(branches) = &spec.branches {
198+
branches.contains(&tag.name)
199+
} else {
200+
false
201+
}
222202
}
223203

224204
fn parse_django_variable(&mut self) -> Result<Node, ParserError> {
@@ -304,6 +284,10 @@ impl Parser {
304284
self.peek_at(0)
305285
}
306286

287+
fn peek_next(&self) -> Result<Token, ParserError> {
288+
self.peek_at(1)
289+
}
290+
307291
fn peek_previous(&self) -> Result<Token, ParserError> {
308292
self.peek_at(-1)
309293
}
@@ -342,6 +326,14 @@ impl Parser {
342326
self.peek_previous()
343327
}
344328

329+
fn backtrack(&mut self, steps: usize) -> Result<Token, ParserError> {
330+
if self.current < steps {
331+
return Err(ParserError::stream_error("AtBeginning"));
332+
}
333+
self.current -= steps;
334+
self.peek_next()
335+
}
336+
345337
fn synchronize(&mut self) -> Result<(), ParserError> {
346338
let sync_types = &[
347339
TokenType::DjangoBlock(String::new()),

0 commit comments

Comments
 (0)