-- Parser for CSS 2.1 -- See CSS 2.1 G.2 { module Parser where import Tokeniser import CSS } %name parser %tokentype { Token } %token INCLUDES { INCLUDES } DASHMATCH { DASHMATCH } LBRACE { LBRACE } PLUS { PLUS } GREATER { GREATER } COMMA { COMMA } STRING { STRING $$ } IDENT { IDENT $$ } HASH { HASH $$ } IMPORT_SYM { IMPORT_SYM } PAGE_SYM { PAGE_SYM } MEDIA_SYM { MEDIA_SYM } CHARSET_SYM { CHARSET_SYM } IMPORTANT_SYM { IMPORTANT_SYM } EMS { EMS $$ } EXS { EXS $$ } LENGTH { LENGTH $$ } ANGLE { ANGLE $$ } TIME { TIME $$ } FREQ { FREQ $$ } DIMEN { DIMEN $$ } PERCENTAGE { PERCENTAGE $$ } NUMBER { NUMBER $$ } URI { URI $$ } FUNCTION { FUNCTION $$ } DELIM { DELIM $$ } SEMI { SEMI } RBRACE { RBRACE } COLON { COLON } SLASH { SLASH } MINUS { MINUS } DOT { DOT } LBRAC { LBRAC } RBRAC { RBRAC } ASTERISK { ASTERISK } EQUALS { EQUALS } RPAREN { RPAREN } %% stylesheet :: { Stylesheet } : charset import_list statement_list { Stylesheet $1 $2 $3 } charset :: { Maybe String } : { Nothing } | CHARSET_SYM STRING SEMI { Just $2 } import_list :: { [(String, [String])] } : { [] } | import_list import { $2 : $1 } import :: { (String, [String]) } : IMPORT_SYM STRING medium_list SEMI { ($2, $3) } | IMPORT_SYM URI medium_list SEMI { ($2, $3) } statement_list :: { [Statement] } : { [] } | statement_list statement { $2 : $1 } statement :: { Statement } : ruleset { $1 } | media { $1 } | page { $1 } medium_list :: { [String] } : { [] } | medium_list_1 { $1 } medium_list_1 :: { [String] } : medium { [$1] } | medium_list_1 COMMA medium { $3 : $1 } media :: { Statement } : MEDIA_SYM medium_list_1 LBRACE ruleset_list RBRACE { Media $2 $4 } medium :: { String } : IDENT { $1 } ruleset_list :: { [Statement] } : { [] } | ruleset_list ruleset { $2 : $1 } page :: { Statement } : PAGE_SYM LBRACE declaration_list_1 RBRACE { Page Nothing $3 } | PAGE_SYM pseudo_page LBRACE declaration_list_1 RBRACE { Page (Just $2) $4 } declaration_list_1 :: { [Declaration] } : { [] } | declaration { [$1] } | declaration_list_1 SEMI { $1 } | declaration_list_1 SEMI declaration { $3 : $1 } pseudo_page :: { String } : COLON IDENT { $2 } ruleset :: { Statement } : selector_list_1 LBRACE declaration_list_1 RBRACE { Ruleset $1 $3 } selector_list_1 :: { [Selector] } : selector { [$1] } | selector_list_1 COMMA selector { $3 : $1 } selector :: { Selector } : simple_selector { [($1, NoMore)] } | simple_selector combinator selector { ($1, $2) : $3 } combinator :: { Combinator } : { Ancestor } | PLUS { Preceded } | GREATER { Parent } simple_selector :: { SimpleSelector } : element_name detail_list_1 { ($1, $2) } | element_name { ($1, []) } | detail_list_1 { (Nothing, $1) } element_name :: { Maybe String } : IDENT { Just $1 } | ASTERISK { Nothing } detail_list_1 :: { [Detail] } : HASH { [Id $1] } | class { [$1] } | attrib { [$1] } | pseudo { [$1] } | detail_list_1 HASH { Id $2 : $1 } | detail_list_1 class { $2 : $1 } | detail_list_1 attrib { $2 : $1 } | detail_list_1 pseudo { $2 : $1 } class :: { Detail } : DOT IDENT { Class $2 } attrib :: { Detail } : LBRAC IDENT RBRAC { Attrib $2 } | LBRAC IDENT EQUALS IDENT RBRAC { AttribEq $2 $4 } | LBRAC IDENT EQUALS STRING RBRAC { AttribEq $2 $4 } | LBRAC IDENT INCLUDES IDENT RBRAC { AttribInc $2 $4 } | LBRAC IDENT INCLUDES STRING RBRAC { AttribInc $2 $4 } | LBRAC IDENT DASHMATCH IDENT RBRAC { AttribDM $2 $4 } | LBRAC IDENT DASHMATCH STRING RBRAC { AttribDM $2 $4 } pseudo :: { Detail } : COLON IDENT { Pseudo $2 } | COLON FUNCTION RPAREN { PseudoFunc $2 "" } | COLON FUNCTION IDENT RPAREN { PseudoFunc $2 $3 } declaration :: { Declaration } : property COLON value_list_1 { ($1, $3, False) } | property COLON value_list_1 prio { ($1, $3, True) } property :: { String } : IDENT { $1 } prio :: { Bool } : IMPORTANT_SYM { True } value_list :: { [Value] } : { [] } | value value_list { $1 : $2 } value_list_1 :: { [Value] } : value { [$1] } | value value_list_1 { $1 : $2 } value :: { Value } : NUMBER { Number $1 } | PERCENTAGE { Percentage $1 } | LENGTH { Length $1 } | EMS { Ems $1 } | EXS { Exs $1 } | ANGLE { Angle $1 } | TIME { Time $1 } | FREQ { Freq $1 } | STRING { StringV $1 } | IDENT { Ident $1 } | URI { Uri $1 } | HASH { HexColour $1 } | SLASH { Slash } | COMMA { Comma } | FUNCTION value_list RPAREN { Function $1 $2 } { happyError :: [Token] -> a happyError _ = error "Parse error" }