@@ -51,11 +51,16 @@ namespace cel::parser_internal {
5151class ParserWorker {
5252 public:
5353 ParserWorker (const cel::Source& source, const cel::ParserOptions& options,
54- std::vector<cel::ParseIssue>* absl_nullable parse_issues);
54+ std::vector<cel::ParseIssue>* absl_nullable parse_issues,
55+ bool track_node_ranges = false );
5556
5657 const absl::flat_hash_map<int64_t , int32_t >& GetNodePositions () const {
5758 return positions_;
5859 }
60+ const absl::flat_hash_map<int64_t , std::pair<int32_t , int32_t >>&
61+ GetNodeRanges () const {
62+ return node_ranges_;
63+ }
5964 absl::Span<const int32_t > GetLineOffsets () const {
6065 return source_.line_offsets ();
6166 }
@@ -75,11 +80,25 @@ class ParserWorker {
7580
7681 // ID and Position tracking
7782 int64_t NextId (int32_t position);
78- int64_t NextId (const Token& token) { return NextId (token.start ); }
83+ int64_t NextId (const Token& token) {
84+ int64_t id = NextId (token.start );
85+ if (ABSL_PREDICT_FALSE (track_node_ranges_)) {
86+ if (token.start >= 0 && token.end > token.start ) {
87+ node_ranges_[id] = {token.start , token.end - 1 };
88+ }
89+ }
90+ return id;
91+ }
7992 int64_t NextId ();
80- bool NodeLimitExceeded ();
8193 int64_t CopyId (int64_t id);
8294 void EraseId (int64_t id);
95+ void SetNodeRange (int64_t id, int32_t begin, int32_t end) {
96+ if (ABSL_PREDICT_FALSE (track_node_ranges_)) {
97+ if (id != 0 && begin >= 0 && end >= begin) {
98+ node_ranges_[id] = {begin, end};
99+ }
100+ }
101+ }
83102
84103 // Error reporting and recovery
85104 bool is_recovery_limit_exceeded () const {
@@ -100,10 +119,12 @@ class ParserWorker {
100119 int64_t next_id_ = 1 ;
101120 bool node_limit_exceeded_ = false ;
102121 absl::flat_hash_map<int64_t , int32_t > positions_;
122+ absl::flat_hash_map<int64_t , std::pair<int32_t , int32_t >> node_ranges_;
103123 std::vector<cel::ParseIssue>* absl_nullable parse_issues_;
104124 int error_count_ = 0 ;
105125 bool lexer_error_reported_ = false ;
106126 bool recursion_limit_exceeded_ = false ;
127+ bool track_node_ranges_ = false ;
107128};
108129
109130struct BinaryOpInfo {
@@ -131,8 +152,10 @@ class PrattParserWorker : public ParserWorker {
131152 explicit PrattParserWorker (
132153 const cel::Source& source, const cel::ParserOptions& options,
133154 std::vector<cel::ParseIssue>* absl_nullable parse_issues,
134- AstFactoryInterface<ExprNode>& ast_factory)
135- : ParserWorker(source, options, parse_issues), ast_factory_(ast_factory) {
155+ AstFactoryInterface<ExprNode>& ast_factory,
156+ bool track_node_ranges = false )
157+ : ParserWorker(source, options, parse_issues, track_node_ranges),
158+ ast_factory_(ast_factory) {
136159 this ->InitTokenStream ();
137160 }
138161
@@ -696,7 +719,9 @@ ExprNode PrattParserWorker<ExprNode>::ParseList() {
696719 break ;
697720 }
698721 }
699- Expect (TokenType::kRightBracket , " expected ']'" );
722+ if (Expect (TokenType::kRightBracket , " expected ']'" )) {
723+ SetNodeRange (list_id, open_tok.start , current_token_.end - 1 );
724+ }
700725 return builder.Build ();
701726}
702727
@@ -732,7 +757,9 @@ ExprNode PrattParserWorker<ExprNode>::ParseMap() {
732757 break ;
733758 }
734759 }
735- Expect (TokenType::kRightBrace , " expected '}'" );
760+ if (Expect (TokenType::kRightBrace , " expected '}'" )) {
761+ SetNodeRange (map_id, open_tok.start , current_token_.end - 1 );
762+ }
736763 return builder.Build ();
737764}
738765
@@ -774,7 +801,14 @@ ExprNode PrattParserWorker<ExprNode>::ParseStruct(
774801 break ;
775802 }
776803 }
777- Expect (TokenType::kRightBrace , " expected '}'" );
804+ if (Expect (TokenType::kRightBrace , " expected '}'" )) {
805+ int32_t start_pos = open_tok.start ;
806+ auto it = positions_.find (obj_id);
807+ if (it != positions_.end ()) {
808+ start_pos = it->second ;
809+ }
810+ SetNodeRange (obj_id, start_pos, current_token_.end - 1 );
811+ }
778812 return builder.Build ();
779813}
780814
@@ -1052,7 +1086,7 @@ std::optional<ExprNode> PrattParserWorker<ExprNode>::TryExpandMacro(
10521086 if (!expander) {
10531087 return std::nullopt ;
10541088 }
1055- if (NodeLimitExceeded () ) {
1089+ if (node_limit_exceeded_ ) {
10561090 ReportError (expr_id,
10571091 " could not expand macro: expression node limit exceeded" );
10581092 return std::nullopt ;
0 commit comments