Skip to content

Commit

Permalink
feat: improve the grammar
Browse files Browse the repository at this point in the history
  • Loading branch information
amaanq committed Apr 11, 2024
1 parent 9068aec commit 056e5d3
Show file tree
Hide file tree
Showing 8 changed files with 23,692 additions and 14,481 deletions.
187 changes: 177 additions & 10 deletions grammar.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,48 @@ module.exports = grammar(CSS, {
optional(alias($.pseudo_class_arguments, $.arguments)),
),

pseudo_element_selector: $ => seq(
optional($._selector),
'::',
alias(choice($.identifier, $._concatenated_identifier), $.tag_name),
optional(alias($.pseudo_element_arguments, $.arguments)),
),

id_selector: $ => seq(
optional($._selector),
'#',
alias(choice($.identifier, $._concatenated_identifier), $.id_name),
),

attribute_selector: $ => seq(
optional($._selector),
'[',
alias(choice($.identifier, $._concatenated_identifier, $.namespace_selector), $.attribute_name),
optional(seq(
choice('=', '~=', '^=', '|=', '*=', '$='),
$._value,
)),
']',
),

child_selector: $ => prec.left(seq(
optional($._selector),
'>',
$._selector,
)),

sibling_selector: $ => prec.left(seq(
optional($._selector),
'~',
$._selector,
)),

adjacent_sibling_selector: $ => prec.left(seq(
optional($._selector),
'+',
$._selector,
)),

// Declarations

declaration: $ => seq(
Expand All @@ -89,6 +131,8 @@ module.exports = grammar(CSS, {
';',
),

default: _ => '!default',

// Media queries

_query: ($, original) => choice(
Expand All @@ -104,13 +148,71 @@ module.exports = grammar(CSS, {
$.nesting_selector,
$._concatenated_identifier,
$.list_value,
$.map_value,
$.unary_expression,
$.default,
)),
$.variable,
),

use_statement: $ => seq('@use', $._value, ';'),
string_value: $ => choice(
seq(
'\'',
repeat(choice(
alias(/([^#'\n]|\\(.|\n)|\#[^{])+/, $.string_content),
$.interpolation,
)),
'\'',
),
seq(
'"',
repeat(choice(
alias(/([^#"\n]|\\(.|\n)|\#[^{])+/, $.string_content),
$.interpolation,
)),
'"',
),
),

use_statement: $ => seq(
'@use',
$._value,
optional($.as_clause),
optional($.with_clause),
';',
),

as_clause: $ => seq('as', choice('*', $.identifier, $.plain_value)),

with_clause: $ => seq('with', $.with_parameters),

with_parameters: $ => seq(
'(',
sep1(
',',
seq(
$.variable,
':',
$._value,
optional($.default),
),
),
optional(','),
')',
),

visibility_clause: $ => seq(choice('hide', 'show'), $.visibility_parameters),

forward_statement: $ => seq('@forward', $._value, ';'),
visibility_parameters: $ => sep1(',', $.identifier),

forward_statement: $ => seq(
'@forward',
$._value,
optional($.as_clause),
optional($.visibility_clause),
optional($.with_clause),
';',
),

mixin_statement: $ => seq(
'@mixin',
Expand Down Expand Up @@ -146,12 +248,16 @@ module.exports = grammar(CSS, {

parameters: $ => seq('(', sep1(',', $.parameter), ')'),

parameter: $ => seq(
$.variable,
optional(seq(
':',
field('default', $._value),
)),
parameter: $ => choice(
seq(
$.variable,
optional('...'),
optional(seq(
':',
field('default', $._value),
)),
),
'...',
),

return_statement: $ => seq('@return', $._value, ';'),
Expand Down Expand Up @@ -209,22 +315,46 @@ module.exports = grammar(CSS, {
$.arguments,
),

binary_expression: $ => prec.left(seq(
binary_expression: $ => prec.left(1, seq(
$._value,
choice('+', '-', '*', '/', '==', '<', '>', '!=', '<=', '>='),
choice('+', '-', '*', '/', '==', '<', '>', '!=', '<=', '>=', 'and', 'or'),
$._value,
)),

unary_expression: $ => seq(
choice('-', '+', '/', 'not'),
$._value,
),

list_value: $ => seq(
'(',
sep2(',', $._value),
')',
),

map_value: $ => seq(
'(',
sep1(',', seq(
field('key', $._value),
':',
field('value', $._value),
)),
')',
),

interpolation: $ => seq('#{', $._value, '}'),

placeholder: $ => seq('%', $.identifier),

arguments: $ => seq(
token.immediate('('),
sep(
choice(',', ';'),
seq(repeat1($._value), optional('...')),
),
')',
),

_concatenated_identifier: $ => choice(
seq(
$.identifier,
Expand All @@ -243,9 +373,46 @@ module.exports = grammar(CSS, {
),

variable: _ => /([a-zA-Z_]+\.)?\$[a-zA-Z-_][a-zA-Z0-9-_]*/,

plain_value: _ => token(seq(
repeat(choice(
/[-_]/,
/\/[^\*\s,;!{}()\[\]]/, // Slash not followed by a '*' (which would be a comment)
)),
/[a-zA-Z]/,
choice(
/[^/\s,:;!{}()\[\]]/, // Not a slash, not a delimiter character (no colon)
/\/[^\*\s,:;!{}()\[\]]/, // Slash not followed by a '*' (which would be a comment) (no colon)
seq(
repeat1(choice(
/[^/\s,;!{}()\[\]]/, // Not a slash, not a delimiter character
/\/[^\*\s,;!{}()\[\]]/, // Slash not followed by a '*' (which would be a comment)
)),
choice(
/[^/\s,:;!{}()\[\]]/, // Not a slash, not a delimiter character (no colon)
/\/[^\*\s,:;!{}()\[\]]/, // Slash not followed by a '*' (which would be a comment) (no colon)
),
),
),
)),

},
});

/**
* Creates a rule to optionally match one or more of the rules separated by `separator`
*
* @param {RuleOrLiteral} separator
*
* @param {RuleOrLiteral} rule
*
* @return {ChoiceRule}
*
*/
function sep(separator, rule) {
return optional(sep1(separator, rule));
}

/**
* Creates a rule to match one or more of the rules separated by `separator`
*
Expand Down
Loading

0 comments on commit 056e5d3

Please sign in to comment.