Skip to content

Commit 6d26d78

Browse files
checkpoint
1 parent bc54814 commit 6d26d78

13 files changed

+713
-117
lines changed

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

Lines changed: 46 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,6 @@ impl Parser {
5252
}
5353

5454
fn next_node(&mut self) -> Result<Node, ParserError> {
55-
if self.is_at_end() {
56-
return Err(ParserError::Ast(AstError::StreamError("AtEnd".to_string())));
57-
}
5855
let token = self.peek()?;
5956
match token.token_type() {
6057
TokenType::DjangoBlock(content) => {
@@ -65,6 +62,10 @@ impl Parser {
6562
self.consume()?;
6663
self.parse_django_variable(content)
6764
}
65+
TokenType::Comment(content, start, end) => {
66+
self.consume()?;
67+
self.parse_comment(content, start, end.as_deref())
68+
}
6869
TokenType::Text(_)
6970
| TokenType::Whitespace(_)
7071
| TokenType::Newline
@@ -74,10 +75,9 @@ impl Parser {
7475
| TokenType::ScriptTagOpen(_)
7576
| TokenType::ScriptTagClose(_)
7677
| TokenType::StyleTagOpen(_)
77-
| TokenType::StyleTagClose(_) => self.parse_text(),
78-
TokenType::Comment(content, start, end) => {
78+
| TokenType::StyleTagClose(_) => {
7979
self.consume()?;
80-
self.parse_comment(content, start, end.as_deref())
80+
self.parse_text()
8181
}
8282
TokenType::Eof => Err(ParserError::Ast(AstError::StreamError("AtEnd".to_string()))),
8383
}
@@ -136,13 +136,16 @@ impl Parser {
136136
tag: branch_tag.clone(),
137137
nodes: branch_nodes.clone(),
138138
}));
139-
closing = Some(Box::new(Block::Closing { tag: next_tag.clone() }));
139+
closing = Some(Box::new(Block::Closing {
140+
tag: next_tag.clone(),
141+
}));
140142
found_closing = true;
141143
break;
142144
}
143145
}
144146
// Check if this is another branch tag
145-
if branches.iter().any(|b| b.name == next_tag.name) {
147+
if branches.iter().any(|b| b.name == next_tag.name)
148+
{
146149
// Push the current branch and start a new one
147150
nodes.push(Node::Block(Block::Branch {
148151
tag: branch_tag.clone(),
@@ -164,7 +167,9 @@ impl Parser {
164167
nodes: branch_nodes.clone(),
165168
}));
166169
// Add error for unclosed tag
167-
self.errors.push(ParserError::Ast(AstError::UnclosedTag(tag_name.clone())));
170+
self.errors.push(ParserError::Ast(AstError::UnclosedTag(
171+
tag_name.clone(),
172+
)));
168173
}
169174
if found_closing {
170175
break;
@@ -198,9 +203,16 @@ impl Parser {
198203
};
199204

200205
// Add error if we didn't find a closing tag for a block
201-
if let Block::Block { closing: None, tag: tag_ref, .. } = &block {
206+
if let Block::Block {
207+
closing: None,
208+
tag: tag_ref,
209+
..
210+
} = &block
211+
{
202212
if let Some(expected_closing) = &spec.closing {
203-
self.errors.push(ParserError::Ast(AstError::UnclosedTag(tag_ref.name.clone())));
213+
self.errors.push(ParserError::Ast(AstError::UnclosedTag(
214+
tag_ref.name.clone(),
215+
)));
204216
}
205217
}
206218

@@ -246,58 +258,40 @@ impl Parser {
246258
}
247259

248260
fn parse_text(&mut self) -> Result<Node, ParserError> {
249-
let start_token = self.peek()?;
261+
let start_token = self.peek_previous()?;
250262
let start_pos = start_token.start().unwrap_or(0);
251-
let mut total_length = start_token.length().unwrap_or(0);
252263

253-
// Handle newlines by returning next node
264+
// If we start with a newline, skip it
254265
if matches!(start_token.token_type(), TokenType::Newline) {
255-
self.consume()?;
256-
let node = self.next_node()?;
257-
return Ok(node);
258-
}
259-
260-
let mut content = match start_token.token_type() {
261-
TokenType::Text(text) => text.to_string(),
262-
TokenType::Whitespace(count) => " ".repeat(*count),
263-
_ => {
264-
return Err(ParserError::Ast(AstError::InvalidTag(
265-
"Expected text or whitespace token".to_string(),
266-
)))
267-
}
268-
};
269-
self.consume()?;
270-
271-
// Look ahead for more tokens until newline
272-
while let Ok(next_token) = self.peek() {
273-
match next_token.token_type() {
274-
TokenType::Text(text) => {
275-
content.push_str(text);
276-
total_length += next_token.length().unwrap_or(0);
277-
self.consume()?;
278-
}
279-
TokenType::Whitespace(count) => {
280-
content.push_str(&" ".repeat(*count));
281-
total_length += next_token.length().unwrap_or(0);
282-
self.consume()?;
283-
}
284-
TokenType::Newline => {
285-
// Include newline in span but not content
286-
total_length += next_token.length().unwrap_or(0);
266+
return self.next_node();
267+
}
268+
269+
// Use TokenType's Display implementation for formatting
270+
let mut text = start_token.token_type().to_string();
271+
let mut total_length: u32 = u32::try_from(text.len()).unwrap();
272+
273+
while let Ok(token) = self.peek() {
274+
match token.token_type() {
275+
TokenType::DjangoBlock(_)
276+
| TokenType::DjangoVariable(_)
277+
| TokenType::Comment(_, _, _)
278+
| TokenType::Newline
279+
| TokenType::Eof => break,
280+
_ => {
281+
let token_text = token.token_type().to_string();
282+
text.push_str(&token_text);
283+
total_length += u32::try_from(token_text.len()).unwrap();
287284
self.consume()?;
288-
break;
289285
}
290-
_ => break,
291286
}
292287
}
293288

294289
// Skip empty text nodes
295-
if content.trim().is_empty() {
296-
let node = self.next_node()?;
297-
Ok(node)
290+
if text.trim().is_empty() {
291+
self.next_node()
298292
} else {
299293
Ok(Node::Text {
300-
content,
294+
content: text,
301295
span: Span::new(start_pos, total_length),
302296
})
303297
}

0 commit comments

Comments
 (0)