Loading...
Searching...
No Matches
pathPatternParser.h
1//
2// Copyright 2024 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_PATH_PATTERN_PARSER_H
9#define PXR_USD_SDF_PATH_PATTERN_PARSER_H
10
11#include "pxr/pxr.h"
12
13#include "pxr/usd/sdf/predicateExpressionParser.h"
14#include "pxr/base/pegtl/pegtl.hpp"
15
16#include <memory>
17
18PXR_NAMESPACE_OPEN_SCOPE
19
20namespace SdfPathPatternParser {
21
22using namespace PXR_PEGTL_NAMESPACE;
23
24template <class Rule> using OptSpaced = pad<Rule, blank>;
25
27// Path patterns with predicates.
28struct PathPatStretch : two<'/'> {};
29struct PathPatSep : sor<PathPatStretch, one<'/'>> {};
30
31// Named close rules so the Errors class can attach targeted messages.
32struct PredExprClose : one<'}'> {};
33struct BracketClassClose : one<']'> {};
34
35// '{' commits to requiring a predicate expression and a closing '}'.
36// PredExprClose is named so the Errors class can target it specifically.
37struct BracedPredExpr
38 : if_must<one<'{'>,
39 OptSpaced<SdfPredicateExpressionParser::PredExpr>,
40 PredExprClose> {};
41
42// '[' commits to requiring valid content and a closing ']'.
43struct BracketClass :
44 if_must<one<'['>,
45 plus<sor<identifier_other, one<'!','-','?','*'>>>,
46 BracketClassClose> {};
47
48struct PrimPathWildCard :
49 plus<sor<BracketClass, identifier_other, one<'?','*'>>> {};
50
51struct PropPathWildCard :
52 plus<sor<BracketClass, identifier_other, one<':','?','*'>>> {};
53
54struct PrimPathPatternElemText : PrimPathWildCard {};
55struct PropPathPatternElemText : PropPathWildCard {};
56
57struct PrimPathPatternElem
58 : if_then_else<PrimPathPatternElemText, opt<BracedPredExpr>,
59 BracedPredExpr> {};
60
61struct PropPathPatternElem
62 : if_then_else<PropPathPatternElemText, opt<BracedPredExpr>,
63 BracedPredExpr> {};
64
65// A single '/' that is not the start of '//'. Used as a commitment point:
66// once matched, a path pattern element is unconditionally required.
67struct PatSepSlash : seq<one<'/'>, not_at<one<'/'>>> {};
68
69// PatSepSlash commits to requiring a following prim pattern element.
70struct PrimPatStep : if_must<PatSepSlash, PrimPathPatternElem> {};
71
72// '//' as separator, but only when a prim element immediately follows.
73// Trailing '//' without a following element falls through to
74// opt<PathPatStretch> at the end of PathPatternElems. Note: the lookahead
75// parses PathPatStretch+PrimPathPatternElem twice; acceptable given the bounded
76// syntax involved.
77struct StretchStep : seq<
78 at<seq<PathPatStretch, PrimPathPatternElem>>,
79 PathPatStretch,
80 PrimPathPatternElem> {};
81
82struct PathPatternElems
83 : seq<PrimPathPatternElem,
84 star<sor<StretchStep, PrimPatStep>>,
85 if_must_else<one<'.'>, PropPathPatternElem, opt<PathPatStretch>>> {};
86
87struct AbsPathPattern : seq<PathPatSep, opt<PathPatternElems>> {};
88
89struct DotDot : two<'.'> {};
90struct DotDots : list<DotDot, one<'/'>> {};
91
92struct ReflexiveRelative : one<'.'> {};
93
94struct AbsoluteStart : at<one<'/'>> {};
95
96// After DotDots, single '/' commits to requiring pattern elements. '//'
97// retains optional-elements behavior since a bare '..//' (stretch from ancestor
98// context) is a valid pattern with no following elements.
99struct DotDotsStep : if_must<PatSepSlash, PathPatternElems> {};
100struct DotDotsStretchTail : seq<PathPatStretch, opt<PathPatternElems>> {};
101
102struct PathPattern :
103 sor<
104 if_must<AbsoluteStart, AbsPathPattern>,
105 seq<DotDots, opt<sor<DotDotsStretchTail, DotDotsStep>>>,
106 PathPatternElems,
107 seq<ReflexiveRelative, opt<PathPatStretch, opt<PathPatternElems>>>
108 >
109{};
110
112// Errors.
113//
114// Inherits from SdfPredicateExpressionParser::Errors so predicate rule errors
115// propagate automatically without re-listing them here. Only
116// path-pattern-specific rules need PARSE_ERROR entries.
117//
118// The struct-override macro is used (rather than a message pointer) because the
119// derived Errors class has no message member of its own -- it uses the base's
120// raise() for inherited rules and overrides raise() directly for local ones.
121
122template <class Rule>
123struct Errors : SdfPredicateExpressionParser::Errors<Rule> {};
124
125#define PARSE_ERROR(rule, msg) \
126 template <> struct Errors<rule> \
127 : SdfPredicateExpressionParser::Errors<rule> { \
128 template <class Input, class... States> \
129 [[noreturn]] static void raise(Input const &in, States &&...) { \
130 throw parse_error(msg, in); \
131 } \
132 }
133
134PARSE_ERROR(PrimPathPatternElem, "expected path pattern element");
135PARSE_ERROR(PathPatternElems, "expected path pattern element after '/'");
136PARSE_ERROR(PropPathPatternElem, "expected property pattern element after '.'");
137PARSE_ERROR(PredExprClose, "expected '}' to close predicate expression");
138PARSE_ERROR(BracketClassClose, "expected ']' to close bracket class");
139
140#undef PARSE_ERROR
141
142} // SdfPathPatternParser
143
144
145namespace SdfPathPatternActions {
146
147using namespace PXR_PEGTL_NAMESPACE;
148
149using namespace SdfPathPatternParser;
150
151// Actions /////////////////////////////////////////////////////////////
152
153struct PatternBuilder
154{
155 // The final resulting pattern winds up here.
156 SdfPathPattern pattern;
157
158 // These are used during parsing.
159 std::string curElemText;
160 SdfPredicateExpression curPredExpr;
161};
162
163
164template <class Rule>
165struct PathPatternAction : nothing<Rule> {};
166
167template <>
168struct PathPatternAction<AbsoluteStart>
169{
170 template <class Input>
171 static void apply(Input const &in, PatternBuilder &builder) {
172 builder.pattern.SetPrefix(SdfPath::AbsoluteRootPath());
173 }
174};
175
176template <>
177struct PathPatternAction<PathPatStretch>
178{
179 template <class Input>
180 static void apply(Input const &in, PatternBuilder &builder) {
181 // '//' appends a component representing arbitrary hierarchy.
182 TF_VERIFY(builder.pattern.AppendStretchIfPossible());
183 }
184};
185
186// Change action & state to the PredicateExpressionParser so it can parse &
187// build a predicate expression for us.
188template <>
189struct PathPatternAction<SdfPredicateExpressionParser::PredExpr>
190 : change_action_and_states<SdfPredicateExpressionParser::PredAction,
191 SdfPredicateExprBuilder>
192{
193 template <class Input>
194 static void success(Input const &in,
195 SdfPredicateExprBuilder &predExprBuilder,
196 PatternBuilder &builder) {
197 builder.curPredExpr = predExprBuilder.Finish();
198 }
199};
200
201template <>
202struct PathPatternAction<PrimPathPatternElemText>
203{
204 template <class Input>
205 static void apply(Input const &in, PatternBuilder &builder) {
206 builder.curElemText = in.string();
207 }
208};
209
210template <>
211struct PathPatternAction<PropPathPatternElemText>
212{
213 template <class Input>
214 static void apply(Input const &in, PatternBuilder &builder) {
215 builder.curElemText = in.string();
216 }
217};
218
219template <>
220struct PathPatternAction<PrimPathPatternElem>
221{
222 template <class Input>
223 static void apply(Input const &in, PatternBuilder &builder) {
224 builder.pattern.AppendChild(builder.curElemText, builder.curPredExpr);
225 builder.curElemText.clear();
226 builder.curPredExpr = SdfPredicateExpression();
227 }
228};
229
230template <>
231struct PathPatternAction<PropPathPatternElem>
232{
233 template <class Input>
234 static void apply(Input const &in, PatternBuilder &builder) {
235 builder.pattern.AppendProperty(builder.curElemText,
236 builder.curPredExpr);
237 builder.curElemText.clear();
238 builder.curPredExpr = SdfPredicateExpression();
239 }
240};
241
242template <>
243struct PathPatternAction<ReflexiveRelative>
244{
245 template <class Input>
246 static void apply(Input const &in, PatternBuilder &builder) {
247 builder.pattern.SetPrefix(SdfPath::ReflexiveRelativePath());
248 }
249};
250
251template <>
252struct PathPatternAction<DotDot>
253{
254 template <class Input>
255 static void apply(Input const &in, PatternBuilder &builder) {
256 builder.pattern.AppendChild("..");
257 }
258};
259
260} // SdfPathPatternActions
261
262PXR_NAMESPACE_CLOSE_SCOPE
263
264#endif // PXR_USD_SDF_PATH_PATTERN_PARSER_H
static SDF_API const SdfPath & AbsoluteRootPath()
The absolute path representing the top of the namespace hierarchy.
static SDF_API const SdfPath & ReflexiveRelativePath()
The relative path representing "self".
Objects of this class represent SdfPath matching patterns, consisting of an SdfPath prefix followed b...
Definition pathPattern.h:31
Represents a logical expression syntax tree consisting of predicate function calls joined by the logi...
#define TF_VERIFY(cond, format,...)
Checks a condition and reports an error if it evaluates false.
Definition diagnostic.h:266