Loading...
Searching...
No Matches
predicateExpressionParser.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
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
15#include "pxr/base/vt/value.h"
16
17#include "pxr/base/pegtl/pegtl.hpp"
18
19#include <memory>
20
21PXR_NAMESPACE_OPEN_SCOPE
22
23// fwd decl, from parserHelpers.cpp.
24std::string
25Sdf_EvalQuotedString(const char* x, size_t n,
26 size_t trimBothSides, unsigned int* numLines=NULL);
27
28struct SdfPredicateExprBuilder
29{
30 SdfPredicateExprBuilder() { OpenGroup(); }
31
32 void PushOp(SdfPredicateExpression::Op op) { _stacks.back().PushOp(op); }
33
34 void PushCall(SdfPredicateExpression::FnCall::Kind kind) {
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
62 SdfPredicateExpression Finish() {
63 SdfPredicateExpression result = _stacks.back().Finish();
64 _stacks.clear();
65 _funcArgs.clear();
66 _funcName.clear();
67 return result;
68 }
69
70private:
71 struct _Stack {
72
73 void PushOp(SdfPredicateExpression::Op op) {
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
85 void PushCall(SdfPredicateExpression::FnCall::Kind kind,
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
97 SdfPredicateExpression Finish() {
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
144// Grammar.
145
146namespace SdfPredicateExpressionParser {
147
148using namespace PXR_PEGTL_NAMESPACE;
149
150template <class Rule, class Sep>
151using LookaheadList = seq<Rule, star<at<Sep, Rule>, Sep, Rule>>;
152
153template <class Rule> using OptSpaced = pad<Rule, blank>;
154
155using OptSpacedComma = OptSpaced<one<','>>;
156
158// Predicate expression grammar.
159
160struct NotKW : keyword<'n','o','t'> {};
161struct AndKW : keyword<'a','n','d'> {};
162struct OrKW : keyword<'o','r'> {};
163struct Inf : keyword<'i','n','f'> {};
164struct True : keyword<'t','r','u','e'> {};
165struct False : keyword<'f','a','l','s','e'> {};
166struct ImpliedAnd : plus<blank> {};
167
168struct ReservedWord : sor<
169 NotKW, AndKW, OrKW, Inf, True, False> {};
170
171struct Digits : plus<range<'0','9'>> {};
172
173struct Exp : seq<one<'e','E'>, opt<one<'-','+'>>, must<Digits>> {};
174struct Frac : if_must<one<'.'>, Digits> {};
175struct PredArgFloat : seq<
176 opt<one<'-'>>, sor<Inf, seq<Digits, if_then_else<Frac, opt<Exp>, Exp>>>
177 > {};
178struct PredArgInt : seq<opt<one<'-'>>, Digits> {};
179
180struct PredArgBool : sor<True, False> {};
181
182template <class Quote>
183struct Escaped : sor<Quote, one<'\\', 'b', 'f', 'n', 'r', 't'>> {};
184template <class Quote>
185struct Unescaped : minus<utf8::range<0x20, 0x10FFFF>, Quote> {};
186
187template <class Quote>
188struct StringChar : if_then_else<
189 one<'\\'>, must<Escaped<Quote>>, Unescaped<Quote>> {};
190
191struct QuotedString : sor<
192 if_must<one<'"'>, until<one<'"'>, StringChar<one<'"'>>>>,
193 if_must<one<'\''>, until<one<'\''>, StringChar<one<'\''>>>>
194 > {};
195
196struct UnquotedStringChar
197 : sor<identifier_other,
198 one<'~', '!', '@', '#', '$', '%', '^', '&', '*', '-', '+', '=',
199 '|', '\\', '.', '?', '/'>> {};
200
201struct UnquotedString : star<UnquotedStringChar> {};
202
203struct PredArgString : sor<QuotedString, UnquotedString> {};
204
205struct PredArgVal : sor<
206 PredArgFloat, PredArgInt, PredArgBool, PredArgString> {};
207
208struct PredKWArgName : minus<identifier, ReservedWord> {};
209
210struct PredKWArgPrefix : seq<PredKWArgName, OptSpaced<one<'='>>> {};
211struct PredKWArg : if_must<PredKWArgPrefix, PredArgVal> {};
212
213struct PredParenPosArg : seq<not_at<PredKWArgPrefix>, PredArgVal> {};
214
215struct PredFuncName : minus<identifier, ReservedWord> {};
216
217struct PredParenArgs
218 : if_then_else<list<PredParenPosArg, OptSpacedComma>,
219 opt<OptSpacedComma, list<PredKWArg, OptSpacedComma>>,
220 opt<list<PredKWArg, OptSpacedComma>>>
221{};
222
223struct PredColonArgs : list<PredArgVal, one<','>> {};
224struct PredColonCall : if_must<seq<PredFuncName, one<':'>>, PredColonArgs> {};
225struct PredParenCall : seq<
226 PredFuncName, OptSpaced<one<'('>>,
227 must<PredParenArgs, star<blank>, one<')'>>
228 >
229{};
230
231struct PredBareCall : PredFuncName {};
232
233struct PredExpr;
234
235struct PredOpenGroup : one<'('> {};
236struct PredCloseGroup : one<')'> {};
237
238struct PredAtom
239 : sor<
240 PredColonCall,
241 PredParenCall,
242 PredBareCall,
243 if_must<PredOpenGroup, OptSpaced<PredExpr>, PredCloseGroup>
244 >
245{};
246
247struct PredFactor : seq<opt<OptSpaced<list<NotKW, plus<blank>>>>, PredAtom> {};
248struct PredOperator : sor<OptSpaced<AndKW>, OptSpaced<OrKW>, ImpliedAnd> {};
249struct PredExpr : LookaheadList<PredFactor, PredOperator> {};
250
251// Actions ///////////////////////////////////////////////////////////////
252
253template <class Rule>
254struct PredAction : nothing<Rule> {};
255
256template <SdfPredicateExpression::Op op>
257struct PredOpAction
258{
259 template <class Input>
260 static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
261 builder.PushOp(op);
262 }
263};
264
265template <> struct PredAction<NotKW>
266 : PredOpAction<SdfPredicateExpression::Not> {};
267template <> struct PredAction<AndKW>
268 : PredOpAction<SdfPredicateExpression::And> {};
269template <> struct PredAction<OrKW>
270 : PredOpAction<SdfPredicateExpression::Or> {};
271template <> struct PredAction<ImpliedAnd>
272 : PredOpAction<SdfPredicateExpression::ImpliedAnd> {};
273
274template <>
275struct PredAction<PredOpenGroup>
276{
277 template <class Input>
278 static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
279 builder.OpenGroup();
280 }
281};
282
283template <>
284struct PredAction<PredCloseGroup>
285{
286 template <class Input>
287 static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
288 builder.CloseGroup();
289 }
290};
291
292template <>
293struct PredAction<PredFuncName>
294{
295 template <class Input>
296 static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
297 builder.SetFuncName(in.string());
298 }
299};
300
301template <>
302struct PredAction<PredArgInt>
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
316template <>
317struct PredAction<PredArgBool>
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
325template <>
326struct PredAction<PredArgFloat>
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
345template <>
346struct PredAction<PredArgString>
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(
358 VtValue(Sdf_EvalQuotedString(
359 instr.c_str(), instr.size(), trimAmount)));
360 }
361};
362
363template <>
364struct PredAction<PredKWArgName>
365{
366 template <class Input>
367 static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
368 builder.SetFuncArgKWName(in.string());
369 }
370};
371
372template <SdfPredicateExpression::FnCall::Kind callKind>
373struct PredCallAction
374{
375 template <class Input>
376 static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
377 builder.PushCall(callKind);
378 }
379};
380template <> struct PredAction<PredBareCall>
381 : PredCallAction<SdfPredicateExpression::FnCall::BareCall> {};
382template <> struct PredAction<PredParenCall>
383 : PredCallAction<SdfPredicateExpression::FnCall::ParenCall> {};
384template <> struct PredAction<PredColonCall>
385 : PredCallAction<SdfPredicateExpression::FnCall::ColonCall> {};
386
387}
388
389PXR_NAMESPACE_CLOSE_SCOPE
390
391#endif // PXR_USD_SDF_PREDICATE_EXPRESSION_PARSER_H
Low-level utilities for informing users of various internal and external diagnostic conditions.
Represents a logical expression syntax tree consisting of predicate function calls joined by the logi...
Op
Enumerant describing a subexpression operation.
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.
static SDF_API SdfPredicateExpression MakeCall(FnCall &&call)
Produce a new expression containing just a the function call call.
Provides a container which may hold any type, and provides introspection and iteration over array typ...
Definition: value.h:152
TF_API int64_t TfStringToInt64(const std::string &txt, bool *outOfRange=NULL)
Convert a sequence of digits in txt to an int64_t value.
TF_API double TfStringToDouble(const std::string &txt)
Converts text string to double.