11use crate :: ast:: { Ast , AstError , Block , DjangoFilter , LineOffsets , Node , Span , Tag } ;
2+ use crate :: lexer:: LexerError ;
23use crate :: tagspecs:: { TagSpec , TagSpecs , TagType } ;
34use crate :: tokens:: { Token , TokenStream , TokenType } ;
45use thiserror:: Error ;
@@ -7,26 +8,16 @@ pub struct Parser {
78 tokens : TokenStream ,
89 current : usize ,
910 errors : Vec < ParserError > ,
10- tag_specs : TagSpecs , // Add TagSpecs field
11+ tags : TagSpecs ,
1112}
1213
1314impl Parser {
14- // Modify the constructor to accept TagSpecs
15- pub fn new ( tokens : TokenStream , tag_specs : TagSpecs ) -> Self {
16- Self {
17- tokens,
18- current : 0 ,
19- errors : Vec :: new ( ) ,
20- tag_specs,
21- }
22- }
23-
24- impl Parser {
25- pub fn new ( tokens : TokenStream ) -> Self {
15+ pub fn new ( tokens : TokenStream , tags : TagSpecs ) -> Self {
2616 Self {
2717 tokens,
2818 current : 0 ,
2919 errors : Vec :: new ( ) ,
20+ tags,
3021 }
3122 }
3223
@@ -127,11 +118,11 @@ impl Parser {
127118 assignment,
128119 } ;
129120
130- let spec = self . tag_specs . get ( & tag_name) ;
121+ let spec = self . tags . get ( & tag_name) . cloned ( ) ;
131122
132123 match spec {
133124 Some ( spec) => match spec. tag_type {
134- TagType :: Container => self . parse_block_tag ( tag, spec) ,
125+ TagType :: Container => self . parse_block_tag ( tag, & spec) ,
135126 TagType :: Single => Ok ( Node :: Block ( Block :: Single { tag } ) ) ,
136127 TagType :: Inclusion => {
137128 let template_name = tag. bits . get ( 1 ) . cloned ( ) . unwrap_or_default ( ) ;
@@ -395,6 +386,8 @@ pub enum ParserError {
395386 Other ( #[ from] anyhow:: Error ) ,
396387 #[ error( "empty tag" ) ]
397388 EmptyTag ,
389+ #[ error( "{0}" ) ]
390+ Lexer ( #[ from] LexerError ) ,
398391}
399392
400393impl ParserError {
@@ -414,7 +407,8 @@ mod tests {
414407 fn test_parse_html_doctype ( ) {
415408 let source = "<!DOCTYPE html>" ;
416409 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
417- let mut parser = Parser :: new ( tokens) ;
410+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
411+ let mut parser = Parser :: new ( tokens, tags) ;
418412 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
419413 insta:: assert_yaml_snapshot!( ast) ;
420414 assert ! ( errors. is_empty( ) ) ;
@@ -424,7 +418,8 @@ mod tests {
424418 fn test_parse_html_tag ( ) {
425419 let source = "<div class=\" container\" >Hello</div>" ;
426420 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
427- let mut parser = Parser :: new ( tokens) ;
421+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
422+ let mut parser = Parser :: new ( tokens, tags) ;
428423 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
429424 insta:: assert_yaml_snapshot!( ast) ;
430425 assert ! ( errors. is_empty( ) ) ;
@@ -434,7 +429,8 @@ mod tests {
434429 fn test_parse_html_void ( ) {
435430 let source = "<input type=\" text\" />" ;
436431 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
437- let mut parser = Parser :: new ( tokens) ;
432+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
433+ let mut parser = Parser :: new ( tokens, tags) ;
438434 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
439435 insta:: assert_yaml_snapshot!( ast) ;
440436 assert ! ( errors. is_empty( ) ) ;
@@ -448,7 +444,8 @@ mod tests {
448444 fn test_parse_django_variable ( ) {
449445 let source = "{{ user.name }}" ;
450446 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
451- let mut parser = Parser :: new ( tokens) ;
447+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
448+ let mut parser = Parser :: new ( tokens, tags) ;
452449 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
453450 insta:: assert_yaml_snapshot!( ast) ;
454451 assert ! ( errors. is_empty( ) ) ;
@@ -458,7 +455,8 @@ mod tests {
458455 fn test_parse_django_variable_with_filter ( ) {
459456 let source = "{{ user.name|title }}" ;
460457 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
461- let mut parser = Parser :: new ( tokens) ;
458+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
459+ let mut parser = Parser :: new ( tokens, tags) ;
462460 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
463461 insta:: assert_yaml_snapshot!( ast) ;
464462 assert ! ( errors. is_empty( ) ) ;
@@ -468,7 +466,8 @@ mod tests {
468466 fn test_parse_filter_chains ( ) {
469467 let source = "{{ value|default:'nothing'|title|upper }}" ;
470468 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
471- let mut parser = Parser :: new ( tokens) ;
469+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
470+ let mut parser = Parser :: new ( tokens, tags) ;
472471 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
473472 insta:: assert_yaml_snapshot!( ast) ;
474473 assert ! ( errors. is_empty( ) ) ;
@@ -478,7 +477,8 @@ mod tests {
478477 fn test_parse_django_if_block ( ) {
479478 let source = "{% if user.is_authenticated %}Welcome{% endif %}" ;
480479 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
481- let mut parser = Parser :: new ( tokens) ;
480+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
481+ let mut parser = Parser :: new ( tokens, tags) ;
482482 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
483483 insta:: assert_yaml_snapshot!( ast) ;
484484 assert ! ( errors. is_empty( ) ) ;
@@ -488,7 +488,8 @@ mod tests {
488488 fn test_parse_django_for_block ( ) {
489489 let source = "{% for item in items %}{{ item }}{% empty %}No items{% endfor %}" ;
490490 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
491- let mut parser = Parser :: new ( tokens) ;
491+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
492+ let mut parser = Parser :: new ( tokens, tags) ;
492493 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
493494 insta:: assert_yaml_snapshot!( ast) ;
494495 assert ! ( errors. is_empty( ) ) ;
@@ -498,7 +499,8 @@ mod tests {
498499 fn test_parse_complex_if_elif ( ) {
499500 let source = "{% if x > 0 %}Positive{% elif x < 0 %}Negative{% else %}Zero{% endif %}" ;
500501 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
501- let mut parser = Parser :: new ( tokens) ;
502+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
503+ let mut parser = Parser :: new ( tokens, tags) ;
502504 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
503505 insta:: assert_yaml_snapshot!( ast) ;
504506 assert ! ( errors. is_empty( ) ) ;
@@ -508,7 +510,8 @@ mod tests {
508510 fn test_parse_django_tag_assignment ( ) {
509511 let source = "{% url 'view-name' as view %}" ;
510512 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
511- let mut parser = Parser :: new ( tokens) ;
513+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
514+ let mut parser = Parser :: new ( tokens, tags) ;
512515 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
513516 insta:: assert_yaml_snapshot!( ast) ;
514517 assert ! ( errors. is_empty( ) ) ;
@@ -519,7 +522,8 @@ mod tests {
519522 let source =
520523 "{% for item in items %}{% if item.active %}{{ item.name }}{% endif %}{% endfor %}" ;
521524 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
522- let mut parser = Parser :: new ( tokens) ;
525+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
526+ let mut parser = Parser :: new ( tokens, tags) ;
523527 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
524528 insta:: assert_yaml_snapshot!( ast) ;
525529 assert ! ( errors. is_empty( ) ) ;
@@ -541,7 +545,8 @@ mod tests {
541545 Guest
542546{% endif %}!" ;
543547 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
544- let mut parser = Parser :: new ( tokens) ;
548+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
549+ let mut parser = Parser :: new ( tokens, tags) ;
545550 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
546551 insta:: assert_yaml_snapshot!( ast) ;
547552 assert ! ( errors. is_empty( ) ) ;
@@ -561,7 +566,8 @@ mod tests {
561566 console.log(x);
562567</script>"# ;
563568 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
564- let mut parser = Parser :: new ( tokens) ;
569+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
570+ let mut parser = Parser :: new ( tokens, tags) ;
565571 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
566572 insta:: assert_yaml_snapshot!( ast) ;
567573 assert ! ( errors. is_empty( ) ) ;
@@ -580,7 +586,8 @@ mod tests {
580586 }
581587</style>"# ;
582588 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
583- let mut parser = Parser :: new ( tokens) ;
589+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
590+ let mut parser = Parser :: new ( tokens, tags) ;
584591 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
585592 insta:: assert_yaml_snapshot!( ast) ;
586593 assert ! ( errors. is_empty( ) ) ;
@@ -594,7 +601,8 @@ mod tests {
594601 fn test_parse_comments ( ) {
595602 let source = "<!-- HTML comment -->{# Django comment #}" ;
596603 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
597- let mut parser = Parser :: new ( tokens) ;
604+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
605+ let mut parser = Parser :: new ( tokens, tags) ;
598606 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
599607 insta:: assert_yaml_snapshot!( ast) ;
600608 assert ! ( errors. is_empty( ) ) ;
@@ -608,7 +616,8 @@ mod tests {
608616 fn test_parse_with_leading_whitespace ( ) {
609617 let source = " hello" ;
610618 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
611- let mut parser = Parser :: new ( tokens) ;
619+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
620+ let mut parser = Parser :: new ( tokens, tags) ;
612621 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
613622 insta:: assert_yaml_snapshot!( ast) ;
614623 assert ! ( errors. is_empty( ) ) ;
@@ -618,7 +627,8 @@ mod tests {
618627 fn test_parse_with_leading_whitespace_newline ( ) {
619628 let source = "\n hello" ;
620629 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
621- let mut parser = Parser :: new ( tokens) ;
630+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
631+ let mut parser = Parser :: new ( tokens, tags) ;
622632 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
623633 insta:: assert_yaml_snapshot!( ast) ;
624634 assert ! ( errors. is_empty( ) ) ;
@@ -628,7 +638,8 @@ mod tests {
628638 fn test_parse_with_trailing_whitespace ( ) {
629639 let source = "hello " ;
630640 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
631- let mut parser = Parser :: new ( tokens) ;
641+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
642+ let mut parser = Parser :: new ( tokens, tags) ;
632643 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
633644 insta:: assert_yaml_snapshot!( ast) ;
634645 assert ! ( errors. is_empty( ) ) ;
@@ -638,7 +649,8 @@ mod tests {
638649 fn test_parse_with_trailing_whitespace_newline ( ) {
639650 let source = "hello \n " ;
640651 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
641- let mut parser = Parser :: new ( tokens) ;
652+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
653+ let mut parser = Parser :: new ( tokens, tags) ;
642654 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
643655 insta:: assert_yaml_snapshot!( ast) ;
644656 assert ! ( errors. is_empty( ) ) ;
@@ -652,7 +664,8 @@ mod tests {
652664 fn test_parse_unclosed_html_tag ( ) {
653665 let source = "<div>" ;
654666 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
655- let mut parser = Parser :: new ( tokens) ;
667+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
668+ let mut parser = Parser :: new ( tokens, tags) ;
656669 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
657670 insta:: assert_yaml_snapshot!( ast) ;
658671 assert ! ( errors. is_empty( ) ) ;
@@ -662,7 +675,8 @@ mod tests {
662675 fn test_parse_unclosed_django_if ( ) {
663676 let source = "{% if user.is_authenticated %}Welcome" ;
664677 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
665- let mut parser = Parser :: new ( tokens) ;
678+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
679+ let mut parser = Parser :: new ( tokens, tags) ;
666680 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
667681 insta:: assert_yaml_snapshot!( ast) ;
668682 assert_eq ! ( errors. len( ) , 1 ) ;
@@ -675,7 +689,8 @@ mod tests {
675689 fn test_parse_unclosed_django_for ( ) {
676690 let source = "{% for item in items %}{{ item.name }}" ;
677691 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
678- let mut parser = Parser :: new ( tokens) ;
692+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
693+ let mut parser = Parser :: new ( tokens, tags) ;
679694 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
680695 insta:: assert_yaml_snapshot!( ast) ;
681696 assert_eq ! ( errors. len( ) , 1 ) ;
@@ -688,7 +703,8 @@ mod tests {
688703 fn test_parse_unclosed_script ( ) {
689704 let source = "<script>console.log('test');" ;
690705 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
691- let mut parser = Parser :: new ( tokens) ;
706+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
707+ let mut parser = Parser :: new ( tokens, tags) ;
692708 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
693709 insta:: assert_yaml_snapshot!( ast) ;
694710 assert ! ( errors. is_empty( ) ) ;
@@ -698,7 +714,8 @@ mod tests {
698714 fn test_parse_unclosed_style ( ) {
699715 let source = "<style>body { color: blue; " ;
700716 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
701- let mut parser = Parser :: new ( tokens) ;
717+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
718+ let mut parser = Parser :: new ( tokens, tags) ;
702719 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
703720 insta:: assert_yaml_snapshot!( ast) ;
704721 assert ! ( errors. is_empty( ) ) ;
@@ -719,7 +736,8 @@ mod tests {
719736 <footer>Page Footer</footer>
720737</div>"# ;
721738 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
722- let mut parser = Parser :: new ( tokens) ;
739+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
740+ let mut parser = Parser :: new ( tokens, tags) ;
723741 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
724742 insta:: assert_yaml_snapshot!( ast) ;
725743 assert_eq ! ( errors. len( ) , 1 ) ;
@@ -765,7 +783,8 @@ mod tests {
765783 </body>
766784</html>"# ;
767785 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
768- let mut parser = Parser :: new ( tokens) ;
786+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
787+ let mut parser = Parser :: new ( tokens, tags) ;
769788 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
770789 insta:: assert_yaml_snapshot!( ast) ;
771790 assert ! ( errors. is_empty( ) ) ;
@@ -779,7 +798,8 @@ mod tests {
779798 fn test_parser_tracks_line_offsets ( ) {
780799 let source = "line1\n line2" ;
781800 let tokens = Lexer :: new ( source) . tokenize ( ) . unwrap ( ) ;
782- let mut parser = Parser :: new ( tokens) ;
801+ let tags = TagSpecs :: load_builtin_specs ( ) . unwrap ( ) ;
802+ let mut parser = Parser :: new ( tokens, tags) ;
783803 let ( ast, errors) = parser. parse ( ) . unwrap ( ) ;
784804
785805 let offsets = ast. line_offsets ( ) ;
0 commit comments