Skip to content

Commit 5c9cda7

Browse files
dmitriplotnikovcopybara-github
authored andcommitted
[Pratt Parser] Add deep copy/replace functionality to AstFactoryInterface
PiperOrigin-RevId: 953058710
1 parent 68aded8 commit 5c9cda7

5 files changed

Lines changed: 534 additions & 96 deletions

File tree

parser/internal/BUILD

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,24 @@ licenses(["notice"])
2323
cc_library(
2424
name = "ast_factory_interface",
2525
hdrs = ["ast_factory_interface.h"],
26+
deps = [
27+
"@com_google_absl//absl/functional:function_ref",
28+
"@com_google_absl//absl/status:statusor",
29+
],
2630
)
2731

2832
cc_library(
2933
name = "ast_factory",
34+
srcs = ["ast_factory.cc"],
3035
hdrs = ["ast_factory.h"],
3136
deps = [
3237
":ast_factory_interface",
33-
"//common:constant",
3438
"//common:expr",
3539
"//common:expr_factory",
40+
"//internal:status_macros",
41+
"@com_google_absl//absl/functional:function_ref",
42+
"@com_google_absl//absl/status",
43+
"@com_google_absl//absl/status:statusor",
3644
"@com_google_absl//absl/strings:string_view",
3745
],
3846
)
@@ -119,8 +127,11 @@ cc_test(
119127
srcs = ["ast_factory_test.cc"],
120128
deps = [
121129
":ast_factory",
130+
"//common:constant",
122131
"//common:expr",
123132
"//internal:testing",
133+
"@com_google_absl//absl/status",
134+
"@com_google_absl//absl/status:status_matchers",
124135
"@com_google_absl//absl/strings:string_view",
125136
],
126137
)

parser/internal/ast_factory.cc

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
// Copyright 2026 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "parser/internal/ast_factory.h"
16+
17+
#include <cstdint>
18+
#include <optional>
19+
#include <string>
20+
#include <utility>
21+
22+
#include "absl/functional/function_ref.h"
23+
#include "absl/status/status.h"
24+
#include "absl/status/statusor.h"
25+
#include "absl/strings/string_view.h"
26+
#include "common/expr.h"
27+
#include "internal/status_macros.h"
28+
29+
namespace cel::parser_internal {
30+
31+
ListNodeBuilder<cel::Expr>::ListNodeBuilder(int64_t id) {
32+
expr_.set_id(id);
33+
expr_.mutable_list_expr();
34+
}
35+
36+
ListNodeBuilder<cel::Expr>& ListNodeBuilder<cel::Expr>::Add(cel::Expr element,
37+
bool optional) {
38+
cel::ListExpr& list_val = expr_.mutable_list_expr();
39+
cel::ListExprElement expr_element;
40+
expr_element.set_expr(std::move(element));
41+
expr_element.set_optional(optional);
42+
list_val.mutable_elements().push_back(std::move(expr_element));
43+
return *this;
44+
}
45+
46+
cel::Expr ListNodeBuilder<cel::Expr>::Build() { return std::move(expr_); }
47+
48+
MapNodeBuilder<cel::Expr>::MapNodeBuilder(int64_t id) {
49+
expr_.set_id(id);
50+
expr_.mutable_map_expr();
51+
}
52+
53+
MapNodeBuilder<cel::Expr>& MapNodeBuilder<cel::Expr>::Add(int64_t id,
54+
cel::Expr key,
55+
cel::Expr value,
56+
bool optional) {
57+
cel::MapExpr& map_val = expr_.mutable_map_expr();
58+
cel::MapExprEntry entry;
59+
entry.set_id(id);
60+
entry.set_key(std::move(key));
61+
entry.set_value(std::move(value));
62+
entry.set_optional(optional);
63+
map_val.mutable_entries().push_back(std::move(entry));
64+
return *this;
65+
}
66+
67+
cel::Expr MapNodeBuilder<cel::Expr>::Build() { return std::move(expr_); }
68+
69+
StructNodeBuilder<cel::Expr>::StructNodeBuilder(int64_t id, std::string name) {
70+
expr_.set_id(id);
71+
expr_.mutable_struct_expr().set_name(std::move(name));
72+
}
73+
74+
StructNodeBuilder<cel::Expr>& StructNodeBuilder<cel::Expr>::Add(
75+
int64_t id, std::string name, cel::Expr value, bool optional) {
76+
cel::StructExpr& struct_val = expr_.mutable_struct_expr();
77+
cel::StructExprField field;
78+
field.set_id(id);
79+
field.set_name(std::move(name));
80+
field.set_value(std::move(value));
81+
field.set_optional(optional);
82+
struct_val.mutable_fields().push_back(std::move(field));
83+
return *this;
84+
}
85+
86+
cel::Expr StructNodeBuilder<cel::Expr>::Build() { return std::move(expr_); }
87+
88+
int64_t AstFactoryInterface<cel::Expr>::GetId(const cel::Expr& expr) const {
89+
return expr.id();
90+
}
91+
92+
bool AstFactoryInterface<cel::Expr>::IsEmpty(const cel::Expr& expr) const {
93+
return expr.id() == 0;
94+
}
95+
96+
bool AstFactoryInterface<cel::Expr>::IsConst(const cel::Expr& expr) const {
97+
return expr.has_const_expr();
98+
}
99+
100+
bool AstFactoryInterface<cel::Expr>::IsIdent(const cel::Expr& expr) const {
101+
return expr.has_ident_expr();
102+
}
103+
104+
absl::string_view AstFactoryInterface<cel::Expr>::GetIdentName(
105+
const cel::Expr& expr) const {
106+
return expr.has_ident_expr() ? absl::string_view(expr.ident_expr().name())
107+
: absl::string_view();
108+
}
109+
110+
bool AstFactoryInterface<cel::Expr>::IsSelect(const cel::Expr& expr) const {
111+
return expr.has_select_expr();
112+
}
113+
114+
bool AstFactoryInterface<cel::Expr>::IsPresenceTest(
115+
const cel::Expr& expr) const {
116+
return expr.has_select_expr() && expr.select_expr().test_only();
117+
}
118+
119+
const cel::Expr* AstFactoryInterface<cel::Expr>::GetSelectOperand(
120+
const cel::Expr& expr) const {
121+
return expr.has_select_expr() ? &expr.select_expr().operand() : nullptr;
122+
}
123+
124+
absl::string_view AstFactoryInterface<cel::Expr>::GetSelectField(
125+
const cel::Expr& expr) const {
126+
return expr.has_select_expr() ? absl::string_view(expr.select_expr().field())
127+
: absl::string_view();
128+
}
129+
130+
absl::StatusOr<cel::Expr> AstFactoryInterface<cel::Expr>::CopyAndReplace(
131+
const cel::Expr& expr,
132+
absl::FunctionRef<std::optional<cel::Expr>(const cel::Expr&)> replacer,
133+
int max_recursion_depth) const {
134+
if (max_recursion_depth <= 0) {
135+
return absl::InvalidArgumentError("recursion limit exceeded");
136+
}
137+
std::optional<cel::Expr> replaced = replacer(expr);
138+
if (replaced.has_value()) {
139+
return *replaced;
140+
}
141+
142+
cel::Expr new_expr = expr;
143+
switch (new_expr.kind_case()) {
144+
case cel::ExprKindCase::kUnspecifiedExpr:
145+
case cel::ExprKindCase::kConstant:
146+
case cel::ExprKindCase::kIdentExpr:
147+
break;
148+
case cel::ExprKindCase::kSelectExpr: {
149+
cel::SelectExpr& select = new_expr.mutable_select_expr();
150+
if (select.has_operand()) {
151+
CEL_ASSIGN_OR_RETURN(cel::Expr operand,
152+
CopyAndReplace(select.operand(), replacer,
153+
max_recursion_depth - 1));
154+
select.set_operand(std::move(operand));
155+
}
156+
break;
157+
}
158+
case cel::ExprKindCase::kCallExpr: {
159+
cel::CallExpr& call = new_expr.mutable_call_expr();
160+
if (call.has_target()) {
161+
CEL_ASSIGN_OR_RETURN(
162+
cel::Expr target,
163+
CopyAndReplace(call.target(), replacer, max_recursion_depth - 1));
164+
call.set_target(std::move(target));
165+
}
166+
for (auto& arg : call.mutable_args()) {
167+
CEL_ASSIGN_OR_RETURN(
168+
cel::Expr new_arg,
169+
CopyAndReplace(arg, replacer, max_recursion_depth - 1));
170+
arg = std::move(new_arg);
171+
}
172+
break;
173+
}
174+
case cel::ExprKindCase::kListExpr: {
175+
cel::ListExpr& list = new_expr.mutable_list_expr();
176+
for (auto& elem : list.mutable_elements()) {
177+
if (elem.has_expr()) {
178+
CEL_ASSIGN_OR_RETURN(
179+
cel::Expr new_elem,
180+
CopyAndReplace(elem.expr(), replacer, max_recursion_depth - 1));
181+
elem.set_expr(std::move(new_elem));
182+
}
183+
}
184+
break;
185+
}
186+
case cel::ExprKindCase::kStructExpr: {
187+
cel::StructExpr& str = new_expr.mutable_struct_expr();
188+
for (auto& field : str.mutable_fields()) {
189+
if (field.has_value()) {
190+
CEL_ASSIGN_OR_RETURN(
191+
cel::Expr new_val,
192+
CopyAndReplace(field.value(), replacer, max_recursion_depth - 1));
193+
field.set_value(std::move(new_val));
194+
}
195+
}
196+
break;
197+
}
198+
case cel::ExprKindCase::kMapExpr: {
199+
cel::MapExpr& map = new_expr.mutable_map_expr();
200+
for (auto& entry : map.mutable_entries()) {
201+
if (entry.has_key()) {
202+
CEL_ASSIGN_OR_RETURN(
203+
cel::Expr new_key,
204+
CopyAndReplace(entry.key(), replacer, max_recursion_depth - 1));
205+
entry.set_key(std::move(new_key));
206+
}
207+
if (entry.has_value()) {
208+
CEL_ASSIGN_OR_RETURN(
209+
cel::Expr new_val,
210+
CopyAndReplace(entry.value(), replacer, max_recursion_depth - 1));
211+
entry.set_value(std::move(new_val));
212+
}
213+
}
214+
break;
215+
}
216+
case cel::ExprKindCase::kComprehensionExpr: {
217+
cel::ComprehensionExpr& comp = new_expr.mutable_comprehension_expr();
218+
if (comp.has_accu_init()) {
219+
CEL_ASSIGN_OR_RETURN(cel::Expr new_accu_init,
220+
CopyAndReplace(comp.accu_init(), replacer,
221+
max_recursion_depth - 1));
222+
comp.set_accu_init(std::move(new_accu_init));
223+
}
224+
if (comp.has_iter_range()) {
225+
CEL_ASSIGN_OR_RETURN(cel::Expr new_iter_range,
226+
CopyAndReplace(comp.iter_range(), replacer,
227+
max_recursion_depth - 1));
228+
comp.set_iter_range(std::move(new_iter_range));
229+
}
230+
if (comp.has_loop_condition()) {
231+
CEL_ASSIGN_OR_RETURN(cel::Expr new_loop_condition,
232+
CopyAndReplace(comp.loop_condition(), replacer,
233+
max_recursion_depth - 1));
234+
comp.set_loop_condition(std::move(new_loop_condition));
235+
}
236+
if (comp.has_loop_step()) {
237+
CEL_ASSIGN_OR_RETURN(cel::Expr new_loop_step,
238+
CopyAndReplace(comp.loop_step(), replacer,
239+
max_recursion_depth - 1));
240+
comp.set_loop_step(std::move(new_loop_step));
241+
}
242+
if (comp.has_result()) {
243+
CEL_ASSIGN_OR_RETURN(
244+
cel::Expr new_result,
245+
CopyAndReplace(comp.result(), replacer, max_recursion_depth - 1));
246+
comp.set_result(std::move(new_result));
247+
}
248+
break;
249+
}
250+
}
251+
return new_expr;
252+
}
253+
254+
ListNodeBuilder<cel::Expr> AstFactoryInterface<cel::Expr>::NewListBuilder(
255+
int64_t id) {
256+
return ListNodeBuilder<cel::Expr>(id);
257+
}
258+
259+
StructNodeBuilder<cel::Expr> AstFactoryInterface<cel::Expr>::NewStructBuilder(
260+
int64_t id, std::string name) {
261+
return StructNodeBuilder<cel::Expr>(id, std::move(name));
262+
}
263+
264+
MapNodeBuilder<cel::Expr> AstFactoryInterface<cel::Expr>::NewMapBuilder(
265+
int64_t id) {
266+
return MapNodeBuilder<cel::Expr>(id);
267+
}
268+
269+
} // namespace cel::parser_internal

0 commit comments

Comments
 (0)