@@ -89,13 +89,17 @@ public static function parseSeries(array $tokens): array
89
89
];
90
90
}
91
91
92
- private function parseSelectorList (TokenStream $ stream ): array
92
+ private function parseSelectorList (TokenStream $ stream, bool $ isArgument = false ): array
93
93
{
94
94
$ stream ->skipWhitespace ();
95
95
$ selectors = [];
96
96
97
97
while (true ) {
98
- $ selectors [] = $ this ->parserSelectorNode ($ stream );
98
+ if ($ isArgument && $ stream ->getPeek ()->isDelimiter ([') ' ])) {
99
+ break ;
100
+ }
101
+
102
+ $ selectors [] = $ this ->parserSelectorNode ($ stream , $ isArgument );
99
103
100
104
if ($ stream ->getPeek ()->isDelimiter ([', ' ])) {
101
105
$ stream ->getNext ();
@@ -108,15 +112,19 @@ private function parseSelectorList(TokenStream $stream): array
108
112
return $ selectors ;
109
113
}
110
114
111
- private function parserSelectorNode (TokenStream $ stream ): Node \SelectorNode
115
+ private function parserSelectorNode (TokenStream $ stream, bool $ isArgument = false ): Node \SelectorNode
112
116
{
113
- [$ result , $ pseudoElement ] = $ this ->parseSimpleSelector ($ stream );
117
+ [$ result , $ pseudoElement ] = $ this ->parseSimpleSelector ($ stream, false , $ isArgument );
114
118
115
119
while (true ) {
116
120
$ stream ->skipWhitespace ();
117
121
$ peek = $ stream ->getPeek ();
118
122
119
- if ($ peek ->isFileEnd () || $ peek ->isDelimiter ([', ' ])) {
123
+ if (
124
+ $ peek ->isFileEnd ()
125
+ || $ peek ->isDelimiter ([', ' ])
126
+ || ($ isArgument && $ peek ->isDelimiter ([') ' ]))
127
+ ) {
120
128
break ;
121
129
}
122
130
@@ -131,7 +139,7 @@ private function parserSelectorNode(TokenStream $stream): Node\SelectorNode
131
139
$ combinator = ' ' ;
132
140
}
133
141
134
- [$ nextSelector , $ pseudoElement ] = $ this ->parseSimpleSelector ($ stream );
142
+ [$ nextSelector , $ pseudoElement ] = $ this ->parseSimpleSelector ($ stream, false , $ isArgument );
135
143
$ result = new Node \CombinedSelectorNode ($ result , $ combinator , $ nextSelector );
136
144
}
137
145
@@ -143,7 +151,7 @@ private function parserSelectorNode(TokenStream $stream): Node\SelectorNode
143
151
*
144
152
* @throws SyntaxErrorException
145
153
*/
146
- private function parseSimpleSelector (TokenStream $ stream , bool $ insideNegation = false ): array
154
+ private function parseSimpleSelector (TokenStream $ stream , bool $ insideNegation = false , bool $ isArgument = false ): array
147
155
{
148
156
$ stream ->skipWhitespace ();
149
157
@@ -156,7 +164,7 @@ private function parseSimpleSelector(TokenStream $stream, bool $insideNegation =
156
164
if ($ peek ->isWhitespace ()
157
165
|| $ peek ->isFileEnd ()
158
166
|| $ peek ->isDelimiter ([', ' , '+ ' , '> ' , '~ ' ])
159
- || ($ insideNegation && $ peek ->isDelimiter ([') ' ]))
167
+ || ($ isArgument && $ peek ->isDelimiter ([') ' ]))
160
168
) {
161
169
break ;
162
170
}
@@ -206,7 +214,7 @@ private function parseSimpleSelector(TokenStream $stream, bool $insideNegation =
206
214
throw SyntaxErrorException::nestedNot ();
207
215
}
208
216
209
- [$ argument , $ argumentPseudoElement ] = $ this ->parseSimpleSelector ($ stream , true );
217
+ [$ argument , $ argumentPseudoElement ] = $ this ->parseSimpleSelector ($ stream , true , true );
210
218
$ next = $ stream ->getNext ();
211
219
212
220
if (null !== $ argumentPseudoElement ) {
@@ -219,11 +227,21 @@ private function parseSimpleSelector(TokenStream $stream, bool $insideNegation =
219
227
220
228
$ result = new Node \NegationNode ($ result , $ argument );
221
229
} elseif ('is ' === strtolower ($ identifier )) {
222
- $ selectors = $ this ->parseSimpleSelectorArguments ($ stream );
230
+ $ selectors = $ this ->parseSelectorList ($ stream , true );
231
+
232
+ $ next = $ stream ->getNext ();
233
+ if (!$ next ->isDelimiter ([') ' ])) {
234
+ throw SyntaxErrorException::unexpectedToken ('")" ' , $ next );
235
+ }
223
236
224
237
$ result = new Node \MatchingNode ($ result , $ selectors );
225
238
} elseif ('where ' === strtolower ($ identifier )) {
226
- $ selectors = $ this ->parseSimpleSelectorArguments ($ stream );
239
+ $ selectors = $ this ->parseSelectorList ($ stream , true );
240
+
241
+ $ next = $ stream ->getNext ();
242
+ if (!$ next ->isDelimiter ([') ' ])) {
243
+ throw SyntaxErrorException::unexpectedToken ('")" ' , $ next );
244
+ }
227
245
228
246
$ result = new Node \SpecificityAdjustmentNode ($ result , $ selectors );
229
247
} else {
@@ -265,32 +283,6 @@ private function parseSimpleSelector(TokenStream $stream, bool $insideNegation =
265
283
return [$ result , $ pseudoElement ];
266
284
}
267
285
268
- private function parseSimpleSelectorArguments (TokenStream $ stream ): array
269
- {
270
- $ arguments = [];
271
- while (true ) {
272
- [$ result , $ pseudoElement ] = $ this ->parseSimpleSelector ($ stream , true );
273
- if ($ pseudoElement ) {
274
- throw SyntaxErrorException::pseudoElementFound ($ pseudoElement , 'function ' );
275
- }
276
- $ stream ->skipWhitespace ();
277
- $ next = $ stream ->getNext ();
278
-
279
- if ($ next ->isFileEnd () || $ next ->isDelimiter ([', ' ])) {
280
- $ stream ->getNext ();
281
- $ stream ->skipWhitespace ();
282
- $ arguments [] = $ result ;
283
- } elseif ($ next ->isDelimiter ([') ' ])) {
284
- $ arguments [] = $ result ;
285
- break ;
286
- } else {
287
- throw SyntaxErrorException::unexpectedToken ('argument ' , $ next );
288
- }
289
- }
290
-
291
- return $ arguments ;
292
- }
293
-
294
286
private function parseElementNode (TokenStream $ stream ): Node \ElementNode
295
287
{
296
288
$ peek = $ stream ->getPeek ();
0 commit comments