@@ -87,13 +87,17 @@ public static function parseSeries(array $tokens): array
87
87
];
88
88
}
89
89
90
- private function parseSelectorList (TokenStream $ stream ): array
90
+ private function parseSelectorList (TokenStream $ stream, bool $ isArgument = false ): array
91
91
{
92
92
$ stream ->skipWhitespace ();
93
93
$ selectors = [];
94
94
95
95
while (true ) {
96
- $ selectors [] = $ this ->parserSelectorNode ($ stream );
96
+ if ($ isArgument && $ stream ->getPeek ()->isDelimiter ([') ' ])) {
97
+ break ;
98
+ }
99
+
100
+ $ selectors [] = $ this ->parserSelectorNode ($ stream , $ isArgument );
97
101
98
102
if ($ stream ->getPeek ()->isDelimiter ([', ' ])) {
99
103
$ stream ->getNext ();
@@ -106,15 +110,19 @@ private function parseSelectorList(TokenStream $stream): array
106
110
return $ selectors ;
107
111
}
108
112
109
- private function parserSelectorNode (TokenStream $ stream ): Node \SelectorNode
113
+ private function parserSelectorNode (TokenStream $ stream, bool $ isArgument = false ): Node \SelectorNode
110
114
{
111
- [$ result , $ pseudoElement ] = $ this ->parseSimpleSelector ($ stream );
115
+ [$ result , $ pseudoElement ] = $ this ->parseSimpleSelector ($ stream, false , $ isArgument );
112
116
113
117
while (true ) {
114
118
$ stream ->skipWhitespace ();
115
119
$ peek = $ stream ->getPeek ();
116
120
117
- if ($ peek ->isFileEnd () || $ peek ->isDelimiter ([', ' ])) {
121
+ if (
122
+ $ peek ->isFileEnd ()
123
+ || $ peek ->isDelimiter ([', ' ])
124
+ || ($ isArgument && $ peek ->isDelimiter ([') ' ]))
125
+ ) {
118
126
break ;
119
127
}
120
128
@@ -129,7 +137,7 @@ private function parserSelectorNode(TokenStream $stream): Node\SelectorNode
129
137
$ combinator = ' ' ;
130
138
}
131
139
132
- [$ nextSelector , $ pseudoElement ] = $ this ->parseSimpleSelector ($ stream );
140
+ [$ nextSelector , $ pseudoElement ] = $ this ->parseSimpleSelector ($ stream, false , $ isArgument );
133
141
$ result = new Node \CombinedSelectorNode ($ result , $ combinator , $ nextSelector );
134
142
}
135
143
@@ -141,7 +149,7 @@ private function parserSelectorNode(TokenStream $stream): Node\SelectorNode
141
149
*
142
150
* @throws SyntaxErrorException
143
151
*/
144
- private function parseSimpleSelector (TokenStream $ stream , bool $ insideNegation = false ): array
152
+ private function parseSimpleSelector (TokenStream $ stream , bool $ insideNegation = false , bool $ isArgument = false ): array
145
153
{
146
154
$ stream ->skipWhitespace ();
147
155
@@ -154,7 +162,7 @@ private function parseSimpleSelector(TokenStream $stream, bool $insideNegation =
154
162
if ($ peek ->isWhitespace ()
155
163
|| $ peek ->isFileEnd ()
156
164
|| $ peek ->isDelimiter ([', ' , '+ ' , '> ' , '~ ' ])
157
- || ($ insideNegation && $ peek ->isDelimiter ([') ' ]))
165
+ || ($ isArgument && $ peek ->isDelimiter ([') ' ]))
158
166
) {
159
167
break ;
160
168
}
@@ -215,7 +223,7 @@ private function parseSimpleSelector(TokenStream $stream, bool $insideNegation =
215
223
throw SyntaxErrorException::nestedNot ();
216
224
}
217
225
218
- [$ argument , $ argumentPseudoElement ] = $ this ->parseSimpleSelector ($ stream , true );
226
+ [$ argument , $ argumentPseudoElement ] = $ this ->parseSimpleSelector ($ stream , true , true );
219
227
$ next = $ stream ->getNext ();
220
228
221
229
if (null !== $ argumentPseudoElement ) {
@@ -227,6 +235,24 @@ private function parseSimpleSelector(TokenStream $stream, bool $insideNegation =
227
235
}
228
236
229
237
$ result = new Node \NegationNode ($ result , $ argument );
238
+ } elseif ('is ' === strtolower ($ identifier )) {
239
+ $ selectors = $ this ->parseSelectorList ($ stream , true );
240
+
241
+ $ next = $ stream ->getNext ();
242
+ if (!$ next ->isDelimiter ([') ' ])) {
243
+ throw SyntaxErrorException::unexpectedToken ('")" ' , $ next );
244
+ }
245
+
246
+ $ result = new Node \MatchingNode ($ result , $ selectors );
247
+ } elseif ('where ' === strtolower ($ identifier )) {
248
+ $ selectors = $ this ->parseSelectorList ($ stream , true );
249
+
250
+ $ next = $ stream ->getNext ();
251
+ if (!$ next ->isDelimiter ([') ' ])) {
252
+ throw SyntaxErrorException::unexpectedToken ('")" ' , $ next );
253
+ }
254
+
255
+ $ result = new Node \SpecificityAdjustmentNode ($ result , $ selectors );
230
256
} else {
231
257
$ arguments = [];
232
258
$ next = null ;
0 commit comments