@@ -87,13 +87,17 @@ public static function parseSeries(array $tokens): array
8787 ];
8888 }
8989
90- private function parseSelectorList (TokenStream $ stream ): array
90+ private function parseSelectorList (TokenStream $ stream, bool $ isArgument = false ): array
9191 {
9292 $ stream ->skipWhitespace ();
9393 $ selectors = [];
9494
9595 while (true ) {
96- $ selectors [] = $ this ->parserSelectorNode ($ stream );
96+ if ($ isArgument && $ stream ->getPeek ()->isDelimiter ([') ' ])) {
97+ break ;
98+ }
99+
100+ $ selectors [] = $ this ->parserSelectorNode ($ stream , $ isArgument );
97101
98102 if ($ stream ->getPeek ()->isDelimiter ([', ' ])) {
99103 $ stream ->getNext ();
@@ -106,15 +110,19 @@ private function parseSelectorList(TokenStream $stream): array
106110 return $ selectors ;
107111 }
108112
109- private function parserSelectorNode (TokenStream $ stream ): Node \SelectorNode
113+ private function parserSelectorNode (TokenStream $ stream, bool $ isArgument = false ): Node \SelectorNode
110114 {
111- [$ result , $ pseudoElement ] = $ this ->parseSimpleSelector ($ stream );
115+ [$ result , $ pseudoElement ] = $ this ->parseSimpleSelector ($ stream, false , $ isArgument );
112116
113117 while (true ) {
114118 $ stream ->skipWhitespace ();
115119 $ peek = $ stream ->getPeek ();
116120
117- if ($ peek ->isFileEnd () || $ peek ->isDelimiter ([', ' ])) {
121+ if (
122+ $ peek ->isFileEnd ()
123+ || $ peek ->isDelimiter ([', ' ])
124+ || ($ isArgument && $ peek ->isDelimiter ([') ' ]))
125+ ) {
118126 break ;
119127 }
120128
@@ -129,7 +137,7 @@ private function parserSelectorNode(TokenStream $stream): Node\SelectorNode
129137 $ combinator = ' ' ;
130138 }
131139
132- [$ nextSelector , $ pseudoElement ] = $ this ->parseSimpleSelector ($ stream );
140+ [$ nextSelector , $ pseudoElement ] = $ this ->parseSimpleSelector ($ stream, false , $ isArgument );
133141 $ result = new Node \CombinedSelectorNode ($ result , $ combinator , $ nextSelector );
134142 }
135143
@@ -141,7 +149,7 @@ private function parserSelectorNode(TokenStream $stream): Node\SelectorNode
141149 *
142150 * @throws SyntaxErrorException
143151 */
144- private function parseSimpleSelector (TokenStream $ stream , bool $ insideNegation = false ): array
152+ private function parseSimpleSelector (TokenStream $ stream , bool $ insideNegation = false , bool $ isArgument = false ): array
145153 {
146154 $ stream ->skipWhitespace ();
147155
@@ -154,7 +162,7 @@ private function parseSimpleSelector(TokenStream $stream, bool $insideNegation =
154162 if ($ peek ->isWhitespace ()
155163 || $ peek ->isFileEnd ()
156164 || $ peek ->isDelimiter ([', ' , '+ ' , '> ' , '~ ' ])
157- || ($ insideNegation && $ peek ->isDelimiter ([') ' ]))
165+ || ($ isArgument && $ peek ->isDelimiter ([') ' ]))
158166 ) {
159167 break ;
160168 }
@@ -215,7 +223,7 @@ private function parseSimpleSelector(TokenStream $stream, bool $insideNegation =
215223 throw SyntaxErrorException::nestedNot ();
216224 }
217225
218- [$ argument , $ argumentPseudoElement ] = $ this ->parseSimpleSelector ($ stream , true );
226+ [$ argument , $ argumentPseudoElement ] = $ this ->parseSimpleSelector ($ stream , true , true );
219227 $ next = $ stream ->getNext ();
220228
221229 if (null !== $ argumentPseudoElement ) {
@@ -227,6 +235,24 @@ private function parseSimpleSelector(TokenStream $stream, bool $insideNegation =
227235 }
228236
229237 $ 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 );
230256 } else {
231257 $ arguments = [];
232258 $ next = null ;
0 commit comments