@@ -462,6 +462,7 @@ impl CELParser {
462462 /// Returns an error if the RHS is missing after `||`, if the RHS does not
463463 /// produce a `bool`, or if any sub-expression returns an error.
464464 fn is_or_expression ( & mut self ) -> Result < bool > {
465+ let start_span = self . peek_span ( ) ;
465466 if self . is_and_expression ( ) ? {
466467 while self . is_punctuation ( "||" ) {
467468 let mut rhs_fragment = self . context . new_fragment ( ) ;
@@ -474,7 +475,13 @@ impl CELParser {
474475 bypass_fragment. just ( true ) ;
475476 self . context
476477 . join2 ( bypass_fragment, rhs_fragment)
477- . map_err ( |e| ParseError :: new ( e. to_string ( ) , self . last_span ) ) ?;
478+ . map_err ( |e| {
479+ ParseError :: new_range (
480+ e. to_string ( ) ,
481+ start_span. expect ( "production has token at start" ) ,
482+ self . last_span ,
483+ )
484+ } ) ?;
478485 }
479486 Ok ( true )
480487 } else {
@@ -489,6 +496,7 @@ impl CELParser {
489496 /// Returns an error if the RHS is missing after `&&`, if the RHS does not
490497 /// produce a `bool`, or if any sub-expression returns an error.
491498 fn is_and_expression ( & mut self ) -> Result < bool > {
499+ let start_span = self . peek_span ( ) ;
492500 if self . is_comparison_expression ( ) ? {
493501 while self . is_punctuation ( "&&" ) {
494502 let mut rhs_fragment = self . context . new_fragment ( ) ;
@@ -501,7 +509,13 @@ impl CELParser {
501509 bypass_fragment. just ( false ) ;
502510 self . context
503511 . join2 ( rhs_fragment, bypass_fragment)
504- . map_err ( |e| ParseError :: new ( e. to_string ( ) , self . last_span ) ) ?;
512+ . map_err ( |e| {
513+ ParseError :: new_range (
514+ e. to_string ( ) ,
515+ start_span. expect ( "production has token at start" ) ,
516+ self . last_span ,
517+ )
518+ } ) ?;
505519 }
506520 Ok ( true )
507521 } else {
@@ -1647,14 +1661,22 @@ mod tests {
16471661 fn and_lhs_type_error ( ) {
16481662 // LHS is i32, not bool — join2 must reject it at parse time.
16491663 let mut parser = CELParser :: new ( OpLookup :: new ( ) ) ;
1650- assert ! ( parser. parse_str( "1i32 && true" ) . is_err( ) ) ;
1664+ let err = match parser. parse_str ( "1i32 && true" ) {
1665+ Err ( e) => e,
1666+ Ok ( _) => panic ! ( "lhs i32 should fail for &&" ) ,
1667+ } ;
1668+ assert ! ( err. end_span( ) . is_some( ) ) ;
16511669 }
16521670
16531671 #[ test]
16541672 fn or_lhs_type_error ( ) {
16551673 // LHS is i32, not bool — join2 must reject it at parse time.
16561674 let mut parser = CELParser :: new ( OpLookup :: new ( ) ) ;
1657- assert ! ( parser. parse_str( "1i32 || true" ) . is_err( ) ) ;
1675+ let err = match parser. parse_str ( "1i32 || true" ) {
1676+ Err ( e) => e,
1677+ Ok ( _) => panic ! ( "lhs i32 should fail for ||" ) ,
1678+ } ;
1679+ assert ! ( err. end_span( ) . is_some( ) ) ;
16581680 }
16591681
16601682 #[ test]
0 commit comments