11use crate :: ast:: { Ast , AstError , Block , DjangoFilter , LineOffsets , Node , Span , Tag } ;
2- use crate :: tagspecs:: { TagType , TagSpecs } ;
2+ use crate :: tagspecs:: { TagSpec , TagSpecs , TagType } ;
33use crate :: tokens:: { Token , TokenStream , TokenType } ;
44use 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