Loading...
Searching...
No Matches
predicateExpression.h
1//
2// Copyright 2023 Pixar
3//
4// Licensed under the Apache License, Version 2.0 (the "Apache License")
5// with the following modification; you may not use this file except in
6// compliance with the Apache License and the following modification to it:
7// Section 6. Trademarks. is deleted and replaced with:
8//
9// 6. Trademarks. This License does not grant permission to use the trade
10// names, trademarks, service marks, or product names of the Licensor
11// and its affiliates, except as required to comply with Section 4(c) of
12// the License and to reproduce the content of the NOTICE file.
13//
14// You may obtain a copy of the Apache License at
15//
16// http://www.apache.org/licenses/LICENSE-2.0
17//
18// Unless required by applicable law or agreed to in writing, software
19// distributed under the Apache License with the above modification is
20// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21// KIND, either express or implied. See the Apache License for the specific
22// language governing permissions and limitations under the Apache License.
23//
24#ifndef PXR_USD_SDF_PREDICATE_EXPRESSION_H
25#define PXR_USD_SDF_PREDICATE_EXPRESSION_H
26
27#include "pxr/pxr.h"
28#include "pxr/usd/sdf/api.h"
29#include "pxr/base/tf/hash.h"
30#include "pxr/base/vt/value.h"
31
32#include <iosfwd>
33#include <string>
34#include <tuple>
35#include <utility>
36#include <vector>
37
38PXR_NAMESPACE_OPEN_SCOPE
39
85{
86public:
87
92 struct FnArg {
93 static FnArg Positional(VtValue const &val) {
94 return { std::string(), val };
95 }
96 static FnArg Keyword(std::string const &name, VtValue const &val) {
97 return { name, val };
98 }
99 std::string argName;
100 VtValue value;
101
102 template <class HashState>
103 friend void TfHashAppend(HashState &h, FnArg const &arg) {
104 h.Append(arg.argName, arg.value);
105 }
106
107 friend bool operator==(FnArg const &l, FnArg const &r) {
108 return std::tie(l.argName, l.value) == std::tie(r.argName, r.value);
109 }
110 friend bool operator!=(FnArg const &l, FnArg const &r) {
111 return !(l == r);
112 }
113
114 friend void swap(FnArg &l, FnArg &r) {
115 swap(l.argName, r.argName);
116 swap(l.value, r.value);
117 }
118 };
119
124 struct FnCall {
125 enum Kind {
128 ParenCall
129 };
130
131 Kind kind;
132 std::string funcName;
133 std::vector<FnArg> args;
134
135 template <class HashState>
136 friend void TfHashAppend(HashState &h, FnCall const &c) {
137 h.Append(c.kind, c.funcName, c.args);
138 }
139
140 friend bool operator==(FnCall const &l, FnCall const &r) {
141 return std::tie(l.kind, l.funcName, l.args) ==
142 std::tie(r.kind, r.funcName, r.args);
143 }
144 friend bool operator!=(FnCall const &l, FnCall const &r) {
145 return !(l == r);
146 }
147 friend void swap(FnCall &l, FnCall &r) {
148 auto lt = std::tie(l.kind, l.funcName, l.args);
149 auto rt = std::tie(r.kind, r.funcName, r.args);
150 swap(lt, rt);
151 }
152 };
153
156
159
162
166 SDF_API
167 explicit SdfPredicateExpression(std::string const &expr,
168 std::string const &context = {});
169
173
177
179 enum Op { Call, Not, ImpliedAnd, And, Or };
180
182 SDF_API
185
188 SDF_API
192 SdfPredicateExpression &&right);
193
195 SDF_API
198
228 SDF_API
229 void Walk(TfFunctionRef<void (Op, int)> logic,
230 TfFunctionRef<void (FnCall const &)> call) const;
231
237 SDF_API
239 TfFunctionRef<void (std::vector<std::pair<Op, int>> const &)> logic,
240 TfFunctionRef<void (FnCall const &)> call) const;
241
244 SDF_API
245 std::string GetText() const;
246
249 bool IsEmpty() const {
250 return _ops.empty();
251 }
252
254 explicit operator bool() const {
255 return !IsEmpty();
256 }
257
260 std::string const &GetParseError() const & {
261 return _parseError;
262 }
263
266 std::string GetParseError() const && {
267 return _parseError;
268 }
269
270private:
271 template <class HashState>
272 friend void TfHashAppend(HashState &h, SdfPredicateExpression const &expr) {
273 h.Append(expr._ops, expr._calls, expr._parseError);
274 }
275
276 friend bool
277 operator==(SdfPredicateExpression const &l,
278 SdfPredicateExpression const &r) {
279 return std::tie(l._ops, l._calls, l._parseError) ==
280 std::tie(r._ops, r._calls, r._parseError);
281 }
282
283 friend bool
284 operator!=(SdfPredicateExpression const &l,
285 SdfPredicateExpression const &r) {
286 return !(l == r);
287 }
288
289 SDF_API
290 friend std::ostream &
291 operator<<(std::ostream &, SdfPredicateExpression const &);
292
293 // The expression is represented in function-call style, but *in reverse* to
294 // facilitate efficient assembly. For example, an expression like "a and b"
295 // would be represented as { Call(b), Call(a), And } rather than { And,
296 // Call(a), Call(b) }. This way, joining two expressions like "a" 'and' "b"
297 // can be done by appending to a vector, avoiding having to shift all the
298 // elements down to insert the new operation at the head. See the
299 // implementation of Walk() for guidance.
300 std::vector<Op> _ops;
301
302 // On the contrary, the elements in _calls are in forward-order, so the last
303 // Call in _ops corresponds to the first element of _calls.
304 std::vector<FnCall> _calls;
305
306 // This member holds a parsing error string if this expression was
307 // constructed by the parser and errors were encountered during the parsing.
308 std::string _parseError;
309};
310
311PXR_NAMESPACE_CLOSE_SCOPE
312
313#endif // PXR_USD_SDF_PREDICATE_EXPRESSION_H
Represents a logical expression syntax tree consisting of predicate function calls joined by the logi...
SdfPredicateExpression()=default
Construct the empty expression whose bool-operator returns false.
SdfPredicateExpression & operator=(SdfPredicateExpression &&)=default
Move assign from another expression.
SdfPredicateExpression & operator=(SdfPredicateExpression const &)=default
Copy assign from another expression.
std::string GetParseError() const &&
Return parsing errors as a string if this function was constructed from a string and parse errors wer...
SDF_API std::string GetText() const
Return a text representation of this expression that parses to the same expression.
Op
Enumerant describing a subexpression operation.
SDF_API void Walk(TfFunctionRef< void(Op, int)> logic, TfFunctionRef< void(FnCall const &)> call) const
Walk this expression's syntax tree in depth-first order, calling call with the current function call ...
static SDF_API SdfPredicateExpression MakeOp(Op op, SdfPredicateExpression &&left, SdfPredicateExpression &&right)
Produce a new expression by combining left and right with the operator op.
static SDF_API SdfPredicateExpression MakeNot(SdfPredicateExpression &&right)
Produce a new expression by prepending the 'not' operator onto right.
SdfPredicateExpression(SdfPredicateExpression &&)=default
Move construct from another expression.
bool IsEmpty() const
Return true if this is the empty expression; i.e.
static SDF_API SdfPredicateExpression MakeCall(FnCall &&call)
Produce a new expression containing just a the function call call.
SdfPredicateExpression(SdfPredicateExpression const &)=default
Copy construct from another expression.
std::string const & GetParseError() const &
Return parsing errors as a string if this function was constructed from a string and parse errors wer...
SDF_API void WalkWithOpStack(TfFunctionRef< void(std::vector< std::pair< Op, int > > const &)> logic, TfFunctionRef< void(FnCall const &)> call) const
Equivalent to Walk(), except that the logic function is called with a const reference to the current ...
SDF_API SdfPredicateExpression(std::string const &expr, std::string const &context={})
Construct an expression by parsing expr.
This class provides a non-owning reference to a type-erased callable object with a specified signatur...
Definition: functionRef.h:36
Provides a container which may hold any type, and provides introspection and iteration over array typ...
Definition: value.h:164
Represents a function argument name and value.
Represents a function call in an expression with calling style, function name, and arguments.
@ BareCall
no-arg call like 'active'
@ ParenCall
paren/comma & pos/kw args like 'foo(23, bar=baz)'
@ ColonCall
colon-separated pos args, like 'isa:Imageable'