2018-09-30 22:59:56 +00:00
|
|
|
module.exports = grammar({
|
|
|
|
name: 'css',
|
|
|
|
|
|
|
|
extras: $ => [
|
|
|
|
/\s/,
|
|
|
|
$.comment,
|
|
|
|
],
|
|
|
|
|
2018-10-18 06:14:21 +00:00
|
|
|
externals: $ => [
|
|
|
|
$._descendant_operator,
|
|
|
|
],
|
|
|
|
|
2018-09-30 22:59:56 +00:00
|
|
|
rules: {
|
|
|
|
stylesheet: $ => repeat(choice(
|
|
|
|
$.rule_set,
|
|
|
|
$.import_statement,
|
|
|
|
)),
|
|
|
|
|
|
|
|
// Statements
|
|
|
|
|
|
|
|
import_statement: $ => seq(
|
|
|
|
'@import'
|
|
|
|
),
|
|
|
|
|
|
|
|
// Rule sets
|
|
|
|
|
|
|
|
rule_set: $ => seq(
|
|
|
|
$.selectors,
|
|
|
|
$.block
|
|
|
|
),
|
|
|
|
|
|
|
|
selectors: $ => commaSep1($._selector),
|
|
|
|
|
2018-10-18 06:14:21 +00:00
|
|
|
block: $ => seq(
|
|
|
|
'{',
|
|
|
|
repeat(choice($.declaration, $.rule_set)),
|
|
|
|
'}'
|
|
|
|
),
|
2018-09-30 22:59:56 +00:00
|
|
|
|
|
|
|
// Selectors
|
|
|
|
|
|
|
|
_selector: $ => choice(
|
|
|
|
$.universal_selector,
|
2018-10-18 06:14:21 +00:00
|
|
|
alias($.identifier, $.tag_name),
|
2018-09-30 22:59:56 +00:00
|
|
|
$.class_selector,
|
2018-10-18 06:14:21 +00:00
|
|
|
$.nesting_selector,
|
|
|
|
$.pseudo_class_selector,
|
|
|
|
$.pseudo_element_selector,
|
2018-09-30 22:59:56 +00:00
|
|
|
$.id_selector,
|
|
|
|
$.attribute_selector,
|
|
|
|
$.child_selector,
|
|
|
|
$.descendant_selector
|
|
|
|
),
|
|
|
|
|
2018-10-18 06:14:21 +00:00
|
|
|
nesting_selector: $ => '&',
|
|
|
|
|
2018-09-30 22:59:56 +00:00
|
|
|
universal_selector: $ => '*',
|
|
|
|
|
2018-10-18 06:14:21 +00:00
|
|
|
class_selector: $ => seq(
|
|
|
|
optional($._selector),
|
|
|
|
'.',
|
|
|
|
alias($.identifier, $.class_name),
|
|
|
|
),
|
|
|
|
|
|
|
|
pseudo_class_selector: $ => seq(
|
|
|
|
optional($._selector),
|
|
|
|
':',
|
|
|
|
alias($.identifier, $.class_name),
|
|
|
|
optional($.arguments)
|
|
|
|
),
|
2018-09-30 22:59:56 +00:00
|
|
|
|
2018-10-18 06:14:21 +00:00
|
|
|
pseudo_element_selector: $ => seq(
|
|
|
|
optional($._selector),
|
|
|
|
'::',
|
|
|
|
alias($.identifier, $.tag_name)
|
|
|
|
),
|
2018-09-30 22:59:56 +00:00
|
|
|
|
2018-10-18 06:14:21 +00:00
|
|
|
id_selector: $ => seq(
|
|
|
|
optional($._selector),
|
|
|
|
'#',
|
|
|
|
alias($.identifier, $.id_name)
|
|
|
|
),
|
2018-09-30 22:59:56 +00:00
|
|
|
|
|
|
|
attribute_selector: $ => seq(
|
2018-10-18 06:14:21 +00:00
|
|
|
optional($._selector),
|
|
|
|
'[',
|
|
|
|
alias($.identifier, $.attribute_name),
|
2018-09-30 22:59:56 +00:00
|
|
|
optional(seq(
|
|
|
|
choice('=', '~=', '^=', '|=', '*=', '$='),
|
2018-10-18 06:14:21 +00:00
|
|
|
$._value
|
2018-09-30 22:59:56 +00:00
|
|
|
)),
|
|
|
|
']'
|
|
|
|
),
|
|
|
|
|
|
|
|
child_selector: $ => prec.left(seq($._selector, '>', $._selector)),
|
|
|
|
|
2018-10-18 06:14:21 +00:00
|
|
|
descendant_selector: $ => prec.left(seq($._selector, $._descendant_operator, $._selector)),
|
2018-09-30 22:59:56 +00:00
|
|
|
|
|
|
|
// Declarations
|
|
|
|
|
2018-10-18 06:14:21 +00:00
|
|
|
declaration: $ => prec(1, seq(
|
|
|
|
alias($.identifier, $.property_name),
|
2018-09-30 22:59:56 +00:00
|
|
|
':',
|
2018-10-18 06:14:21 +00:00
|
|
|
repeat1($._value),
|
2018-09-30 22:59:56 +00:00
|
|
|
';'
|
2018-10-18 06:14:21 +00:00
|
|
|
)),
|
|
|
|
|
|
|
|
// Property Values
|
|
|
|
|
|
|
|
_value: $ => choice(
|
|
|
|
alias($.identifier, $.value_name),
|
|
|
|
$.color_value,
|
|
|
|
$.integer_value,
|
|
|
|
$.float_value,
|
|
|
|
$.function_value
|
|
|
|
),
|
|
|
|
|
|
|
|
integer_value: $ => seq(
|
|
|
|
token(seq(
|
|
|
|
optional(choice('+', '-')),
|
|
|
|
/\d+/
|
|
|
|
)),
|
|
|
|
optional($.unit)
|
|
|
|
),
|
|
|
|
|
|
|
|
float_value: $ => seq(
|
|
|
|
token(seq(
|
|
|
|
optional(choice('+', '-')),
|
|
|
|
/\d*/,
|
|
|
|
choice(
|
|
|
|
seq('.', /\d+/),
|
|
|
|
seq('e', optional('-'), /\d+/),
|
|
|
|
seq('.', /\d+/, 'e', optional('-'), /\d+/)
|
|
|
|
)
|
|
|
|
)),
|
|
|
|
optional($.unit)
|
|
|
|
),
|
|
|
|
|
|
|
|
unit: $ => token.immediate(/[a-z]+/),
|
|
|
|
|
|
|
|
color_value: $ => /#[0-9a-fA-F]{3,6}/,
|
|
|
|
|
|
|
|
function_value: $ => seq(
|
|
|
|
alias($.identifier, $.function_name),
|
|
|
|
$.arguments
|
|
|
|
),
|
|
|
|
|
|
|
|
arguments: $ => seq(
|
|
|
|
'(',
|
|
|
|
commaSep($._value),
|
|
|
|
')'
|
2018-09-30 22:59:56 +00:00
|
|
|
),
|
|
|
|
|
|
|
|
property_name: $ => $.identifier,
|
|
|
|
|
|
|
|
identifier: $ => /[a-zA-Z-_]+/,
|
|
|
|
|
|
|
|
comment: $ => token(choice(
|
|
|
|
seq('//', /.*/),
|
|
|
|
seq(
|
|
|
|
'/*',
|
|
|
|
/[^*]*\*+([^/*][^*]*\*+)*/,
|
|
|
|
'/'
|
|
|
|
)
|
|
|
|
))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2018-10-18 06:14:21 +00:00
|
|
|
function commaSep (rule) {
|
|
|
|
return optional(commaSep1(rule))
|
|
|
|
}
|
|
|
|
|
2018-09-30 22:59:56 +00:00
|
|
|
function commaSep1 (rule) {
|
|
|
|
return seq(rule, repeat(seq(',', rule)))
|
|
|
|
}
|