@@ -35,14 +35,21 @@ struct CSSSimpleBlock {
35
35
CSSTokenType openBracketType{};
36
36
};
37
37
38
+ /* *
39
+ * Describes a valid return type for a CSSSyntaxParser visitor
40
+ */
41
+ template <typename T>
42
+ concept CSSSyntaxVisitorReturn =
43
+ std::is_default_constructible_v<T> && std::equality_comparable<T>;
44
+
38
45
/* *
39
46
* A CSSFunctionVisitor is called to start parsing a function component value.
40
47
* At this point, the Parser is positioned at the start of the function
41
48
* component value list. It is expected that the visitor finishes before the end
42
49
* of the function block.
43
50
*/
44
51
template <typename T, typename ReturnT>
45
- concept CSSFunctionVisitor =
52
+ concept CSSFunctionVisitor = CSSSyntaxVisitorReturn<ReturnT> &&
46
53
requires (T visitor, CSSFunctionBlock func, CSSSyntaxParser& blockParser) {
47
54
{ visitor (func, blockParser) } -> std::convertible_to<ReturnT>;
48
55
};
@@ -52,7 +59,7 @@ concept CSSFunctionVisitor =
52
59
* component value.
53
60
*/
54
61
template <typename T, typename ReturnT>
55
- concept CSSPreservedTokenVisitor =
62
+ concept CSSPreservedTokenVisitor = CSSSyntaxVisitorReturn<ReturnT> &&
56
63
requires (T visitor, CSSPreservedToken token) {
57
64
{ visitor (token) } -> std::convertible_to<ReturnT>;
58
65
};
@@ -63,7 +70,7 @@ concept CSSPreservedTokenVisitor =
63
70
* of the block.
64
71
*/
65
72
template <typename T, typename ReturnT>
66
- concept CSSSimpleBlockVisitor =
73
+ concept CSSSimpleBlockVisitor = CSSSyntaxVisitorReturn<ReturnT> &&
67
74
requires (T visitor, CSSSimpleBlock block, CSSSyntaxParser& blockParser) {
68
75
{ visitor (block, blockParser) } -> std::convertible_to<ReturnT>;
69
76
};
@@ -72,16 +79,17 @@ concept CSSSimpleBlockVisitor =
72
79
* Any visitor for a component value.
73
80
*/
74
81
template <typename T, typename ReturnT>
75
- concept CSSComponentValueVisitor = CSSFunctionVisitor<T, ReturnT> ||
76
- CSSPreservedTokenVisitor<T, ReturnT> || CSSSimpleBlockVisitor<T, ReturnT>;
82
+ concept CSSComponentValueVisitor = CSSSyntaxVisitorReturn<ReturnT> &&
83
+ (CSSFunctionVisitor<T, ReturnT> || CSSPreservedTokenVisitor<T, ReturnT> ||
84
+ CSSSimpleBlockVisitor<T, ReturnT>);
77
85
78
86
/* *
79
87
* Represents a variadic set of CSSComponentValueVisitor with no more than one
80
88
* of a specific type of visitor.
81
89
*/
82
90
template <typename ReturnT, typename ... VisitorsT>
83
- concept CSSUniqueComponentValueVisitors =
84
- (CSSComponentValueVisitor<VisitorsT, ReturnT> && ... && true ) &&
91
+ concept CSSUniqueComponentValueVisitors = CSSSyntaxVisitorReturn<ReturnT> &&
92
+ (CSSComponentValueVisitor<VisitorsT, ReturnT> && ...) &&
85
93
((CSSFunctionVisitor<VisitorsT, ReturnT> ? 1 : 0 ) + ... + 0 ) <= 1 &&
86
94
((CSSPreservedTokenVisitor<VisitorsT, ReturnT> ? 1 : 0 ) + ... + 0 ) <= 1 &&
87
95
((CSSSimpleBlockVisitor<VisitorsT, ReturnT> ? 1 : 0 ) + ... + 0 ) <= 1 ;
@@ -106,7 +114,9 @@ enum class CSSDelimiter {
106
114
* https://www.w3.org/TR/css-syntax-3/#component-value
107
115
*/
108
116
class CSSSyntaxParser {
109
- template <typename ReturnT, CSSComponentValueVisitor<ReturnT>... VisitorsT>
117
+ template <
118
+ CSSSyntaxVisitorReturn ReturnT,
119
+ CSSComponentValueVisitor<ReturnT>... VisitorsT>
110
120
friend struct CSSComponentValueVisitorDispatcher ;
111
121
112
122
public:
@@ -130,6 +140,11 @@ class CSSSyntaxParser {
130
140
* higher-level data structure, and continue parsing within its scope using
131
141
* the same underlying CSSSyntaxParser.
132
142
*
143
+ * The state of the parser is reset if a visitor returns a default-constructed
144
+ * value for the given return type, even if it previously advanced the parser.
145
+ * If no visitor returns a non-default-constructed value, the component value
146
+ * will not be consumed.
147
+ *
133
148
* https://www.w3.org/TR/css-syntax-3/#consume-component-value
134
149
*
135
150
* @param <ReturnT> caller-specified return type of visitors. This type will
@@ -142,47 +157,16 @@ class CSSSyntaxParser {
142
157
* @returns the visitor returned value, or a default constructed value if no
143
158
* visitor was matched, or a syntax error occurred.
144
159
*/
145
- template <typename ReturnT = std:: nullptr_t >
160
+ template <CSSSyntaxVisitorReturn ReturnT>
146
161
constexpr ReturnT consumeComponentValue (
147
162
CSSDelimiter delimiter,
148
163
const CSSComponentValueVisitor<ReturnT> auto &... visitors)
149
164
requires(CSSUniqueComponentValueVisitors<ReturnT, decltype(visitors)...>);
150
165
151
- template <typename ReturnT = std:: nullptr_t >
166
+ template <CSSSyntaxVisitorReturn ReturnT>
152
167
constexpr ReturnT consumeComponentValue (
153
168
const CSSComponentValueVisitor<ReturnT> auto &... visitors)
154
169
requires(CSSUniqueComponentValueVisitors<ReturnT, decltype(visitors)...>);
155
-
156
- /* *
157
- * Peek at the next component value without consuming it. The component value
158
- * is provided to a passed in "visitor", typically a lambda which accepts the
159
- * component value in a new scope. The visitor may read this component
160
- * parameter into a higher-level data structure, and continue parsing within
161
- * its scope using the same underlying CSSSyntaxParser.
162
- *
163
- * https://www.w3.org/TR/css-syntax-3/#consume-component-value
164
- *
165
- * @param <ReturnT> caller-specified return type of visitors. This type will
166
- * be set to its default constructed state if consuming a component value with
167
- * no matching visitors, or syntax error
168
- * @param visitors A unique list of CSSComponentValueVisitor to be called on a
169
- * match
170
- * @param delimiter The expected delimeter to occur before the next component
171
- * value
172
- * @returns the visitor returned value, or a default constructed value if no
173
- * visitor was matched, or a syntax error occurred.
174
- */
175
- template <typename ReturnT = std::nullptr_t >
176
- constexpr ReturnT peekComponentValue (
177
- CSSDelimiter delimiter,
178
- const CSSComponentValueVisitor<ReturnT> auto &... visitors)
179
- requires(CSSUniqueComponentValueVisitors<ReturnT, decltype(visitors)...>);
180
-
181
- template <typename ReturnT = std::nullptr_t >
182
- constexpr ReturnT peekComponentValue (
183
- const CSSComponentValueVisitor<ReturnT> auto &... visitors)
184
- requires(CSSUniqueComponentValueVisitors<ReturnT, decltype(visitors)...>);
185
-
186
170
/* *
187
171
* The parser is considered finished when there are no more remaining tokens
188
172
* to be processed
@@ -226,7 +210,9 @@ class CSSSyntaxParser {
226
210
CSSTokenType terminator_{CSSTokenType::EndOfFile};
227
211
};
228
212
229
- template <typename ReturnT, CSSComponentValueVisitor<ReturnT>... VisitorsT>
213
+ template <
214
+ CSSSyntaxVisitorReturn ReturnT,
215
+ CSSComponentValueVisitor<ReturnT>... VisitorsT>
230
216
struct CSSComponentValueVisitorDispatcher {
231
217
CSSSyntaxParser& parser;
232
218
@@ -275,6 +261,7 @@ struct CSSComponentValueVisitorDispatcher {
275
261
break ;
276
262
}
277
263
264
+ parser = originalParser;
278
265
return ReturnT{};
279
266
}
280
267
@@ -331,15 +318,6 @@ struct CSSComponentValueVisitorDispatcher {
331
318
return false ;
332
319
}
333
320
334
- constexpr ReturnT peekComponentValue (
335
- CSSDelimiter delimiter,
336
- const VisitorsT&... visitors) {
337
- auto originalParser = parser;
338
- auto ret = consumeComponentValue (delimiter, visitors...);
339
- parser = originalParser;
340
- return ret;
341
- }
342
-
343
321
constexpr std::optional<ReturnT> visitFunction (
344
322
const CSSComponentValueVisitor<ReturnT> auto & visitor,
345
323
const CSSComponentValueVisitor<ReturnT> auto &... rest) {
@@ -357,7 +335,8 @@ struct CSSComponentValueVisitorDispatcher {
357
335
auto functionValue = visitor ({name}, blockParser);
358
336
parser.advanceToBlockParser (blockParser);
359
337
parser.consumeWhitespace ();
360
- if (parser.peek ().type () == CSSTokenType::CloseParen) {
338
+ if (parser.peek ().type () == CSSTokenType::CloseParen &&
339
+ functionValue != ReturnT{}) {
361
340
parser.consumeToken ();
362
341
return functionValue;
363
342
}
@@ -369,11 +348,6 @@ struct CSSComponentValueVisitorDispatcher {
369
348
}
370
349
371
350
constexpr std::optional<ReturnT> visitFunction () {
372
- while (parser.peek ().type () != CSSTokenType::CloseParen) {
373
- parser.consumeToken ();
374
- }
375
- parser.consumeToken ();
376
-
377
351
return {};
378
352
}
379
353
@@ -388,7 +362,7 @@ struct CSSComponentValueVisitorDispatcher {
388
362
auto blockValue = visitor ({openBracketType}, blockParser);
389
363
parser.advanceToBlockParser (blockParser);
390
364
parser.consumeWhitespace ();
391
- if (parser.peek ().type () == endToken) {
365
+ if (parser.peek ().type () == endToken && blockValue != ReturnT{} ) {
392
366
parser.consumeToken ();
393
367
return blockValue;
394
368
}
@@ -399,29 +373,27 @@ struct CSSComponentValueVisitorDispatcher {
399
373
}
400
374
401
375
constexpr std::optional<ReturnT> visitSimpleBlock (CSSTokenType endToken) {
402
- while (parser.peek ().type () != endToken) {
403
- parser.consumeToken ();
404
- }
405
- parser.consumeToken ();
406
376
return {};
407
377
}
408
378
409
379
constexpr std::optional<ReturnT> visitPreservedToken (
410
380
const CSSComponentValueVisitor<ReturnT> auto & visitor,
411
381
const CSSComponentValueVisitor<ReturnT> auto &... rest) {
412
382
if constexpr (CSSPreservedTokenVisitor<decltype (visitor), ReturnT>) {
413
- return visitor (parser.consumeToken ());
383
+ auto ret = visitor (parser.consumeToken ());
384
+ if (ret != ReturnT{}) {
385
+ return ret;
386
+ }
414
387
}
415
388
return visitPreservedToken (rest...);
416
389
}
417
390
418
391
constexpr std::optional<ReturnT> visitPreservedToken () {
419
- parser.consumeToken ();
420
392
return {};
421
393
}
422
394
};
423
395
424
- template <typename ReturnT>
396
+ template <CSSSyntaxVisitorReturn ReturnT>
425
397
constexpr ReturnT CSSSyntaxParser::consumeComponentValue (
426
398
CSSDelimiter delimiter,
427
399
const CSSComponentValueVisitor<ReturnT> auto &... visitors)
@@ -432,31 +404,12 @@ constexpr ReturnT CSSSyntaxParser::consumeComponentValue(
432
404
.consumeComponentValue (delimiter, visitors...);
433
405
}
434
406
435
- template <typename ReturnT>
407
+ template <CSSSyntaxVisitorReturn ReturnT>
436
408
constexpr ReturnT CSSSyntaxParser::consumeComponentValue (
437
409
const CSSComponentValueVisitor<ReturnT> auto &... visitors)
438
410
requires(CSSUniqueComponentValueVisitors<ReturnT, decltype(visitors)...>)
439
411
{
440
412
return consumeComponentValue<ReturnT>(CSSDelimiter::None, visitors...);
441
413
}
442
414
443
- template <typename ReturnT>
444
- constexpr ReturnT CSSSyntaxParser::peekComponentValue (
445
- CSSDelimiter delimiter,
446
- const CSSComponentValueVisitor<ReturnT> auto &... visitors)
447
- requires(CSSUniqueComponentValueVisitors<ReturnT, decltype(visitors)...>)
448
- {
449
- return CSSComponentValueVisitorDispatcher<ReturnT, decltype (visitors)...>{
450
- *this }
451
- .peekComponentValue (delimiter, visitors...);
452
- }
453
-
454
- template <typename ReturnT>
455
- constexpr ReturnT CSSSyntaxParser::peekComponentValue (
456
- const CSSComponentValueVisitor<ReturnT> auto &... visitors)
457
- requires(CSSUniqueComponentValueVisitors<ReturnT, decltype(visitors)...>)
458
- {
459
- return peekComponentValue<ReturnT>(CSSDelimiter::None, visitors...);
460
- }
461
-
462
415
} // namespace facebook::react
0 commit comments