rcss-css 0.2.2

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.
// Add this in the CSS section, near the beginning
rcss = _{ SOI ~ (WHITE_SPACE* ~ (at_methods_oneliner | import_statement | function_definition | variable_declaration | rule) ~ WHITE_SPACE*)* ~ EOI }

at_methods_oneliner = { 
    WHITE_SPACE* ~ "@" ~ (
        "import" ~ WHITE_SPACE+ ~ "url" ~ "(" ~ string_literal ~ ")" ~ WHITE_SPACE* ~ ";" |
        "charset" ~ WHITE_SPACE+ ~ string_literal ~ WHITE_SPACE* ~ ";" |
        "namespace" ~ WHITE_SPACE+ ~ (string_literal ~ WHITE_SPACE+)? ~ identifier ~ WHITE_SPACE* ~ ";" |
        ANY ~ WHITE_SPACE ~ ANY ~ WHITE_SPACE ~ ";"
    )
}

//
// IMPORTS
//
import_statement = { WHITE_SPACE* ~ "use" ~ WHITE_SPACE+ ~ import_path ~ end_seperater ~ WHITE_SPACE* }
import_path = _{ (identifier ~ "::" )* ~ ( identifier | "*" ) }

//
// 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" | "@-webkit-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", "::before")
sel_element     = _{ sel_id | sel_class | sel_uni | sel_type | pseudo_element | pseudo_element_reference }

// 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* }

// Pseudo-elements (e.g., "::before", "::after")
pseudo_element  = _{ ":" ~ ":"? ~ ASCII_ALPHA+ }
pseudo_element_reference = _{ "&:" ~ ":"? ~ ASCII_ALPHA+ }

//
// DECLARATION
//
del_property        = @{ ANY ~ 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 )* ~ "\"") | ("'" ~ ( !"'" ~ 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 | ASCII_DIGIT | "-")+ ~ "(" ~ 
    (
        WHITE_SPACE* ~ 
        (
            function_call | 
            del_val_keyword | 
            del_val_color | 
            del_val_length | 
            variable_reference | 
            string_literal |
            "-" ~ ASCII_DIGIT+ ~ ("." ~ ASCII_DIGIT+)? ~ length_type |  // For negative values
            arithmetic_operator                                         // For calc expressions
        ) ~ 
        WHITE_SPACE* ~ ("," ~ WHITE_SPACE*)?
    )* ~ 
    ")" 
}

// Add this new rule for arithmetic operators in calc() functions
arithmetic_operator = { "+" | "-" | "*" | "/" }

important = {"!important"}

del_value = _{ 
    (
        (function_call | del_val_keyword | del_val_color | del_val_length | variable_reference | string_literal | css_operator | important) ~ 
        WHITE_SPACE*
    )+ ~ 
    (
        "," ~ WHITE_SPACE* ~ 
        (
            (function_call | del_val_keyword | del_val_color | del_val_length | variable_reference | string_literal | css_operator) ~ 
            WHITE_SPACE*
        )+
    )*
}

css_operator = { "/" | "," }

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