Loading...
Searching...
No Matches
predicateExpressionParser.h
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
32#include "pxr/base/vt/value.h"
33
34#include "pxr/base/pegtl/pegtl.hpp"
35
36#include <memory>
37
38PXR_NAMESPACE_OPEN_SCOPE
39
40// fwd decl, from parserHelpers.cpp.
41std::string
42Sdf_EvalQuotedString(const char* x, size_t n,
43 size_t trimBothSides, unsigned int* numLines=NULL);
44
45struct SdfPredicateExprBuilder
46{
47 SdfPredicateExprBuilder() { OpenGroup(); }
48
49 void PushOp(SdfPredicateExpression::Op op) { _stacks.back().PushOp(op); }
50
51 void PushCall(SdfPredicateExpression::FnCall::Kind kind) {
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
79 SdfPredicateExpression Finish() {
80 SdfPredicateExpression result = _stacks.back().Finish();
81 _stacks.clear();
82 _funcArgs.clear();
83 _funcName.clear();
84 return result;
85 }
86
87private:
88 struct _Stack {
89
90 void PushOp(SdfPredicateExpression::Op op) {
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
102 void PushCall(SdfPredicateExpression::FnCall::Kind kind,
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
114 SdfPredicateExpression Finish() {
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
161// Grammar.
162
163namespace {
164
165using namespace PXR_PEGTL_NAMESPACE;
166
167template <class Rule, class Sep>
168using LookaheadList = seq<Rule, star<at<Sep, Rule>, Sep, Rule>>;
169
170template <class Rule> using OptSpaced = pad<Rule, blank>;
171
172using OptSpacedComma = OptSpaced<one<','>>;
173
175// Predicate expression grammar.
176
177struct NotKW : keyword<'n','o','t'> {};
178struct AndKW : keyword<'a','n','d'> {};
179struct OrKW : keyword<'o','r'> {};
180struct Inf : keyword<'i','n','f'> {};
181struct True : keyword<'t','r','u','e'> {};
182struct False : keyword<'f','a','l','s','e'> {};
183struct ImpliedAnd : plus<blank> {};
184
185struct ReservedWord : sor<
186 NotKW, AndKW, OrKW, Inf, True, False> {};
187
188struct Digits : plus<range<'0','9'>> {};
189
190struct Exp : seq<one<'e','E'>, opt<one<'-','+'>>, must<Digits>> {};
191struct Frac : if_must<one<'.'>, Digits> {};
192struct PredArgFloat : seq<
193 opt<one<'-'>>, sor<Inf, seq<Digits, if_then_else<Frac, opt<Exp>, Exp>>>
194 > {};
195struct PredArgInt : seq<opt<one<'-'>>, Digits> {};
196
197struct PredArgBool : sor<True, False> {};
198
199template <class Quote>
200struct Escaped : sor<Quote, one<'\\', 'b', 'f', 'n', 'r', 't'>> {};
201template <class Quote>
202struct Unescaped : minus<utf8::range<0x20, 0x10FFFF>, Quote> {};
203
204template <class Quote>
205struct StringChar : if_then_else<
206 one<'\\'>, must<Escaped<Quote>>, Unescaped<Quote>> {};
207
208struct QuotedString : sor<
209 if_must<one<'"'>, until<one<'"'>, StringChar<one<'"'>>>>,
210 if_must<one<'\''>, until<one<'\''>, StringChar<one<'\''>>>>
211 > {};
212
213struct UnquotedStringChar
214 : sor<identifier_other,
215 one<'~', '!', '@', '#', '$', '%', '^', '&', '*', '-', '+', '=',
216 '|', '\\', '.', '?', '/'>> {};
217
218struct UnquotedString : star<UnquotedStringChar> {};
219
220struct PredArgString : sor<QuotedString, UnquotedString> {};
221
222struct PredArgVal : sor<
223 PredArgFloat, PredArgInt, PredArgBool, PredArgString> {};
224
225struct PredKWArgName : minus<identifier, ReservedWord> {};
226
227struct PredKWArgPrefix : seq<PredKWArgName, OptSpaced<one<'='>>> {};
228struct PredKWArg : if_must<PredKWArgPrefix, PredArgVal> {};
229
230struct PredParenPosArg : seq<not_at<PredKWArgPrefix>, PredArgVal> {};
231
232struct PredFuncName : minus<identifier, ReservedWord> {};
233
234struct PredParenArgs
235 : if_then_else<list<PredParenPosArg, OptSpacedComma>,
236 opt<OptSpacedComma, list<PredKWArg, OptSpacedComma>>,
237 opt<list<PredKWArg, OptSpacedComma>>>
238{};
239
240struct PredColonArgs : list<PredArgVal, one<','>> {};
241struct PredColonCall : if_must<seq<PredFuncName, one<':'>>, PredColonArgs> {};
242struct PredParenCall : seq<
243 PredFuncName, OptSpaced<one<'('>>,
244 must<PredParenArgs, star<blank>, one<')'>>
245 >
246{};
247
248struct PredBareCall : PredFuncName {};
249
250struct PredExpr;
251
252struct PredOpenGroup : one<'('> {};
253struct PredCloseGroup : one<')'> {};
254
255struct PredAtom
256 : sor<
257 PredColonCall,
258 PredParenCall,
259 PredBareCall,
260 if_must<PredOpenGroup, OptSpaced<PredExpr>, PredCloseGroup>
261 >
262{};
263
264struct PredFactor : seq<opt<OptSpaced<list<NotKW, plus<blank>>>>, PredAtom> {};
265struct PredOperator : sor<OptSpaced<AndKW>, OptSpaced<OrKW>, ImpliedAnd> {};
266struct PredExpr : LookaheadList<PredFactor, PredOperator> {};
267
268// Actions ///////////////////////////////////////////////////////////////
269
270template <class Rule>
271struct PredAction : nothing<Rule> {};
272
273template <SdfPredicateExpression::Op op>
274struct PredOpAction
275{
276 template <class Input>
277 static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
278 builder.PushOp(op);
279 }
280};
281
282template <> struct PredAction<NotKW>
283 : PredOpAction<SdfPredicateExpression::Not> {};
284template <> struct PredAction<AndKW>
285 : PredOpAction<SdfPredicateExpression::And> {};
286template <> struct PredAction<OrKW>
287 : PredOpAction<SdfPredicateExpression::Or> {};
288template <> struct PredAction<ImpliedAnd>
289 : PredOpAction<SdfPredicateExpression::ImpliedAnd> {};
290
291template <>
292struct PredAction<PredOpenGroup>
293{
294 template <class Input>
295 static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
296 builder.OpenGroup();
297 }
298};
299
300template <>
301struct PredAction<PredCloseGroup>
302{
303 template <class Input>
304 static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
305 builder.CloseGroup();
306 }
307};
308
309template <>
310struct PredAction<PredFuncName>
311{
312 template <class Input>
313 static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
314 builder.SetFuncName(in.string());
315 }
316};
317
318template <>
319struct 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
333template <>
334struct 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
342template <>
343struct 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
362template <>
363struct 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(
375 VtValue(Sdf_EvalQuotedString(
376 instr.c_str(), instr.size(), trimAmount)));
377 }
378};
379
380template <>
381struct PredAction<PredKWArgName>
382{
383 template <class Input>
384 static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
385 builder.SetFuncArgKWName(in.string());
386 }
387};
388
389template <SdfPredicateExpression::FnCall::Kind callKind>
390struct PredCallAction
391{
392 template <class Input>
393 static void apply(Input const &in, SdfPredicateExprBuilder &builder) {
394 builder.PushCall(callKind);
395 }
396};
397template <> struct PredAction<PredBareCall>
398 : PredCallAction<SdfPredicateExpression::FnCall::BareCall> {};
399template <> struct PredAction<PredParenCall>
400 : PredCallAction<SdfPredicateExpression::FnCall::ParenCall> {};
401template <> struct PredAction<PredColonCall>
402 : PredCallAction<SdfPredicateExpression::FnCall::ColonCall> {};
403
404}
405
406PXR_NAMESPACE_CLOSE_SCOPE
407
408#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:164
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.