//
// CSS
//
css = _{ SOI ~ (WHITE_SPACE* ~ (function_definition | variable_declaration | rule) ~ WHITE_SPACE*)* ~ EOI }
//
// RULES
//
rule = _{ rule_comment | media_query | keyframes_rule | rule_normal }
rule_comment = { WHITE_SPACE* ~ comment ~ WHITE_SPACE* }
rule_normal = { r_base }
//
// MEDIA QUERIES
//
media_query = { WHITE_SPACE* ~ "@media" ~ WHITE_SPACE+ ~ media_condition ~ WHITE_SPACE* ~ left_curly_brace ~ rule* ~ right_curly_brace ~ WHITE_SPACE* }
media_condition = { (!(left_curly_brace) ~ ANY)+ }
//
// KEYFRAMES
//
keyframes_rule = { WHITE_SPACE* ~ "@keyframes" ~ WHITE_SPACE+ ~ keyframes_name ~ WHITE_SPACE* ~ left_curly_brace ~ keyframe_selector_block* ~ right_curly_brace ~ WHITE_SPACE* }
keyframes_name = @{ ASCII_ALPHA ~ text_chars* }
keyframe_selector_block = { WHITE_SPACE* ~ keyframe_selector ~ WHITE_SPACE* ~ left_curly_brace ~ declaration* ~ right_curly_brace ~ WHITE_SPACE* }
keyframe_selector = { percentage | from_keyword | to_keyword | (percentage ~ (WHITE_SPACE* ~ "," ~ WHITE_SPACE* ~ percentage)*) }
percentage = @{ ASCII_DIGIT+ ~ "%" }
from_keyword = { "from" }
to_keyword = { "to" }
//
// COMMENTS
//
comment = _{ comment_start_tag ~ comment_body ~ comment_end_tag }
comment_body = { (!comment_end_tag ~ ANY)* }
comment_start_tag = _{ "/*" ~ WHITE_SPACE* }
comment_end_tag = _{ WHITE_SPACE* ~ "*/" }
//
// SELECTORS
//
sel_id = _{ prefix_id ~ sel_id_body }
sel_id_body = { ASCII_ALPHA ~ text_chars* }
sel_class = _{ prefix_class ~ sel_class_body }
sel_class_body = { ASCII_ALPHA ~ text_chars* }
sel_type = _{ ASCII_ALPHA ~ text_chars* }
sel_uni = _{ "*" }
// A single selector element (e.g., "div", ".class", "#id")
sel_element = _{ sel_id | sel_class | sel_uni | sel_type }
// A compound selector with no spaces (e.g., "div.class#id")
sel_compound = _{ sel_element+ }
// The full selector with support for nesting through whitespace
selector = { WHITE_SPACE* ~ sel_compound ~ (WHITE_SPACE+ ~ sel_compound)* ~ WHITE_SPACE* }
//
// DECLARATION
//
del_property = @{ ASCII_ALPHA ~ text_chars* }
del_val_keyword = @{ ASCII_ALPHA ~ text_chars* }
del_val_color = { prefix_id ~ (ASCII_ALPHA | ASCII_DIGIT)* }
del_val_length = { ASCII_DIGIT+ ~ ("." ~ ASCII_DIGIT+)? ~ length_type }
//
// VARIABLES
//
variable_declaration = { WHITE_SPACE* ~ "let" ~ WHITE_SPACE+ ~ variable_name ~ property_separater ~ WHITE_SPACE* ~ string_literal ~ end_seperater ~ WHITE_SPACE* }
string_literal = { "\"" ~ ( !"\"" ~ ANY )* ~ "\"" }
variable_name = @{ ASCII_ALPHA ~ text_chars* }
variable_reference = { "&" ~ ASCII_ALPHA ~ text_chars* }
//
// USER CREATED FUNCTIONS
//
function_definition = { "fn" ~ WHITE_SPACE+ ~ function_name ~ WHITE_SPACE* ~ parameter_list ~ WHITE_SPACE* ~ function_block }
function_name = @{ ASCII_ALPHA ~ text_chars* }
parameter_list = { "(" ~ ")" }
parameter = { WHITE_SPACE* ~ identifier ~ WHITE_SPACE* }
identifier = @{ ASCII_ALPHA ~ text_chars* }
function_block = { left_curly_brace ~ declaration* ~ right_curly_brace }
user_created_function_call = { WHITE_SPACE* ~ function_name ~ WHITE_SPACE* ~ parameter_list ~ WHITE_SPACE* ~ ";" }
// Function calls (ex: blur(10px))
function_call = { ASCII_ALPHA+ ~ "(" ~ (!")" ~ ANY)* ~ ")" }
del_value = _{ ((function_call | del_val_keyword | del_val_color | del_val_length | variable_reference | string_literal) ~ WHITE_SPACE*)+ }
declaration = { WHITE_SPACE* ~ del_property ~ property_separater ~ WHITE_SPACE* ~ del_value ~ end_seperater ~ WHITE_SPACE* }
//
// RULE BASE
//
// Ex: h1 { color: red }
r_base = _{ selector ~ left_curly_brace ~ r_content* ~ right_curly_brace ~ WHITE_SPACE* }
nested_rule = _{ r_base }
r_content = _{
(comment ~ WHITE_SPACE*) |
(user_created_function_call ~ WHITE_SPACE*) |
(declaration ~ WHITE_SPACE*) |
(nested_rule ~ WHITE_SPACE*)
}
//
// SYMBOLS / CHARACTERS
//
text_chars = _{ ASCII_ALPHA | ASCII_DIGIT | "_" | "-" }
left_curly_brace = _{ "{" }
right_curly_brace = { "}" }
// multiples_separater = _{ "," }
property_separater = _{ ":" }
end_seperater = _{ ";" }
prefix_id = _{ "#" }
prefix_class = _{ "." }
length_type = { "cm" | "mm" | "in" | "px" | "pt" | "pc" | "em" | "ex" | "ch" | "rem" | "vw" | "vh" | "vmin" | "vmax" | "%" | "s" | "ms" | "" }