| File: | blib/lib/CSS/Grammar/CSS21.pm |
| Coverage: | 100.0% |
| line | stmt | bran | cond | sub | time | code |
|---|---|---|---|---|---|---|
| 1 | package CSS::Grammar::CSS21; | |||||
| 2 | ||||||
| 3 | 4 4 4 | 20 8 23 | use strict; | |||
| 4 | 4 4 4 | 28 13 23 | use warnings; | |||
| 5 | ||||||
| 6 | 4 4 4 | 32 11 23 | use base 'CSS::Grammar'; | |||
| 7 | ||||||
| 8 | # | |||||
| 9 | # http://www.w3.org/TR/CSS21/ | |||||
| 10 | # http://www.w3.org/TR/CSS21/grammar.html | |||||
| 11 | # http://www.w3.org/TR/CSS21/syndata.html#parsing-errors | |||||
| 12 | # | |||||
| 13 | ||||||
| 14 | sub init { | |||||
| 15 | 4 | 13 | my ($self) = @_; | |||
| 16 | ||||||
| 17 | 4 | 7 | my %rx; | |||
| 18 | ||||||
| 19 | ##################################################################################### | |||||
| 20 | ||||||
| 21 | 4 | 12 | $self->{case_insensitive} = 1; | |||
| 22 | ||||||
| 23 | ||||||
| 24 | ##################################################################################### | |||||
| 25 | ||||||
| 26 | #h [0-9a-f] | |||||
| 27 | #nonascii [\200-\377] | |||||
| 28 | #unicode \\{h}{1,6}(\r\n|[ \t\r\n\f])? | |||||
| 29 | #escape {unicode}|\\[^\r\n\f0-9a-f] | |||||
| 30 | #s [ \t\r\n\f]+ | |||||
| 31 | #w {s}? | |||||
| 32 | #nl \n|\r\n|\r|\f | |||||
| 33 | ||||||
| 34 | 4 | 14 | $rx{h} = '[0-9a-f]'; | |||
| 35 | 4 | 11 | $rx{nonascii} = '[\\x80-\\xff]'; | |||
| 36 | 4 | 18 | $rx{unicode} = '(\\'.$rx{h}.'{1,6}(\\r\\n|[ \\t\\r\\n\\f])?)'; | |||
| 37 | 4 | 20 | $rx{escape} = '('.$rx{unicode}.'|\\\\[ -~\\x80-\\xff])'; | |||
| 38 | 4 | 9 | $rx{s} = '[ \t\r\n\f]'; | |||
| 39 | 4 | 17 | $rx{w} = "$rx{s}*"; | |||
| 40 | 4 | 11 | $rx{nl} = '(\\n|\\r\\n|\\r|\\f)'; | |||
| 41 | ||||||
| 42 | ||||||
| 43 | #nmstart [_a-z]|{nonascii}|{escape} | |||||
| 44 | #nmchar [_a-z0-9-]|{nonascii}|{escape} | |||||
| 45 | #string1 \"([^\n\r\f\\"]|\\{nl}|{escape})*\" | |||||
| 46 | #string2 \'([^\n\r\f\\']|\\{nl}|{escape})*\' | |||||
| 47 | ||||||
| 48 | 4 | 183 | $rx{nmstart} = '([_a-z]|'.$rx{nonascii}.'|'.$rx{escape}.')'; | |||
| 49 | 4 | 25 | $rx{nmchar} = '([_a-zA-Z0-9-]|'.$rx{nonascii}.'|'.$rx{escape}.')'; | |||
| 50 | 4 | 28 | $rx{string1} = '("([\\t !#$%&(-~]|\\\\('.$rx{nl}.')|\'|('.$rx{nonascii}.')|('.$rx{escape}.'))*")'; | |||
| 51 | 4 | 28 | $rx{string2} = '(\'([\\t !#$%&(-~]|\\\\('.$rx{nl}.')|"|('.$rx{nonascii}.')|('.$rx{escape}.'))*\')'; | |||
| 52 | ||||||
| 53 | ||||||
| 54 | #ident -?{nmstart}{nmchar}* | |||||
| 55 | #name {nmchar}+ | |||||
| 56 | #num [0-9]+|[0-9]*"."[0-9]+ | |||||
| 57 | #string {string1}|{string2} | |||||
| 58 | #url ([!#$%&*-~]|{nonascii}|{escape})* | |||||
| 59 | ||||||
| 60 | 4 | 20 | $rx{ident} = "$rx{nmstart}$rx{nmchar}*"; | |||
| 61 | 4 | 13 | $rx{name} = "$rx{nmchar}+"; | |||
| 62 | 4 | 12 | $rx{num} = '([0-9]+|[0-9]*\\.[0-9]+)'; | |||
| 63 | 4 | 24 | $rx{string} = "($rx{string1}|$rx{string2})"; | |||
| 64 | 4 | 26 | $rx{url} = "(([!#\$%&*-~]|$rx{nonascii}|$rx{escape})*)"; | |||
| 65 | ||||||
| 66 | ||||||
| 67 | # these aren't used in any productions... | |||||
| 68 | #invalid1 \"([^\n\r\f\\"]|\\{nl}|{escape})* | |||||
| 69 | #invalid2 \'([^\n\r\f\\']|\\{nl}|{escape})* | |||||
| 70 | #invalid {invalid1}|{invalid2} | |||||
| 71 | ||||||
| 72 | ||||||
| 73 | #A a|\\0{0,4}(41|61)(\r\n|[ \t\r\n\f])? | |||||
| 74 | #C c|\\0{0,4}(43|63)(\r\n|[ \t\r\n\f])? | |||||
| 75 | #D d|\\0{0,4}(44|64)(\r\n|[ \t\r\n\f])? | |||||
| 76 | #E e|\\0{0,4}(45|65)(\r\n|[ \t\r\n\f])? | |||||
| 77 | #G g|\\0{0,4}(47|67)(\r\n|[ \t\r\n\f])?|\\g | |||||
| 78 | #H h|\\0{0,4}(48|68)(\r\n|[ \t\r\n\f])?|\\h | |||||
| 79 | #I i|\\0{0,4}(49|69)(\r\n|[ \t\r\n\f])?|\\i | |||||
| 80 | #K k|\\0{0,4}(4b|6b)(\r\n|[ \t\r\n\f])?|\\k | |||||
| 81 | #M m|\\0{0,4}(4d|6d)(\r\n|[ \t\r\n\f])?|\\m | |||||
| 82 | #N n|\\0{0,4}(4e|6e)(\r\n|[ \t\r\n\f])?|\\n | |||||
| 83 | #O o|\\0{0,4}(51|71)(\r\n|[ \t\r\n\f])?|\\o | |||||
| 84 | #P p|\\0{0,4}(50|70)(\r\n|[ \t\r\n\f])?|\\p | |||||
| 85 | #R r|\\0{0,4}(52|72)(\r\n|[ \t\r\n\f])?|\\r | |||||
| 86 | #S s|\\0{0,4}(53|73)(\r\n|[ \t\r\n\f])?|\\s | |||||
| 87 | #T t|\\0{0,4}(54|74)(\r\n|[ \t\r\n\f])?|\\t | |||||
| 88 | #X x|\\0{0,4}(58|78)(\r\n|[ \t\r\n\f])?|\\x | |||||
| 89 | #Z z|\\0{0,4}(5a|7a)(\r\n|[ \t\r\n\f])?|\\z | |||||
| 90 | ||||||
| 91 | 4 | 11 | $rx{A} = '(a|\\\\0{0,4}(41|61)(\r\n|[ \t\r\n\f])?)'; | |||
| 92 | 4 | 13 | $rx{C} = '(c|\\\\0{0,4}(43|63)(\r\n|[ \t\r\n\f])?)'; | |||
| 93 | 4 | 11 | $rx{D} = '(d|\\\\0{0,4}(44|64)(\r\n|[ \t\r\n\f])?)'; | |||
| 94 | 4 | 11 | $rx{E} = '(e|\\\\0{0,4}(45|65)(\r\n|[ \t\r\n\f])?)'; | |||
| 95 | 4 | 11 | $rx{G} = '(g|\\\\0{0,4}(47|67)(\r\n|[ \t\r\n\f])?|\\\\g)'; | |||
| 96 | 4 | 13 | $rx{H} = '(h|\\\\0{0,4}(48|68)(\r\n|[ \t\r\n\f])?|\\\\h)'; | |||
| 97 | 4 | 11 | $rx{I} = '(i|\\\\0{0,4}(49|69)(\r\n|[ \t\r\n\f])?|\\\\i)'; | |||
| 98 | 4 | 11 | $rx{K} = '(k|\\\\0{0,4}(4b|6b)(\r\n|[ \t\r\n\f])?|\\\\k)'; | |||
| 99 | 4 | 11 | $rx{M} = '(m|\\\\0{0,4}(4d|6d)(\r\n|[ \t\r\n\f])?|\\\\m)'; | |||
| 100 | 4 | 12 | $rx{N} = '(n|\\\\0{0,4}(4e|6e)(\r\n|[ \t\r\n\f])?|\\\\n)'; | |||
| 101 | 4 | 13 | $rx{O} = '(o|\\\\0{0,4}(51|71)(\r\n|[ \t\r\n\f])?|\\\\o)'; | |||
| 102 | 4 | 10 | $rx{P} = '(p|\\\\0{0,4}(50|70)(\r\n|[ \t\r\n\f])?|\\\\p)'; | |||
| 103 | 4 | 12 | $rx{R} = '(r|\\\\0{0,4}(52|72)(\r\n|[ \t\r\n\f])?|\\\\r)'; | |||
| 104 | 4 | 9 | $rx{S} = '(s|\\\\0{0,4}(53|73)(\r\n|[ \t\r\n\f])?|\\\\s)'; | |||
| 105 | 4 | 11 | $rx{T} = '(t|\\\\0{0,4}(54|74)(\r\n|[ \t\r\n\f])?|\\\\t)'; | |||
| 106 | 4 | 12 | $rx{X} = '(x|\\\\0{0,4}(58|78)(\r\n|[ \t\r\n\f])?|\\\\x)'; | |||
| 107 | 4 | 18 | $rx{Z} = '(z|\\\\0{0,4}(5a|7a)(\r\n|[ \t\r\n\f])?|\\\\z)'; | |||
| 108 | ||||||
| 109 | ||||||
| 110 | ##################################################################################### | |||||
| 111 | ||||||
| 112 | #{s} {return S;} | |||||
| 113 | #"<!--" {return CDO;} | |||||
| 114 | #"-->" {return CDC;} | |||||
| 115 | #"~=" {return INCLUDES;} | |||||
| 116 | #"|=" {return DASHMATCH;} | |||||
| 117 | ||||||
| 118 | 4 | 28 | $self->add_toke_rule('S' , "$rx{s}+"); | |||
| 119 | 4 | 17 | $self->add_toke_rule('CDO' , '<!--'); | |||
| 120 | 4 | 15 | $self->add_toke_rule('CDC' , '-->'); | |||
| 121 | 4 | 15 | $self->add_toke_rule('INCLUDES' , '~='); | |||
| 122 | 4 | 15 | $self->add_toke_rule('DASHMATCH' , '\\|='); | |||
| 123 | ||||||
| 124 | ||||||
| 125 | #{w}"{" {return LBRACE;} | |||||
| 126 | #{w}"+" {return PLUS;} | |||||
| 127 | #{w}">" {return GREATER;} | |||||
| 128 | #{w}"," {return COMMA;} | |||||
| 129 | ||||||
| 130 | 4 | 23 | $self->add_toke_rule('LBRACE' , "$rx{w}\\{"); | |||
| 131 | 4 | 20 | $self->add_toke_rule('PLUS' , "$rx{w}\\+"); | |||
| 132 | 4 | 20 | $self->add_toke_rule('GREATER' , "$rx{w}>"); | |||
| 133 | 4 | 20 | $self->add_toke_rule('COMMA' , "$rx{w},"); | |||
| 134 | ||||||
| 135 | ||||||
| 136 | #{string} {return STRING;} | |||||
| 137 | #{invalid} {return INVALID; /* unclosed string */} | |||||
| 138 | #{ident} {return IDENT;} | |||||
| 139 | #"#"{name} {return HASH;} | |||||
| 140 | ||||||
| 141 | 4 | 16 | $self->add_toke_rule('STRING' , $rx{string}); | |||
| 142 | 4 | 18 | $self->add_toke_rule('IDENT' , $rx{ident}); | |||
| 143 | 4 | 22 | $self->add_toke_rule('HASH' , "#$rx{name}"); | |||
| 144 | ||||||
| 145 | ||||||
| 146 | #@{I}{M}{P}{O}{R}{T} {return IMPORT_SYM;} | |||||
| 147 | #@{P}{A}{G}{E} {return PAGE_SYM;} | |||||
| 148 | #@{M}{E}{D}{I}{A} {return MEDIA_SYM;} | |||||
| 149 | #@{C}{H}{A}{R}{S}{E}{T} {return CHARSET_SYM;} | |||||
| 150 | ||||||
| 151 | #"!"({w}|{comment})*{I}{M}{P}{O}{R}{T}{A}{N}{T} {return IMPORTANT_SYM;} | |||||
| 152 | ||||||
| 153 | 4 | 40 | $self->add_toke_rule('IMPORT_SYM' , "\@$rx{I}$rx{M}$rx{P}$rx{O}$rx{R}$rx{T}"); | |||
| 154 | 4 | 31 | $self->add_toke_rule('PAGE_SYM' , "\@$rx{P}$rx{A}$rx{G}$rx{E}"); | |||
| 155 | 4 | 35 | $self->add_toke_rule('MEDIA_SYM' , "\@$rx{M}$rx{E}$rx{D}$rx{I}$rx{A}"); | |||
| 156 | 4 | 43 | $self->add_toke_rule('CHARSET_SYM' , "\@$rx{C}$rx{H}$rx{A}$rx{R}$rx{S}$rx{E}$rx{T}"); | |||
| 157 | ||||||
| 158 | 4 | 56 | $self->add_toke_rule('IMPORTANT_SYM' , "!$rx{w}$rx{I}$rx{M}$rx{P}$rx{O}$rx{R}$rx{T}$rx{A}$rx{N}$rx{T}"); | |||
| 159 | ||||||
| 160 | ||||||
| 161 | #{num}{E}{M} {return EMS;} | |||||
| 162 | #{num}{E}{X} {return EXS;} | |||||
| 163 | #{num}{P}{X} {return LENGTH;} | |||||
| 164 | #{num}{C}{M} {return LENGTH;} | |||||
| 165 | #{num}{M}{M} {return LENGTH;} | |||||
| 166 | #{num}{I}{N} {return LENGTH;} | |||||
| 167 | #{num}{P}{T} {return LENGTH;} | |||||
| 168 | #{num}{P}{C} {return LENGTH;} | |||||
| 169 | #{num}{D}{E}{G} {return ANGLE;} | |||||
| 170 | #{num}{R}{A}{D} {return ANGLE;} | |||||
| 171 | #{num}{G}{R}{A}{D} {return ANGLE;} | |||||
| 172 | #{num}{M}{S} {return TIME;} | |||||
| 173 | #{num}{S} {return TIME;} | |||||
| 174 | #{num}{H}{Z} {return FREQ;} | |||||
| 175 | #{num}{K}{H}{Z} {return FREQ;} | |||||
| 176 | #{num}{ident} {return DIMENSION;} | |||||
| 177 | ||||||
| 178 | #{num}% {return PERCENTAGE;} | |||||
| 179 | #{num} {return NUMBER;} | |||||
| 180 | ||||||
| 181 | 4 | 28 | $self->add_toke_rule('EMS' , "$rx{num}$rx{E}$rx{M}"); | |||
| 182 | 4 | 27 | $self->add_toke_rule('EXS' , "$rx{num}$rx{E}$rx{X}"); | |||
| 183 | 4 | 119 | $self->add_toke_rule('LENGTH' , "$rx{num}($rx{P}$rx{X}|$rx{C}$rx{M}|$rx{M}$rx{M}|$rx{I}$rx{N}|$rx{P}$rx{T}|$rx{P}$rx{C})"); | |||
| 184 | 4 | 61 | $self->add_toke_rule('ANGLE' , "$rx{num}($rx{D}$rx{E}$rx{G}|$rx{R}$rx{A}$rx{D}|$rx{G}$rx{R}$rx{A}$rx{D})"); | |||
| 185 | 4 | 33 | $self->add_toke_rule('TIME' , "$rx{num}($rx{M}$rx{S}|$rx{S})"); | |||
| 186 | 4 | 41 | $self->add_toke_rule('FREQ' , "$rx{num}($rx{H}$rx{Z}|$rx{K}$rx{H}$rx{Z})"); | |||
| 187 | 4 | 25 | $self->add_toke_rule('DIMEN' , "$rx{num}$rx{ident}"); | |||
| 188 | 4 | 20 | $self->add_toke_rule('PERCENTAGE' , "$rx{num}%"); | |||
| 189 | 4 | 72 | $self->add_toke_rule('NUMBER' , "$rx{num}"); | |||
| 190 | ||||||
| 191 | ||||||
| 192 | #"url("{w}{string}{w}")" {return URI;} | |||||
| 193 | #"url("{w}{url}{w}")" {return URI;} | |||||
| 194 | #{ident}"(" {return FUNCTION;} | |||||
| 195 | ||||||
| 196 | 4 | 40 | $self->add_toke_rule('URI' , "url\\($rx{w}($rx{string}|$rx{url})$rx{w}\\)"); | |||
| 197 | 4 | 20 | $self->add_toke_rule('FUNCTION' , "$rx{ident}\\("); | |||
| 198 | ||||||
| 199 | ||||||
| 200 | ##################################################################################### | |||||
| 201 | ||||||
| 202 | 4 | 15 | $self->add_toke_rule('_SEMICOLON' , ';'); | |||
| 203 | 4 | 15 | $self->add_toke_rule('_BRACE_CLOSE' , '}'); | |||
| 204 | 4 | 14 | $self->add_toke_rule('_COLON' , ':'); | |||
| 205 | 4 | 16 | $self->add_toke_rule('_SLASH' , '/'); | |||
| 206 | 4 | 16 | $self->add_toke_rule('_MINUS' , '-'); | |||
| 207 | 4 | 16 | $self->add_toke_rule('_PERIOD' , '\\.'); | |||
| 208 | 4 | 16 | $self->add_toke_rule('_STAR' , '\\*'); | |||
| 209 | 4 | 15 | $self->add_toke_rule('_SQUARE_OPEN' , '\\['); | |||
| 210 | 4 | 14 | $self->add_toke_rule('_SQUARE_CLOSE' , '\\]'); | |||
| 211 | 4 | 15 | $self->add_toke_rule('_EQUALS' , '='); | |||
| 212 | 4 | 15 | $self->add_toke_rule('_ROUND_CLOSE' , '\\)'); | |||
| 213 | ||||||
| 214 | ||||||
| 215 | ##################################################################################### | |||||
| 216 | ||||||
| 217 | #stylesheet | |||||
| 218 | # : [ CHARSET_SYM STRING ';' ]? | |||||
| 219 | # [S|CDO|CDC]* [ import [S|CDO|CDC]* ]* | |||||
| 220 | # [ [ ruleset | media | page ] [S|CDO|CDC]* ]* | |||||
| 221 | # ; | |||||
| 222 | #import | |||||
| 223 | # : IMPORT_SYM S* | |||||
| 224 | # [STRING|URI] S* [ medium [ COMMA S* medium]* ]? ';' S* | |||||
| 225 | # ; | |||||
| 226 | #media | |||||
| 227 | # : MEDIA_SYM S* medium [ COMMA S* medium ]* LBRACE S* ruleset* '}' S* | |||||
| 228 | # ; | |||||
| 229 | ||||||
| 230 | 4 | 26 | $self->add_lex_rule('stylesheet', '[ CHARSET_SYM S* STRING S* _SEMICOLON ]? [S|CDO|CDC]* [ import [S|CDO|CDC]* ]* '. | |||
| 231 | '[ [ ruleset | media | page ] [S|CDO|CDC]* ]*'); | |||||
| 232 | 4 | 16 | $self->add_lex_rule('import', 'IMPORT_SYM S* [STRING|URI] S* [ medium [ COMMA S* medium]* ]? _SEMICOLON S*'); | |||
| 233 | 4 | 15 | $self->add_lex_rule('media', 'MEDIA_SYM S* medium [ COMMA S* medium ]* LBRACE S* ruleset* _BRACE_CLOSE S*'); | |||
| 234 | ||||||
| 235 | ||||||
| 236 | #medium | |||||
| 237 | # : IDENT S* | |||||
| 238 | # ; | |||||
| 239 | #page | |||||
| 240 | # : PAGE_SYM S* pseudo_page? S* | |||||
| 241 | # LBRACE S* declaration [ ';' S* declaration ]* '}' S* | |||||
| 242 | # ; | |||||
| 243 | #pseudo_page | |||||
| 244 | # : ':' IDENT | |||||
| 245 | # ; | |||||
| 246 | #operator | |||||
| 247 | # : '/' S* | COMMA S* | /* empty */ | |||||
| 248 | # ; | |||||
| 249 | ||||||
| 250 | 4 | 15 | $self->add_lex_rule('medium', 'IDENT S*'); | |||
| 251 | 4 | 18 | $self->add_lex_rule('page', 'PAGE_SYM S* pseudo_page? S* LBRACE S* declaration [ _SEMICOLON S* declaration ]* _BRACE_CLOSE S*'); | |||
| 252 | 4 | 15 | $self->add_lex_rule('pseudo_page', '_COLON IDENT'); | |||
| 253 | 4 | 16 | $self->add_lex_rule('operator', '_SLASH S* | COMMA S* | '); | |||
| 254 | ||||||
| 255 | ||||||
| 256 | #combinator | |||||
| 257 | # : PLUS S* | |||||
| 258 | # | GREATER S* | |||||
| 259 | # | S | |||||
| 260 | # ; | |||||
| 261 | #unary_operator | |||||
| 262 | # : '-' | PLUS | |||||
| 263 | # ; | |||||
| 264 | #property | |||||
| 265 | # : IDENT S* | |||||
| 266 | # ; | |||||
| 267 | #ruleset | |||||
| 268 | # : selector [ COMMA S* selector ]* | |||||
| 269 | # LBRACE S* declaration [ ';' S* declaration ]* '}' S* | |||||
| 270 | # ; | |||||
| 271 | ||||||
| 272 | 4 | 15 | $self->add_lex_rule('combinator', 'PLUS S* | GREATER S* | S+'); | |||
| 273 | 4 | 17 | $self->add_lex_rule('unary_operator', '_MINUS | PLUS'); | |||
| 274 | 4 | 16 | $self->add_lex_rule('property', 'IDENT S*'); | |||
| 275 | 4 | 17 | $self->add_lex_rule('ruleset', 'selector [ COMMA S* selector ]* S* LBRACE S* declaration [ _SEMICOLON S* declaration ]* _BRACE_CLOSE S*'); | |||
| 276 | ||||||
| 277 | ||||||
| 278 | #selector | |||||
| 279 | # : simple_selector [ combinator simple_selector ]* | |||||
| 280 | # ; | |||||
| 281 | #simple_selector | |||||
| 282 | # : element_name [ HASH | class | attrib | pseudo ]* | |||||
| 283 | # | [ HASH | class | attrib | pseudo ]+ | |||||
| 284 | # ; | |||||
| 285 | #class | |||||
| 286 | # : '.' IDENT | |||||
| 287 | # ; | |||||
| 288 | #element_name | |||||
| 289 | # : IDENT | '*' | |||||
| 290 | # ; | |||||
| 291 | ||||||
| 292 | 4 | 15 | $self->add_lex_rule('selector', 'simple_selector [ combinator simple_selector ]*'); | |||
| 293 | 4 | 15 | $self->add_lex_rule('simple_selector', 'element_name [ HASH | class | attrib | pseudo ]* | [ HASH | class | attrib | pseudo ]+'); | |||
| 294 | 4 | 16 | $self->add_lex_rule('class', '_PERIOD IDENT'); | |||
| 295 | 4 | 16 | $self->add_lex_rule('element_name', 'IDENT | _STAR'); | |||
| 296 | ||||||
| 297 | ||||||
| 298 | #attrib | |||||
| 299 | # : '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S* | |||||
| 300 | # [ IDENT | STRING ] S* ]? ']' | |||||
| 301 | # ; | |||||
| 302 | #pseudo | |||||
| 303 | # : ':' [ IDENT | FUNCTION S* IDENT? S* ')' ] | |||||
| 304 | # ; | |||||
| 305 | #declaration | |||||
| 306 | # : property ':' S* expr prio? | |||||
| 307 | # | /* empty */ | |||||
| 308 | # ; | |||||
| 309 | #prio | |||||
| 310 | # : IMPORTANT_SYM S* | |||||
| 311 | # ; | |||||
| 312 | ||||||
| 313 | 4 | 16 | $self->add_lex_rule('attrib', '_SQUARE_OPEN S* IDENT S* [ [ _EQUALS | INCLUDES | DASHMATCH ] S* [ IDENT | STRING ] S* ]? _SQUARE_CLOSE'); | |||
| 314 | 4 | 17 | $self->add_lex_rule('pseudo', '_COLON [ IDENT | FUNCTION S* IDENT? S* _ROUND_CLOSE ]'); | |||
| 315 | 4 | 16 | $self->add_lex_rule('declaration', 'property _COLON S* expr prio? | '); | |||
| 316 | 4 | 15 | $self->add_lex_rule('prio', 'IMPORTANT_SYM S*'); | |||
| 317 | ||||||
| 318 | ||||||
| 319 | ##expr | |||||
| 320 | # : term [ operator term ]* | |||||
| 321 | # ; | |||||
| 322 | #term | |||||
| 323 | # : unary_operator? | |||||
| 324 | # [ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* | | |||||
| 325 | # TIME S* | FREQ S* ] | |||||
| 326 | # | STRING S* | IDENT S* | URI S* | hexcolor | function | |||||
| 327 | # ; | |||||
| 328 | #function | |||||
| 329 | # : FUNCTION S* expr ')' S* | |||||
| 330 | # ; | |||||
| 331 | #hexcolor | |||||
| 332 | # : HASH S* | |||||
| 333 | # ; | |||||
| 334 | ||||||
| 335 | 4 | 16 | $self->add_lex_rule('expr', 'term [ operator term ]*'); | |||
| 336 | 4 | 18 | $self->add_lex_rule('term', 'unary_operator? [ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* | TIME S* | FREQ S* ] '. | |||
| 337 | '| STRING S* | IDENT S* | URI S* | hexcolor | function'); | |||||
| 338 | 4 | 16 | $self->add_lex_rule('function', 'FUNCTION S* expr _ROUND_CLOSE S*'); | |||
| 339 | 4 | 16 | $self->add_lex_rule('hexcolor', 'HASH S*'); | |||
| 340 | ||||||
| 341 | ||||||
| 342 | ##################################################################################### | |||||
| 343 | ||||||
| 344 | 4 | 33 | $self->set_base('stylesheet'); | |||
| 345 | } | |||||
| 346 | ||||||
| 347 | sub toke { | |||||
| 348 | 3 | 19 | my ($self, $input) = @_; | |||
| 349 | ||||||
| 350 | # strip comments first | |||||
| 351 | 3 | 9 | $input =~ s!/\*[^*]*\*+([^/*][^*]*\*+)*/! !g; | |||
| 352 | ||||||
| 353 | 3 | 27 | $self->SUPER::toke($input); | |||
| 354 | } | |||||
| 355 | ||||||
| 356 | 1; | |||||