@@ -75,6 +75,48 @@ module.exports = grammar(CSS, {
7575 optional ( alias ( $ . pseudo_class_arguments , $ . arguments ) ) ,
7676 ) ,
7777
78+ pseudo_element_selector : $ => seq (
79+ optional ( $ . _selector ) ,
80+ '::' ,
81+ alias ( choice ( $ . identifier , $ . _concatenated_identifier ) , $ . tag_name ) ,
82+ optional ( alias ( $ . pseudo_element_arguments , $ . arguments ) ) ,
83+ ) ,
84+
85+ id_selector : $ => seq (
86+ optional ( $ . _selector ) ,
87+ '#' ,
88+ alias ( choice ( $ . identifier , $ . _concatenated_identifier ) , $ . id_name ) ,
89+ ) ,
90+
91+ attribute_selector : $ => seq (
92+ optional ( $ . _selector ) ,
93+ '[' ,
94+ alias ( choice ( $ . identifier , $ . _concatenated_identifier , $ . namespace_selector ) , $ . attribute_name ) ,
95+ optional ( seq (
96+ choice ( '=' , '~=' , '^=' , '|=' , '*=' , '$=' ) ,
97+ $ . _value ,
98+ ) ) ,
99+ ']' ,
100+ ) ,
101+
102+ child_selector : $ => prec . left ( seq (
103+ optional ( $ . _selector ) ,
104+ '>' ,
105+ $ . _selector ,
106+ ) ) ,
107+
108+ sibling_selector : $ => prec . left ( seq (
109+ optional ( $ . _selector ) ,
110+ '~' ,
111+ $ . _selector ,
112+ ) ) ,
113+
114+ adjacent_sibling_selector : $ => prec . left ( seq (
115+ optional ( $ . _selector ) ,
116+ '+' ,
117+ $ . _selector ,
118+ ) ) ,
119+
78120 // Declarations
79121
80122 declaration : $ => seq (
@@ -89,6 +131,8 @@ module.exports = grammar(CSS, {
89131 ';' ,
90132 ) ,
91133
134+ default : _ => '!default' ,
135+
92136 // Media queries
93137
94138 _query : ( $ , original ) => choice (
@@ -104,13 +148,71 @@ module.exports = grammar(CSS, {
104148 $ . nesting_selector ,
105149 $ . _concatenated_identifier ,
106150 $ . list_value ,
151+ $ . map_value ,
152+ $ . unary_expression ,
153+ $ . default ,
107154 ) ) ,
108155 $ . variable ,
109156 ) ,
110157
111- use_statement : $ => seq ( '@use' , $ . _value , ';' ) ,
158+ string_value : $ => choice (
159+ seq (
160+ '\'' ,
161+ repeat ( choice (
162+ alias ( / ( [ ^ # ' \n ] | \\ ( .| \n ) | \# [ ^ { ] ) + / , $ . string_content ) ,
163+ $ . interpolation ,
164+ ) ) ,
165+ '\'' ,
166+ ) ,
167+ seq (
168+ '"' ,
169+ repeat ( choice (
170+ alias ( / ( [ ^ # " \n ] | \\ ( .| \n ) | \# [ ^ { ] ) + / , $ . string_content ) ,
171+ $ . interpolation ,
172+ ) ) ,
173+ '"' ,
174+ ) ,
175+ ) ,
176+
177+ use_statement : $ => seq (
178+ '@use' ,
179+ $ . _value ,
180+ optional ( $ . as_clause ) ,
181+ optional ( $ . with_clause ) ,
182+ ';' ,
183+ ) ,
184+
185+ as_clause : $ => seq ( 'as' , choice ( '*' , $ . identifier , $ . plain_value ) ) ,
186+
187+ with_clause : $ => seq ( 'with' , $ . with_parameters ) ,
188+
189+ with_parameters : $ => seq (
190+ '(' ,
191+ sep1 (
192+ ',' ,
193+ seq (
194+ $ . variable ,
195+ ':' ,
196+ $ . _value ,
197+ optional ( $ . default ) ,
198+ ) ,
199+ ) ,
200+ optional ( ',' ) ,
201+ ')' ,
202+ ) ,
203+
204+ visibility_clause : $ => seq ( choice ( 'hide' , 'show' ) , $ . visibility_parameters ) ,
112205
113- forward_statement : $ => seq ( '@forward' , $ . _value , ';' ) ,
206+ visibility_parameters : $ => sep1 ( ',' , $ . identifier ) ,
207+
208+ forward_statement : $ => seq (
209+ '@forward' ,
210+ $ . _value ,
211+ optional ( $ . as_clause ) ,
212+ optional ( $ . visibility_clause ) ,
213+ optional ( $ . with_clause ) ,
214+ ';' ,
215+ ) ,
114216
115217 mixin_statement : $ => seq (
116218 '@mixin' ,
@@ -146,12 +248,16 @@ module.exports = grammar(CSS, {
146248
147249 parameters : $ => seq ( '(' , sep1 ( ',' , $ . parameter ) , ')' ) ,
148250
149- parameter : $ => seq (
150- $ . variable ,
151- optional ( seq (
152- ':' ,
153- field ( 'default' , $ . _value ) ,
154- ) ) ,
251+ parameter : $ => choice (
252+ seq (
253+ $ . variable ,
254+ optional ( '...' ) ,
255+ optional ( seq (
256+ ':' ,
257+ field ( 'default' , $ . _value ) ,
258+ ) ) ,
259+ ) ,
260+ '...' ,
155261 ) ,
156262
157263 return_statement : $ => seq ( '@return' , $ . _value , ';' ) ,
@@ -209,22 +315,46 @@ module.exports = grammar(CSS, {
209315 $ . arguments ,
210316 ) ,
211317
212- binary_expression : $ => prec . left ( seq (
318+ binary_expression : $ => prec . left ( 1 , seq (
213319 $ . _value ,
214- choice ( '+' , '-' , '*' , '/' , '==' , '<' , '>' , '!=' , '<=' , '>=' ) ,
320+ choice ( '+' , '-' , '*' , '/' , '==' , '<' , '>' , '!=' , '<=' , '>=' , 'and' , 'or' ) ,
215321 $ . _value ,
216322 ) ) ,
217323
324+ unary_expression : $ => seq (
325+ choice ( '-' , '+' , '/' , 'not' ) ,
326+ $ . _value ,
327+ ) ,
328+
218329 list_value : $ => seq (
219330 '(' ,
220331 sep2 ( ',' , $ . _value ) ,
221332 ')' ,
222333 ) ,
223334
335+ map_value : $ => seq (
336+ '(' ,
337+ sep1 ( ',' , seq (
338+ field ( 'key' , $ . _value ) ,
339+ ':' ,
340+ field ( 'value' , $ . _value ) ,
341+ ) ) ,
342+ ')' ,
343+ ) ,
344+
224345 interpolation : $ => seq ( '#{' , $ . _value , '}' ) ,
225346
226347 placeholder : $ => seq ( '%' , $ . identifier ) ,
227348
349+ arguments : $ => seq (
350+ token . immediate ( '(' ) ,
351+ sep (
352+ choice ( ',' , ';' ) ,
353+ seq ( repeat1 ( $ . _value ) , optional ( '...' ) ) ,
354+ ) ,
355+ ')' ,
356+ ) ,
357+
228358 _concatenated_identifier : $ => choice (
229359 seq (
230360 $ . identifier ,
@@ -243,9 +373,46 @@ module.exports = grammar(CSS, {
243373 ) ,
244374
245375 variable : _ => / ( [ a - z A - Z _ ] + \. ) ? \$ [ a - z A - Z - _ ] [ a - z A - Z 0 - 9 - _ ] * / ,
376+
377+ plain_value : _ => token ( seq (
378+ repeat ( choice (
379+ / [ - _ ] / ,
380+ / \/ [ ^ \* \s , ; ! { } ( ) \[ \] ] / , // Slash not followed by a '*' (which would be a comment)
381+ ) ) ,
382+ / [ a - z A - Z ] / ,
383+ choice (
384+ / [ ^ / \s , : ; ! { } ( ) \[ \] ] / , // Not a slash, not a delimiter character (no colon)
385+ / \/ [ ^ \* \s , : ; ! { } ( ) \[ \] ] / , // Slash not followed by a '*' (which would be a comment) (no colon)
386+ seq (
387+ repeat1 ( choice (
388+ / [ ^ / \s , ; ! { } ( ) \[ \] ] / , // Not a slash, not a delimiter character
389+ / \/ [ ^ \* \s , ; ! { } ( ) \[ \] ] / , // Slash not followed by a '*' (which would be a comment)
390+ ) ) ,
391+ choice (
392+ / [ ^ / \s , : ; ! { } ( ) \[ \] ] / , // Not a slash, not a delimiter character (no colon)
393+ / \/ [ ^ \* \s , : ; ! { } ( ) \[ \] ] / , // Slash not followed by a '*' (which would be a comment) (no colon)
394+ ) ,
395+ ) ,
396+ ) ,
397+ ) ) ,
398+
246399 } ,
247400} ) ;
248401
402+ /**
403+ * Creates a rule to optionally match one or more of the rules separated by `separator`
404+ *
405+ * @param {RuleOrLiteral } separator
406+ *
407+ * @param {RuleOrLiteral } rule
408+ *
409+ * @return {ChoiceRule }
410+ *
411+ */
412+ function sep ( separator , rule ) {
413+ return optional ( sep1 ( separator , rule ) ) ;
414+ }
415+
249416/**
250417 * Creates a rule to match one or more of the rules separated by `separator`
251418 *
0 commit comments