HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
predicateExpressionParser.h
Go to the documentation of this file.
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 
8 #ifndef PXR_USD_SDF_PREDICATE_EXPRESSION_PARSER_H
9 #define PXR_USD_SDF_PREDICATE_EXPRESSION_PARSER_H
10 
11 #include "pxr/pxr.h"
12 #include "pxr/usd/sdf/api.h"
13 
14 #include "pxr/base/tf/diagnostic.h"
15 #include "pxr/base/vt/value.h"
16 
17 #include "pxr/base/pegtl/pegtl.hpp"
18 
19 #include <memory>
20 
22 
23 // fwd decl, from parserHelpers.cpp.
24 std::string
25 Sdf_EvalQuotedString(const char* x, size_t n,
26  size_t trimBothSides, unsigned int* numLines=NULL);
27 
29 {
31 
32  void PushOp(SdfPredicateExpression::Op op) { _stacks.back().PushOp(op); }
33 
35  _stacks.back().PushCall(
36  kind, std::move(_funcName), std::move(_funcArgs));
37  _funcName.clear();
38  _funcArgs.clear();
39  }
40 
41  void SetFuncName(std::string const &name) {
42  _funcName = name;
43  }
44 
45  void AddFuncArg(VtValue const &val) {
46  _funcArgs.push_back({ std::move(_funcKwArgName), val });
47  _funcKwArgName.clear();
48  }
49 
50  void SetFuncArgKWName(std::string const &kw) {
51  _funcKwArgName = kw;
52  }
53 
54  void OpenGroup() { _stacks.emplace_back(); }
55 
56  void CloseGroup() {
57  SdfPredicateExpression innerExpr = _stacks.back().Finish();
58  _stacks.pop_back();
59  _stacks.back().PushExpr(std::move(innerExpr));
60  }
61 
63  SdfPredicateExpression result = _stacks.back().Finish();
64  _stacks.clear();
65  _funcArgs.clear();
66  _funcName.clear();
67  return result;
68  }
69 
70 private:
71  struct _Stack {
72 
75  auto higherPrec = [](Op left, Op right) {
76  return (left < right) || (left == right && left != Op::Not);
77  };
78  // Reduce while prior ops have higher precendence.
79  while (!opStack.empty() && higherPrec(opStack.back(), op)) {
80  _Reduce();
81  }
82  opStack.push_back(op);
83  }
84 
86  std::string &&name,
87  std::vector<SdfPredicateExpression::FnArg> &&args) {
88  exprStack.push_back(
90  kind, std::move(name), std::move(args) }));
91  }
92 
93  void PushExpr(SdfPredicateExpression &&expr) {
94  exprStack.push_back(std::move(expr));
95  }
96 
98  while (!opStack.empty()) {
99  _Reduce();
100  }
101  SdfPredicateExpression ret = std::move(exprStack.back());
102  exprStack.clear();
103  return ret;
104  }
105 
106  private:
107  void _Reduce() {
108  SdfPredicateExpression::Op op = opStack.back();
109  opStack.pop_back();
110  SdfPredicateExpression right = std::move(exprStack.back());
111  exprStack.pop_back();
112 
113  if (op == SdfPredicateExpression::Not) {
114  // Not is the only unary op.
115  exprStack.push_back(
116  SdfPredicateExpression::MakeNot(std::move(right)));
117  }
118  else {
119  // All other ops are all binary.
120  SdfPredicateExpression left = std::move(exprStack.back());
121  exprStack.pop_back();
122  exprStack.push_back(
124  op, std::move(left), std::move(right))
125  );
126  }
127  }
128 
129  // Working space.
130  std::vector<SdfPredicateExpression::Op> opStack;
131  std::vector<SdfPredicateExpression> exprStack;
132  };
133 
134  std::vector<_Stack> _stacks;
135 
136  std::string _funcName;
137  std::string _funcKwArgName;
138  std::vector<SdfPredicateExpression::FnArg> _funcArgs;
139 };
140 
141 
142 
143 ////////////////////////////////////////////////////////////////////////
144 // Grammar.
145 
146 namespace SdfPredicateExpressionParser {
147 
148 using namespace PXR_PEGTL_NAMESPACE;
149 
150 template <class Rule, class Sep>
151 using LookaheadList = seq<Rule, star<at<Sep, Rule>, Sep, Rule>>;
152 
153 template <class Rule> using OptSpaced = pad<Rule, blank>;
154 
156 
157 ////////////////////////////////////////////////////////////////////////
158 // Predicate expression grammar.
159 
160 struct NotKW : keyword<'n','o','t'> {};
161 struct AndKW : keyword<'a','n','d'> {};
162 struct OrKW : keyword<'o','r'> {};
163 struct Inf : keyword<'i','n','f'> {};
164 struct True : keyword<'t','r','u','e'> {};
165 struct False : keyword<'f','a','l','s','e'> {};
166 struct ImpliedAnd : plus<blank> {};
167 
168 struct ReservedWord : sor<
169  NotKW, AndKW, OrKW, Inf, True, False> {};
170 
171 struct Digits : plus<range<'0','9'>> {};
172 
173 struct Exp : seq<one<'e','E'>, opt<one<'-','+'>>, must<Digits>> {};
174 struct Frac : if_must<one<'.'>, Digits> {};
175 struct PredArgFloat : seq<
176  opt<one<'-'>>, sor<Inf, seq<Digits, if_then_else<Frac, opt<Exp>, Exp>>>
177  > {};
178 struct PredArgInt : seq<opt<one<'-'>>, Digits> {};
179 
180 struct PredArgBool : sor<True, False> {};
181 
182 template <class Quote>
183 struct Escaped : sor<Quote, one<'\\', 'b', 'f', 'n', 'r', 't'>> {};
184 template <class Quote>
185 struct Unescaped : minus<utf8::range<0x20, 0x10FFFF>, Quote> {};
186 
187 template <class Quote>
188 struct StringChar : if_then_else<
189  one<'\\'>, must<Escaped<Quote>>, Unescaped<Quote>> {};
190 
191 struct QuotedString : sor<
192  if_must<one<'"'>, until<one<'"'>, StringChar<one<'"'>>>>,
193  if_must<one<'\''>, until<one<'\''>, StringChar<one<'\''>>>>
194  > {};
195 
197  : sor<identifier_other,
198  one<'~', '!', '@', '#', '$', '%', '^', '&', '*', '-', '+', '=',
199  '|', '\\', '.', '?', '/'>> {};
200 
201 struct UnquotedString : star<UnquotedStringChar> {};
202 
203 struct PredArgString : sor<QuotedString, UnquotedString> {};
204 
205 struct PredArgVal : sor<
206  PredArgFloat, PredArgInt, PredArgBool, PredArgString> {};
207 
208 struct PredKWArgName : minus<identifier, ReservedWord> {};
209 
210 struct PredKWArgPrefix : seq<PredKWArgName, OptSpaced<one<'='>>> {};
211 struct PredKWArg : if_must<PredKWArgPrefix, PredArgVal> {};
212 
213 struct PredParenPosArg : seq<not_at<PredKWArgPrefix>, PredArgVal> {};
214 
215 struct PredFuncName : minus<identifier, ReservedWord> {};
216 
218  : if_then_else<list<PredParenPosArg, OptSpacedComma>,
219  opt<OptSpacedComma, list<PredKWArg, OptSpacedComma>>,
220  opt<list<PredKWArg, OptSpacedComma>>>
221 {};
222 
223 struct PredColonArgs : list<PredArgVal, one<','>> {};
224 struct PredColonCall : if_must<seq<PredFuncName, one<':'>>, PredColonArgs> {};
225 struct PredParenCall : seq<
226  PredFuncName, OptSpaced<one<'('>>,
227  must<PredParenArgs, star<blank>, one<')'>>
228  >
229 {};
230 
232 
233 struct PredExpr;
234 
235 struct PredOpenGroup : one<'('> {};
236 struct PredCloseGroup : one<')'> {};
237 
238 struct PredAtom
239  : sor<
240  PredColonCall,
241  PredParenCall,
242  PredBareCall,
243  if_must<PredOpenGroup, OptSpaced<PredExpr>, PredCloseGroup>
244  >
245 {};
246 
247 struct PredFactor : seq<opt<OptSpaced<list<NotKW, plus<blank>>>>, PredAtom> {};
248 struct PredOperator : sor<OptSpaced<AndKW>, OptSpaced<OrKW>, ImpliedAnd> {};
249 struct PredExpr : LookaheadList<PredFactor, PredOperator> {};
250 
251 // Actions ///////////////////////////////////////////////////////////////
252 
253 template <class Rule>
254 struct PredAction : nothing<Rule> {};
255 
256 template <SdfPredicateExpression::Op op>
258 {
259  template <class Input>
260  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
261  builder.PushOp(op);
262  }
263 };
264 
265 template <> struct PredAction<NotKW>
266  : PredOpAction<SdfPredicateExpression::Not> {};
267 template <> struct PredAction<AndKW>
268  : PredOpAction<SdfPredicateExpression::And> {};
269 template <> struct PredAction<OrKW>
270  : PredOpAction<SdfPredicateExpression::Or> {};
271 template <> struct PredAction<ImpliedAnd>
272  : PredOpAction<SdfPredicateExpression::ImpliedAnd> {};
273 
274 template <>
276 {
277  template <class Input>
278  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
279  builder.OpenGroup();
280  }
281 };
282 
283 template <>
284 struct PredAction<PredCloseGroup>
285 {
286  template <class Input>
287  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
288  builder.CloseGroup();
289  }
290 };
291 
292 template <>
294 {
295  template <class Input>
296  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
297  builder.SetFuncName(in.string());
298  }
299 };
300 
301 template <>
303 {
304  template <class Input>
305  static bool apply(Input const &in, SdfPredicateExprBuilder &builder) {
306  bool outOfRange = false;
307  int64_t ival = TfStringToInt64(in.string(), &outOfRange);
308  if (outOfRange) {
309  return false;
310  }
311  builder.AddFuncArg(VtValue(ival));
312  return true;
313  }
314 };
315 
316 template <>
318 {
319  template <class Input>
320  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
321  builder.AddFuncArg(VtValue(in.string()[0] == 't'));
322  }
323 };
324 
325 template <>
327 {
328  template <class Input>
329  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
330  std::string const &instr = in.string();
331  double fval;
332  if (instr == "inf") {
333  fval = std::numeric_limits<double>::infinity();
334  }
335  else if (instr == "-inf") {
336  fval = -std::numeric_limits<double>::infinity();
337  }
338  else {
339  fval = TfStringToDouble(instr);
340  }
341  builder.AddFuncArg(VtValue(fval));
342  }
343 };
344 
345 template <>
347 {
348  template <class Input>
349  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
350  std::string const &instr = in.string();
351  size_t trimAmount = 0;
352  if (instr.size() >= 2 &&
353  ((instr.front() == '"' && instr.back() == '"') ||
354  (instr.front() == '\'' && instr.back() == '\''))) {
355  trimAmount = 1;
356  }
357  builder.AddFuncArg(
359  instr.c_str(), instr.size(), trimAmount)));
360  }
361 };
362 
363 template <>
365 {
366  template <class Input>
367  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
368  builder.SetFuncArgKWName(in.string());
369  }
370 };
371 
372 template <SdfPredicateExpression::FnCall::Kind callKind>
374 {
375  template <class Input>
376  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
377  builder.PushCall(callKind);
378  }
379 };
380 template <> struct PredAction<PredBareCall>
381  : PredCallAction<SdfPredicateExpression::FnCall::BareCall> {};
382 template <> struct PredAction<PredParenCall>
383  : PredCallAction<SdfPredicateExpression::FnCall::ParenCall> {};
384 template <> struct PredAction<PredColonCall>
385  : PredCallAction<SdfPredicateExpression::FnCall::ColonCall> {};
386 
387 }
388 
390 
391 #endif // PXR_USD_SDF_PREDICATE_EXPRESSION_PARSER_H
static void apply(Input const &in, SdfPredicateExprBuilder &builder)
seq< Rule, star< at< Sep, Rule >, Sep, Rule >> LookaheadList
GLint left
Definition: glcorearb.h:2005
GLdouble right
Definition: glad.h:2817
static SDF_API SdfPredicateExpression MakeCall(FnCall &&call)
Produce a new expression containing just a the function call call.
TF_API double TfStringToDouble(const std::string &txt)
**But if you need a result
Definition: thread.h:622
static void apply(Input const &in, SdfPredicateExprBuilder &builder)
constexpr auto in(type t, int set) -> bool
Definition: core.h:611
static void apply(Input const &in, SdfPredicateExprBuilder &builder)
static void apply(Input const &in, SdfPredicateExprBuilder &builder)
static bool apply(Input const &in, SdfPredicateExprBuilder &builder)
static void apply(Input const &in, SdfPredicateExprBuilder &builder)
void SetFuncArgKWName(std::string const &kw)
GLdouble n
Definition: glcorearb.h:2008
static void apply(Input const &in, SdfPredicateExprBuilder &builder)
static void apply(Input const &in, SdfPredicateExprBuilder &builder)
static void apply(Input const &in, SdfPredicateExprBuilder &builder)
void PushCall(SdfPredicateExpression::FnCall::Kind kind)
void AddFuncArg(VtValue const &val)
PXR_NAMESPACE_OPEN_SCOPE std::string Sdf_EvalQuotedString(const char *x, size_t n, size_t trimBothSides, unsigned int *numLines=NULL)
GLuint const GLchar * name
Definition: glcorearb.h:786
static SDF_API SdfPredicateExpression MakeOp(Op op, SdfPredicateExpression &&left, SdfPredicateExpression &&right)
GLint GLenum GLint x
Definition: glcorearb.h:409
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
static SDF_API SdfPredicateExpression MakeNot(SdfPredicateExpression &&right)
Produce a new expression by prepending the 'not' operator onto right.
SdfPredicateExpression Finish()
GLuint GLfloat * val
Definition: glcorearb.h:1608
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
static void apply(Input const &in, SdfPredicateExprBuilder &builder)
**If you just want to fire and args
Definition: thread.h:618
void PushOp(SdfPredicateExpression::Op op)
Op
Enumerant describing a subexpression operation.
TF_API int64_t TfStringToInt64(const std::string &txt, bool *outOfRange=NULL)
Definition: value.h:146
void SetFuncName(std::string const &name)