rcss-css 0.1.0

Rusty Cascading Style Sheets (RCSS) is a styling language that brings Rust-inspired syntax to CSS. It combines the robustness of Rust with SASS-like features such as nesting and variables for cleaner, more maintainable styles.
//
// 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" | "" }