Loading...
Searching...
No Matches
predicateExpression.h
1//
2// Copyright 2023 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_USD_SDF_PREDICATE_EXPRESSION_H
8#define PXR_USD_SDF_PREDICATE_EXPRESSION_H
9
10#include "pxr/pxr.h"
11#include "pxr/usd/sdf/api.h"
12#include "pxr/base/tf/hash.h"
13#include "pxr/base/vt/value.h"
14
15#include <iosfwd>
16#include <string>
17#include <tuple>
18#include <utility>
19#include <vector>
20
21PXR_NAMESPACE_OPEN_SCOPE
22
68{
69public:
70
75 struct FnArg {
76 static FnArg Positional(VtValue const &val) {
77 return { std::string(), val };
78 }
79 static FnArg Keyword(std::string const &name, VtValue const &val) {
80 return { name, val };
81 }
82 std::string argName;
83 VtValue value;
84
85 template <class HashState>
86 friend void TfHashAppend(HashState &h, FnArg const &arg) {
87 h.Append(arg.argName, arg.value);
88 }
89
90 friend bool operator==(FnArg const &l, FnArg const &r) {
91 return std::tie(l.argName, l.value) == std::tie(r.argName, r.value);
92 }
93 friend bool operator!=(FnArg const &l, FnArg const &r) {
94 return !(l == r);
95 }
96
97 friend void swap(FnArg &l, FnArg &r) {
98 swap(l.argName, r.argName);
99 swap(l.value, r.value);
100 }
101 };
102
107 struct FnCall {
108 enum Kind {
111 ParenCall
112 };
113
114 Kind kind;
115 std::string funcName;
116 std::vector<FnArg> args;
117
118 template <class HashState>
119 friend void TfHashAppend(HashState &h, FnCall const &c) {
120 h.Append(c.kind, c.funcName, c.args);
121 }
122
123 friend bool operator==(FnCall const &l, FnCall const &r) {
124 return std::tie(l.kind, l.funcName, l.args) ==
125 std::tie(r.kind, r.funcName, r.args);
126 }
127 friend bool operator!=(FnCall const &l, FnCall const &r) {
128 return !(l == r);
129 }
130 friend void swap(FnCall &l, FnCall &r) {
131 auto lt = std::tie(l.kind, l.funcName, l.args);
132 auto rt = std::tie(r.kind, r.funcName, r.args);
133 swap(lt, rt);
134 }
135 };
136
139
142
145
149 SDF_API
150 explicit SdfPredicateExpression(std::string const &expr,
151 std::string const &context = {});
152
156
160
162 enum Op { Call, Not, ImpliedAnd, And, Or };
163
165 SDF_API
168
171 SDF_API
175 SdfPredicateExpression &&right);
176
178 SDF_API
181
211 SDF_API
212 void Walk(TfFunctionRef<void (Op, int)> logic,
213 TfFunctionRef<void (FnCall const &)> call) const;
214
220 SDF_API
222 TfFunctionRef<void (std::vector<std::pair<Op, int>> const &)> logic,
223 TfFunctionRef<void (FnCall const &)> call) const;
224
227 SDF_API
228 std::string GetText() const;
229
232 bool IsEmpty() const {
233 return _ops.empty();
234 }
235
237 explicit operator bool() const {
238 return !IsEmpty();
239 }
240
243 std::string const &GetParseError() const & {
244 return _parseError;
245 }
246
249 std::string GetParseError() && {
250 return std::move(_parseError);
251 }
252
253private:
254 template <class HashState>
255 friend void TfHashAppend(HashState &h, SdfPredicateExpression const &expr) {
256 h.Append(expr._ops, expr._calls, expr._parseError);
257 }
258
259 friend bool
260 operator==(SdfPredicateExpression const &l,
261 SdfPredicateExpression const &r) {
262 return std::tie(l._ops, l._calls, l._parseError) ==
263 std::tie(r._ops, r._calls, r._parseError);
264 }
265
266 friend bool
267 operator!=(SdfPredicateExpression const &l,
268 SdfPredicateExpression const &r) {
269 return !(l == r);
270 }
271
272 SDF_API
273 friend std::ostream &
274 operator<<(std::ostream &, SdfPredicateExpression const &);
275
276 // The expression is represented in function-call style, but *in reverse* to
277 // facilitate efficient assembly. For example, an expression like "a and b"
278 // would be represented as { Call(b), Call(a), And } rather than { And,
279 // Call(a), Call(b) }. This way, joining two expressions like "a" 'and' "b"
280 // can be done by appending to a vector, avoiding having to shift all the
281 // elements down to insert the new operation at the head. See the
282 // implementation of Walk() for guidance.
283 std::vector<Op> _ops;
284
285 // On the contrary, the elements in _calls are in forward-order, so the last
286 // Call in _ops corresponds to the first element of _calls.
287 std::vector<FnCall> _calls;
288
289 // This member holds a parsing error string if this expression was
290 // constructed by the parser and errors were encountered during the parsing.
291 std::string _parseError;
292};
293
294PXR_NAMESPACE_CLOSE_SCOPE
295
296#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.
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.
std::string GetParseError() &&
Return parsing errors as a string if this function was constructed from a string and parse errors wer...
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:19
Provides a container which may hold any type, and provides introspection and iteration over array typ...
Definition: value.h:152
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'