CSS2.1 Grammar
Author: wayland76, David Warring
This should be doing CSS2.1; hopefully CSS3 when that's ready (but that may be a while).
Source code: CSSGrammar.pm
use v6; grammar CSSGrammar { # builtin: ident (we use cssident), alpha token TOP { ^ <import>* <css>* $ || <.panic: "CSS parsing failed"> } token css { <ruleset> | <media> | <page> } rule ruleset { <selector> +% ',' '{' ~ '}' <declarations> } rule declarations { <declaration> +%% ';' } rule selector { <simple_selector> +% <combinator>? } rule simple_selector { <element_name> [ <hcap> ]* | <hcap>+ } token hcap { '#' | <class> | '[' ~ ']' <attrib> | <pseudo> } token class { '.' <cssident> } token element_name { <cssident> | '*' } token attrib { <cssident> [ [ '=' | <INCLUDES> | <DASHMATCH> ] [ <cssident> | <string> ] ]? } token pseudo { ':' [ <FUNCTION> ~ ')' <cssident>? | <cssident> ] } token combinator { '+' | '>' } rule declaration { <property> ':' <expr> <prio>? } token property { <cssident> } token prio { <important_sym> } token expr { <term> +% <operator>? } token cssident { '-'?<namestart><namechar>* } rule term { <unary_operator>? [ <percentage> | <length> | <ems> | <exs> | <angle> | <time> | <freq> | <number> ] | <string> | <uri> | <function> | <cssident> | <hexcolor> } token operator { '/' | ',' } token function { <FUNCTION> ~ ')' <expr> } token hexcolor { '#' } token namestart { <alpha> | _ } token namechar { \w | '-' } token unary_operator { '-' | '+' } token number { \d+ | \d* '.' \d+ } token percentage { <number> '%' } token length {:i <number> [ px | cm | mm | in | pt | pc ] } token ems {:i <number>? em } token exs {:i <number>? ex } token angle {:i <number> [ deg | rad | grad ] } token time {:i <number> [ ms | s ] } token freq {:i <number> k?hz } token string { ('"' | \') (<- nl>|\\ \n)*? $0 } token uri {:i url '(' ~ ')' [ <string> | <url>] } token url { ( <- [\( \) \' \" \\]> )* } token FUNCTION { <cssident> '(' } token INCLUDES { '~=' } token DASHMATCH { '|=' } token important_sym {:i '!'important } rule import {:i'@import' [<string>|<uri>] <media_list>? ';' } rule media {:i'@media' <media_list> <media_rules> } rule media_list {<media_type> +%','} rule media_type { <cssident> } rule media_rules { '{' ~ '}' <ruleset>* } rule page {:i'@page' [':'<cssident>]? '{' ~ '}' <declarations> } # Comments and whitespace. token comment {'<!--' .*? '-->' | '/*' .*? '*/'} token nl {\xA|"\r"\xA|"\r"|"\f"} token ws { <!ww> [ nl | "\t" | " " | <comment> ]* } method panic($e) {die $e;} }