HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pathExpression.h
Go to the documentation of this file.
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_PATH_EXPRESSION_H
25 #define PXR_USD_SDF_PATH_EXPRESSION_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/usd/sdf/api.h"
29 #include "pxr/usd/sdf/path.h"
31 
32 #include <string>
33 #include <vector>
34 
36 
37 /// \class SdfPathExpression
38 ///
39 /// Objects of this class represent a logical expression syntax tree consisting
40 /// of SdfPath matching patterns (with optionally embedded predicate
41 /// expressions) joined by the set-algebraic operators '+' (union), '&'
42 /// (intersection), '-' (difference), '~' (complement) and an implied-union
43 /// operator represented by two subexpressions joined by whitespace.
44 ///
45 /// An SdfPathExpression can be constructed from a string, which will parse the
46 /// string into an expression object. The syntax for an expression is as
47 /// follows:
48 ///
49 /// The fundamental building blocks are path patterns and expression references.
50 /// A path pattern is similar to an SdfPath, but it may contain glob-style
51 /// wild-card characters, embedded brace-enclosed predicate expressions (see
52 /// SdfPredicateExpression) and '//' elements indicating arbitrary levels of
53 /// prim hierarchy. For example, consider "/foo//bar*/baz{active:false}". This
54 /// pattern matches absolute paths whose first component is 'foo', that also
55 /// have some descendant prim whose name begins with 'bar', which in turn has a
56 /// child named 'baz' where the predicate "active:false" evaluates to true.
57 ///
58 /// An expression reference starts with '%' followed by a prim path, a ':', and
59 /// a name. There is also one "special" expression reference, "%_" which means
60 /// "the weaker" expression when composing expressions together. See
61 /// ComposeOver() and ResolveReferences() for more information.
62 ///
63 /// These building blocks may be joined as mentioned above, with '+', '-', '&',
64 /// or whitespace, and may be complemented with '~', and grouped with '(' and
65 /// ')'.
67 {
68 public:
69  /// \class PathPattern
70  ///
71  /// Objects of this class represent SdfPath matching patterns, consisting of
72  /// an SdfPath prefix followed by a sequence of components, which may
73  /// contain wildcards and optional embedded predicate expressions (see
74  /// SdfPredicateExpression).
75  class PathPattern
76  {
77  public:
78  /// Construct the empty pattern whose bool-conversion operator returns
79  /// false.
80  SDF_API
81  PathPattern();
82 
83  /// A component represents a pattern matching component past the initial
84  /// SdfPath prefix. A component's text can contain wildcard characters,
85  /// and if the component references a predicate expression, its
86  /// predicateIndex indicates which one in the owning PathPattern's list
87  /// of expressions. A component whose text is empty represents an
88  /// "arbitrary levels of hierarchy" element (the //) in a path pattern.
89  struct Component {
90  bool IsStretch() const {
91  return predicateIndex == -1 && text.empty();
92  }
93  std::string text;
94  int predicateIndex = -1;
95  bool isLiteral = false;
96  };
97 
98  /// Append a prim child component to this pattern, with optional
99  /// predicate expression \p predExpr. If this pattern does not yet
100  /// contain any wildcards or components with predicate expressions, and
101  /// the input text does not contain wildcards, and \p predExpr is empty,
102  /// then append a child component to this pattern's prefix path (see
103  /// GetPrefix()). Otherwise append this component to the sequence of
104  /// components.
105  SDF_API
106  void AppendChild(std::string const &text,
107  SdfPredicateExpression &&predExpr);
108  /// \overload
109  SDF_API
110  void AppendChild(std::string const &text,
111  SdfPredicateExpression const &predExpr);
112  /// \overload
113  SDF_API
114  void AppendChild(std::string const &text);
115 
116  /// Append a prim property component to this pattern, with optional
117  /// predicate expression \p predExpr. If this pattern does not yet
118  /// contain any wildcards or components with predicate expressions, and
119  /// the input text does not contain wildcards, and \p predExpr is empty,
120  /// then append a property component to this pattern's prefix path (see
121  /// GetPrefix()). Otherwise append this component to the sequence of
122  /// components.
123  SDF_API
124  void AppendProperty(std::string const &text,
125  SdfPredicateExpression &&predExpr);
126  /// \overload
127  SDF_API
128  void AppendProperty(std::string const &text,
129  SdfPredicateExpression const &predExpr);
130  /// \overload
131  SDF_API
132  void AppendProperty(std::string const &text);
133 
134  /// Return this pattern's non-speculative prefix (leading path
135  /// components with no wildcards and no predicates).
136  SdfPath const &GetPrefix() const & {
137  return _prefix;
138  }
139 
140  /// \overload.
141  SdfPath GetPrefix() && {
142  return std::move(_prefix);
143  }
144 
145  /// Set this pattern's non-speculative prefix (leading path
146  /// components with no wildcards and no predicates).
147  SDF_API
148  void SetPrefix(SdfPath &&p);
149 
150  /// \overload
151  void SetPrefix(SdfPath const &p) {
152  SetPrefix(SdfPath(p));
153  }
154 
155  /// Return a debugging-oriented string representation of this pattern.
156  SDF_API
157  std::string GetDebugString() const;
158 
159  std::vector<Component> const &GetComponents() const & {
160  return _components;
161  }
162 
163  std::vector<Component> GetComponents() && {
164  return _components;
165  }
166 
167  std::vector<SdfPredicateExpression> const &
168  GetPredicateExprs() const & {
169  return _predExprs;
170  }
171 
172  std::vector<SdfPredicateExpression>
173  GetPredicateExprs() && {
174  return _predExprs;
175  }
176 
177  bool IsProperty() const {
178  return _isProperty;
179  }
180 
181  /// Return true if this pattern is not empty, false if it is.
182  explicit operator bool() const {
183  return !_prefix.IsEmpty();
184  }
185 
186  private:
187  SdfPath _prefix;
188  std::vector<Component> _components;
189  std::vector<SdfPredicateExpression> _predExprs;
190  bool _isProperty;
191  };
192 
193  /// \class ExpressionReference
194  ///
195  /// Objects of this class represent references to other path expressions,
196  /// which will be resolved later by a call to ResolveReferences() or
197  /// ComposeOver().
198  class ExpressionReference {
199  public:
200  // Optional path reference, can be empty for "weaker" references (name
201  // is "_") or for references to local collections.
202  SdfPath path;
203 
204  // Name is either a property name, or "_" (meaning the weaker
205  // collection). If the name is "_", the path must be empty.
207  };
208 
209  /// Enumerant describing a subexpression operation.
210  enum Op {
211  // Operations on atoms.
212  Complement,
213  ImpliedUnion,
214  Union,
215  Intersection,
216  Difference,
217 
218  // Atoms.
219  ExpressionRef,
220  Pattern
221  };
222 
223  /// Default construction produces the "empty" expression. Conversion to
224  /// bool returns 'false'.
225  SdfPathExpression() = default;
226 
227  /// Construct an expression by parsing \p expr. If provided, \p
228  /// parseContext appears in a parse error, if one is generated. See
229  /// GetParseError(). See the class documentation for details on expression
230  /// syntax.
231  SDF_API
232  explicit SdfPathExpression(std::string const &expr,
233  std::string const &parseContext = {});
234 
235  /// Produce a new expression representing the set-complement of \p right.
236  SDF_API
237  static SdfPathExpression
238  MakeComplement(SdfPathExpression &&right);
239 
240  /// \overload
241  static SdfPathExpression
242  MakeComplement(SdfPathExpression const &right) {
243  return MakeComplement(SdfPathExpression(right));
244  }
245 
246  /// Produce a new expression representing the set-algebraic operation \p op
247  /// with operands \p left and \p right. The \p op must be one of
248  /// ImpliedUnion, Union, Intersection, or Difference.
249  SDF_API
250  static SdfPathExpression
251  MakeOp(Op op, SdfPathExpression &&left, SdfPathExpression &&right);
252 
253  /// \overload
254  static SdfPathExpression
255  MakeOp(Op op,
256  SdfPathExpression const &left,
257  SdfPathExpression const &right) {
258  return MakeOp(op, SdfPathExpression(left), SdfPathExpression(right));
259  }
260 
261  /// Produce a new expression containing only the reference \p ref.
262  SDF_API
263  static SdfPathExpression
264  MakeAtom(ExpressionReference &&ref);
265 
266  /// \overload
267  static SdfPathExpression
268  MakeAtom(ExpressionReference const &ref) {
269  return MakeAtom(ExpressionReference(ref));
270  }
271 
272  /// Produce a new expression containing only the pattern \p pattern.
273  SDF_API
274  static SdfPathExpression
275  MakeAtom(PathPattern &&pattern);
276 
277  /// \overload
278  static SdfPathExpression
279  MakeAtom(PathPattern const &pattern) {
280  return MakeAtom(PathPattern(pattern));
281  }
282 
283  /// Walk this expression's syntax tree in depth-first order, calling \p
284  /// pattern with the current PathPattern when one is encountered, \p ref
285  /// with the current ExpressionReference when one is encountered, and \p
286  /// logic multiple times for each logical operation encountered. When
287  /// calling \p logic, the logical operation is passed as the \p Op
288  /// parameter, and an integer indicating "where" we are in the set of
289  /// operands is passed as the int parameter. For a Complement, call \p
290  /// logic(Op=Complement, int=0) to start, then after the subexpression that
291  /// the Complement applies to is walked, call \p logic(Op=Complement,
292  /// int=1). For the other operators like Union and Intersection, call \p
293  /// logic(Op, 0) before the first argument, then \p logic(Op, 1) after the
294  /// first subexpression, then \p logic(Op, 2) after the second
295  /// subexpression. For a concrete example, consider the following
296  /// expression:
297  ///
298  /// /foo/bar// /foo/baz// & ~/foo/bar/qux// %_
299  ///
300  /// logic(Intersection, 0)
301  /// logic(ImpliedUnion, 0)
302  /// pattern(/foo/bar//)
303  /// logic(ImpliedUnion, 1)
304  /// pattern(/foo/baz//)
305  /// logic(ImpliedUnion, 2)
306  /// logic(Intersection, 1)
307  /// logic(ImpliedUnion, 0)
308  /// logic(Complement, 0)
309  /// pattern(/foo/bar/qux//)
310  /// logic(Complement, 1)
311  /// logic(ImpliedUnion, 1)
312  /// ref(%_)
313  /// logic(ImpliedUnion, 2)
314  /// logic(Intersection, 2)
315  ///
316  SDF_API
317  void Walk(TfFunctionRef<void (Op, int)> logic,
318  TfFunctionRef<void (ExpressionReference const &)> ref,
319  TfFunctionRef<void (PathPattern const &)> pattern) const;
320 
321  /// Return a new expression created by replacing literal path prefixes that
322  /// start with \p oldPrefix with \p newPrefix.
324  ReplacePrefix(SdfPath const &oldPrefix,
325  SdfPath const &newPrefix) const & {
326  return SdfPathExpression(*this).ReplacePrefix(oldPrefix, newPrefix);
327  }
328 
329  /// Return a new expression created by replacing literal path prefixes that
330  /// start with \p oldPrefix with \p newPrefix.
331  SDF_API
333  ReplacePrefix(SdfPath const &oldPrefix,
334  SdfPath const &newPrefix) &&;
335 
336  /// Return true if all contained pattern prefixes are absolute, false
337  /// otherwise. Call MakeAbsolute() to anchor any relative paths and make
338  /// them absolute.
339  SDF_API
340  bool IsAbsolute() const;
341 
342  /// Return a new expression created by making any relative path prefixes in
343  /// this expression absolute by SdfPath::MakeAbsolutePath().
345  MakeAbsolute(SdfPath const &anchor) const & {
346  return SdfPathExpression(*this).MakeAbsolute(anchor);
347  }
348 
349  /// Return a new expression created by making any relative path prefixes in
350  /// this expression absolute by SdfPath::MakeAbsolutePath().
351  SDF_API
353  MakeAbsolute(SdfPath const &anchor) &&;
354 
355  /// Return true if this expression contains any references to other
356  /// collections.
357  bool ContainsExpressionReferences() const {
358  return !_refs.empty();
359  }
360 
361  /// Return a new expression created by resolving collection references in
362  /// this expression. Call \p resolve to produce an subexpression from a
363  /// %-referenced collection. By convention, the empty SdfPath represents
364  /// the "weaker" %_ reference. If \p resolve returns the empty
365  /// SdfPathExpression, the reference is not resolved and persists in the
366  /// output.
368  ResolveReferences(
370  ExpressionReference const &)> resolve) const & {
371  return SdfPathExpression(*this).ResolveReferences(resolve);
372  }
373 
374  /// \overload
375  SDF_API
377  ResolveReferences(
379  ExpressionReference const &)> resolve) &&;
380 
381  /// Return a new expression created by replacing references to the "weaker
382  /// expression" (i.e. %_) in this expression with \p weaker. This is a
383  /// restricted form of ResolveReferences() that only resolves "weaker"
384  /// references, replacing them by \p weaker, leaving other references
385  /// unmodified.
387  ComposeOver(SdfPathExpression const &weaker) const & {
388  return SdfPathExpression(*this).ComposeOver(weaker);
389  }
390 
391  /// \overload
392  SDF_API
394  ComposeOver(SdfPathExpression const &weaker) &&;
395 
396  /// Return true if this expression is considered "complete". Here, complete
397  /// means that the expression has all absolute paths, and contains no
398  /// expression references. This is equivalent to:
399  ///
400  /// \code
401  /// !expr.ContainsExpressionReferences() && expr.IsAbsolute()
402  /// \endcode
403  ///
404  /// To complete an expression, call MakeAbsolute(), ResolveReferences()
405  /// and/or ComposeOver().
406  bool IsComplete() const {
407  return !ContainsExpressionReferences() && IsAbsolute();
408  }
409 
410  /// Return a debugging-oriented string representation of this expression.
411  SDF_API
412  std::string GetDebugString() const;
413 
414  /// Return true if this is the empty expression; i.e. default-constructed or
415  /// constructed from a string with invalid syntax.
416  bool IsEmpty() const {
417  return _ops.empty();
418  }
419 
420  /// Return true if this expression contains any operations, false otherwise.
421  explicit operator bool() const {
422  return !IsEmpty();
423  }
424 
425  /// Return parsing errors as a string if this function was constructed from
426  /// a string and parse errors were encountered.
427  std::string const &GetParseError() const & {
428  return _parseError;
429  }
430 
431 private:
432 
433  std::vector<Op> _ops;
434  std::vector<ExpressionReference> _refs;
435  std::vector<PathPattern> _patterns;
436 
437  // This member holds a parsing error string if this expression was
438  // constructed by the parser and errors were encountered during the parsing.
439  std::string _parseError;
440 };
441 
442 
444 
445 #endif // PXR_USD_SDF_PATH_EXPRESSION_H
GLint left
Definition: glcorearb.h:2005
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
GLsizei const GLchar *const * path
Definition: glcorearb.h:3341
GLdouble right
Definition: glad.h:2817
GLint ref
Definition: glcorearb.h:124
Definition: path.h:291
GLushort pattern
Definition: glad.h:2583
#define SDF_API
Definition: api.h:40
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1441
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
#define const
Definition: zconf.h:214