tree-sitter-css/grammar.js

176 lines
3.2 KiB
JavaScript
Raw Normal View History

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)))
}