// 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 = { "+" | "-" | "*" | "/" }
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" | "" }