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 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 
25 #ifndef PXR_USD_SDF_PREDICATE_EXPRESSION_PARSER_H
26 #define PXR_USD_SDF_PREDICATE_EXPRESSION_PARSER_H
27 
28 #include "pxr/pxr.h"
29 #include "pxr/usd/sdf/api.h"
30 
31 #include "pxr/base/tf/diagnostic.h"
32 #include "pxr/base/vt/value.h"
33 
34 #include "pxr/base/tf/pxrPEGTL/pegtl.h"
35 
36 #include <memory>
37 
39 
40 // fwd decl, from parserHelpers.cpp.
42 Sdf_EvalQuotedString(const char* x, size_t n,
43  size_t trimBothSides, unsigned int* numLines=NULL);
44 
46 {
48 
49  void PushOp(SdfPredicateExpression::Op op) { _stacks.back().PushOp(op); }
50 
52  _stacks.back().PushCall(
53  kind, std::move(_funcName), std::move(_funcArgs));
54  _funcName.clear();
55  _funcArgs.clear();
56  }
57 
58  void SetFuncName(std::string const &name) {
59  _funcName = name;
60  }
61 
62  void AddFuncArg(VtValue const &val) {
63  _funcArgs.push_back({ std::move(_funcKwArgName), val });
64  _funcKwArgName.clear();
65  }
66 
67  void SetFuncArgKWName(std::string const &kw) {
68  _funcKwArgName = kw;
69  }
70 
71  void OpenGroup() { _stacks.emplace_back(); }
72 
73  void CloseGroup() {
74  SdfPredicateExpression innerExpr = _stacks.back().Finish();
75  _stacks.pop_back();
76  _stacks.back().PushExpr(std::move(innerExpr));
77  }
78 
80  SdfPredicateExpression result = _stacks.back().Finish();
81  _stacks.clear();
82  _funcArgs.clear();
83  _funcName.clear();
84  return result;
85  }
86 
87 private:
88  struct _Stack {
89 
92  auto higherPrec = [](Op left, Op right) {
93  return (left < right) || (left == right && left != Op::Not);
94  };
95  // Reduce while prior ops have higher precendence.
96  while (!opStack.empty() && higherPrec(opStack.back(), op)) {
97  _Reduce();
98  }
99  opStack.push_back(op);
100  }
101 
103  std::string &&name,
104  std::vector<SdfPredicateExpression::FnArg> &&args) {
105  exprStack.push_back(
107  kind, std::move(name), std::move(args) }));
108  }
109 
110  void PushExpr(SdfPredicateExpression &&expr) {
111  exprStack.push_back(std::move(expr));
112  }
113 
115  while (!opStack.empty()) {
116  _Reduce();
117  }
118  SdfPredicateExpression ret = std::move(exprStack.back());
119  exprStack.clear();
120  return ret;
121  }
122 
123  private:
124  void _Reduce() {
125  SdfPredicateExpression::Op op = opStack.back();
126  opStack.pop_back();
127  SdfPredicateExpression right = std::move(exprStack.back());
128  exprStack.pop_back();
129 
130  if (op == SdfPredicateExpression::Not) {
131  // Not is the only unary op.
132  exprStack.push_back(
133  SdfPredicateExpression::MakeNot(std::move(right)));
134  }
135  else {
136  // All other ops are all binary.
137  SdfPredicateExpression left = std::move(exprStack.back());
138  exprStack.pop_back();
139  exprStack.push_back(
141  op, std::move(left), std::move(right))
142  );
143  }
144  }
145 
146  // Working space.
147  std::vector<SdfPredicateExpression::Op> opStack;
148  std::vector<SdfPredicateExpression> exprStack;
149  };
150 
151  std::vector<_Stack> _stacks;
152 
153  std::string _funcName;
154  std::string _funcKwArgName;
155  std::vector<SdfPredicateExpression::FnArg> _funcArgs;
156 };
157 
158 
159 
160 ////////////////////////////////////////////////////////////////////////
161 // Grammar.
162 
163 namespace {
164 
165 using namespace tao::TAO_PEGTL_NAMESPACE;
166 
167 template <class Rule, class Sep>
168 using LookaheadList = seq<Rule, star<at<Sep, Rule>, Sep, Rule>>;
169 
170 template <class Rule> using OptSpaced = pad<Rule, blank>;
171 
172 using OptSpacedComma = OptSpaced<one<','>>;
173 
174 ////////////////////////////////////////////////////////////////////////
175 // Predicate expression grammar.
176 
177 struct NotKW : keyword<'n','o','t'> {};
178 struct AndKW : keyword<'a','n','d'> {};
179 struct OrKW : keyword<'o','r'> {};
180 struct Inf : keyword<'i','n','f'> {};
181 struct True : keyword<'t','r','u','e'> {};
182 struct False : keyword<'f','a','l','s','e'> {};
183 struct ImpliedAnd : plus<blank> {};
184 
185 struct ReservedWord : sor<
186  NotKW, AndKW, OrKW, Inf, True, False> {};
187 
188 struct Digits : plus<range<'0','9'>> {};
189 
190 struct Exp : seq<one<'e','E'>, opt<one<'-','+'>>, must<Digits>> {};
191 struct Frac : if_must<one<'.'>, Digits> {};
192 struct PredArgFloat : seq<
193  opt<one<'-'>>, sor<Inf, seq<Digits, if_then_else<Frac, opt<Exp>, Exp>>>
194  > {};
195 struct PredArgInt : seq<opt<one<'-'>>, Digits> {};
196 
197 struct PredArgBool : sor<True, False> {};
198 
199 template <class Quote>
200 struct Escaped : sor<Quote, one<'\\', 'b', 'f', 'n', 'r', 't'>> {};
201 template <class Quote>
202 struct Unescaped : minus<utf8::range<0x20, 0x10FFFF>, Quote> {};
203 
204 template <class Quote>
205 struct StringChar : if_then_else<
206  one<'\\'>, must<Escaped<Quote>>, Unescaped<Quote>> {};
207 
208 struct QuotedString : sor<
209  if_must<one<'"'>, until<one<'"'>, StringChar<one<'"'>>>>,
210  if_must<one<'\''>, until<one<'\''>, StringChar<one<'\''>>>>
211  > {};
212 
213 struct UnquotedStringChar
214  : sor<identifier_other,
215  one<'~', '!', '@', '#', '$', '%', '^', '&', '*', '-', '+', '=',
216  '|', '\\', '.', '?', '/'>> {};
217 
218 struct UnquotedString : star<UnquotedStringChar> {};
219 
220 struct PredArgString : sor<QuotedString, UnquotedString> {};
221 
222 struct PredArgVal : sor<
223  PredArgFloat, PredArgInt, PredArgBool, PredArgString> {};
224 
225 struct PredKWArgName : minus<identifier, ReservedWord> {};
226 
227 struct PredKWArgPrefix : seq<PredKWArgName, OptSpaced<one<'='>>> {};
228 struct PredKWArg : if_must<PredKWArgPrefix, PredArgVal> {};
229 
230 struct PredParenPosArg : seq<not_at<PredKWArgPrefix>, PredArgVal> {};
231 
232 struct PredFuncName : minus<identifier, ReservedWord> {};
233 
234 struct PredParenArgs
235  : if_then_else<list<PredParenPosArg, OptSpacedComma>,
236  opt<OptSpacedComma, list<PredKWArg, OptSpacedComma>>,
237  opt<list<PredKWArg, OptSpacedComma>>>
238 {};
239 
240 struct PredColonArgs : list<PredArgVal, one<','>> {};
241 struct PredColonCall : if_must<seq<PredFuncName, one<':'>>, PredColonArgs> {};
242 struct PredParenCall : seq<
243  PredFuncName, OptSpaced<one<'('>>,
244  must<PredParenArgs, star<blank>, one<')'>>
245  >
246 {};
247 
248 struct PredBareCall : PredFuncName {};
249 
250 struct PredExpr;
251 
252 struct PredOpenGroup : one<'('> {};
253 struct PredCloseGroup : one<')'> {};
254 
255 struct PredAtom
256  : sor<
257  PredColonCall,
258  PredParenCall,
259  PredBareCall,
260  if_must<PredOpenGroup, OptSpaced<PredExpr>, PredCloseGroup>
261  >
262 {};
263 
264 struct PredFactor : seq<opt<OptSpaced<list<NotKW, plus<blank>>>>, PredAtom> {};
265 struct PredOperator : sor<OptSpaced<AndKW>, OptSpaced<OrKW>, ImpliedAnd> {};
266 struct PredExpr : LookaheadList<PredFactor, PredOperator> {};
267 
268 // Actions ///////////////////////////////////////////////////////////////
269 
270 template <class Rule>
271 struct PredAction : nothing<Rule> {};
272 
273 template <SdfPredicateExpression::Op op>
274 struct PredOpAction
275 {
276  template <class Input>
277  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
278  builder.PushOp(op);
279  }
280 };
281 
282 template <> struct PredAction<NotKW>
283  : PredOpAction<SdfPredicateExpression::Not> {};
284 template <> struct PredAction<AndKW>
285  : PredOpAction<SdfPredicateExpression::And> {};
286 template <> struct PredAction<OrKW>
287  : PredOpAction<SdfPredicateExpression::Or> {};
288 template <> struct PredAction<ImpliedAnd>
289  : PredOpAction<SdfPredicateExpression::ImpliedAnd> {};
290 
291 template <>
292 struct PredAction<PredOpenGroup>
293 {
294  template <class Input>
295  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
296  builder.OpenGroup();
297  }
298 };
299 
300 template <>
301 struct PredAction<PredCloseGroup>
302 {
303  template <class Input>
304  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
305  builder.CloseGroup();
306  }
307 };
308 
309 template <>
310 struct PredAction<PredFuncName>
311 {
312  template <class Input>
313  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
314  builder.SetFuncName(in.string());
315  }
316 };
317 
318 template <>
319 struct PredAction<PredArgInt>
320 {
321  template <class Input>
322  static bool apply(Input const &in, SdfPredicateExprBuilder &builder) {
323  bool outOfRange = false;
324  int64_t ival = TfStringToInt64(in.string(), &outOfRange);
325  if (outOfRange) {
326  return false;
327  }
328  builder.AddFuncArg(VtValue(ival));
329  return true;
330  }
331 };
332 
333 template <>
334 struct PredAction<PredArgBool>
335 {
336  template <class Input>
337  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
338  builder.AddFuncArg(VtValue(in.string()[0] == 't'));
339  }
340 };
341 
342 template <>
343 struct PredAction<PredArgFloat>
344 {
345  template <class Input>
346  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
347  std::string const &instr = in.string();
348  double fval;
349  if (instr == "inf") {
350  fval = std::numeric_limits<double>::infinity();
351  }
352  else if (instr == "-inf") {
353  fval = -std::numeric_limits<double>::infinity();
354  }
355  else {
356  fval = TfStringToDouble(instr);
357  }
358  builder.AddFuncArg(VtValue(fval));
359  }
360 };
361 
362 template <>
363 struct PredAction<PredArgString>
364 {
365  template <class Input>
366  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
367  std::string const &instr = in.string();
368  size_t trimAmount = 0;
369  if (instr.size() >= 2 &&
370  ((instr.front() == '"' && instr.back() == '"') ||
371  (instr.front() == '\'' && instr.back() == '\''))) {
372  trimAmount = 1;
373  }
374  builder.AddFuncArg(
376  instr.c_str(), instr.size(), trimAmount)));
377  }
378 };
379 
380 template <>
381 struct PredAction<PredKWArgName>
382 {
383  template <class Input>
384  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
385  builder.SetFuncArgKWName(in.string());
386  }
387 };
388 
389 template <SdfPredicateExpression::FnCall::Kind callKind>
390 struct PredCallAction
391 {
392  template <class Input>
393  static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
394  builder.PushCall(callKind);
395  }
396 };
397 template <> struct PredAction<PredBareCall>
398  : PredCallAction<SdfPredicateExpression::FnCall::BareCall> {};
399 template <> struct PredAction<PredParenCall>
400  : PredCallAction<SdfPredicateExpression::FnCall::ParenCall> {};
401 template <> struct PredAction<PredColonCall>
402  : PredCallAction<SdfPredicateExpression::FnCall::ColonCall> {};
403 
404 template <class Grammar>
405 static void Analyze() {
406  static const size_t numIssues = analyze<Grammar>();
407  if (numIssues) {
408  TF_FATAL_ERROR("%zu issues found in '%s'", numIssues,
409  TF_FUNC_NAME().c_str());
410  }
411 }
412 
413 }
414 
416 
417 #endif // PXR_USD_SDF_PREDICATE_EXPRESSION_PARSER_H
GLint left
Definition: glcorearb.h:2005
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
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:613
void SetFuncArgKWName(std::string const &kw)
GLdouble n
Definition: glcorearb.h:2008
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)
#define TF_FATAL_ERROR
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:1432
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:91
**If you just want to fire and args
Definition: thread.h:609
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:164
Type Exp(const Type &x)
Return ex.
Definition: Math.h:710
void SetFuncName(std::string const &name)