@@ -394,6 +394,7 @@ impl<'s> Parser<'s> {
394394
395395 let value = CSTNode :: Production ( Production {
396396 id : reduce. production_id ,
397+ span : get_span_of_nodes ( args) ,
397398 args,
398399 inlined_ids : None ,
399400 } ) ;
@@ -419,7 +420,7 @@ impl<'s> Parser<'s> {
419420 Some ( ctx. alloc_slice_and_push ( & new_prod. inlined_ids , inlined_id) ) ;
420421 }
421422
422- extend_span ( & mut value, span, ctx) ;
423+ expand_span ( & mut value, span, ctx) ;
423424 } else {
424425 // place back
425426 value = CSTNode :: Production ( production) ;
@@ -607,38 +608,54 @@ impl<'a> StackNode<'a> {
607608 }
608609}
609610
610- fn get_span_of_nodes ( args : & [ CSTNode ] ) -> Option < Span > {
611- let start = args. iter ( ) . find_map ( |x| match x {
611+ /// Returns the span of syntactically ordered nodes. Panic on empty nodes.
612+ fn get_span_of_nodes ( nodes : & [ CSTNode ] ) -> Option < Span > {
613+ let start = nodes. iter ( ) . find_map ( |x| match x {
612614 CSTNode :: Terminal ( t) => Some ( t. span . start ) ,
613- CSTNode :: Production ( p) => get_span_of_nodes ( p. args ) . map ( |x| x . start ) ,
614- _ => None ,
615+ CSTNode :: Production ( p) => Some ( p. span ? . start ) ,
616+ CSTNode :: Empty => panic ! ( ) ,
615617 } ) ?;
616- let end = args . iter ( ) . rev ( ) . find_map ( |x| match x {
618+ let end = nodes . iter ( ) . rev ( ) . find_map ( |x| match x {
617619 CSTNode :: Terminal ( t) => Some ( t. span . end ) ,
618- CSTNode :: Production ( p) => get_span_of_nodes ( p. args ) . map ( |x| x . end ) ,
619- _ => None ,
620+ CSTNode :: Production ( p) => Some ( p. span ? . end ) ,
621+ CSTNode :: Empty => panic ! ( ) ,
620622 } ) ?;
621623 Some ( Span { start, end } )
622624}
623625
624- fn extend_span < ' a > ( value : & mut CSTNode < ' a > , span : Option < Span > , ctx : & ' a Context ) {
626+ fn expand_span < ' a > ( value : & mut CSTNode < ' a > , span : Option < Span > , ctx : & ' a Context ) {
625627 let Some ( span) = span else {
626628 return ;
627629 } ;
628630
629- let CSTNode :: Terminal ( terminal) = value else {
630- return ;
631+ let curr_span = match value {
632+ CSTNode :: Empty => panic ! ( ) ,
633+ CSTNode :: Terminal ( t) => & t. span ,
634+ CSTNode :: Production ( p) => {
635+ if let Some ( span) = & p. span {
636+ span
637+ } else {
638+ p. span = Some ( span) ;
639+ return ;
640+ }
641+ }
631642 } ;
632643
633- let mut new_term = terminal. clone ( ) ;
634-
635- if span. start < new_term. span . start {
636- new_term. span . start = span. start ;
637- }
638- if span. end > new_term. span . end {
639- new_term. span . end = span. end ;
644+ if curr_span. start <= span. start && span. end <= curr_span. end {
645+ return ;
640646 }
641- * terminal = ctx. alloc_terminal ( new_term) ;
647+
648+ let span = span. extend ( curr_span) ;
649+
650+ match value {
651+ CSTNode :: Empty => panic ! ( ) ,
652+ CSTNode :: Terminal ( t) => {
653+ let mut new_term = t. clone ( ) ;
654+ new_term. span = span;
655+ * t = ctx. alloc_terminal ( new_term) ;
656+ }
657+ CSTNode :: Production ( p) => p. span = Some ( span) ,
658+ } ;
642659}
643660
644661const PARSER_COUNT_MAX : usize = 10 ;
0 commit comments