-- -- This file is part of FactorCSS -- Licensed under the MIT License, -- http://www.opensource.org/licenses/mit-license -- Copyright 2004 James Bursa -- -- Parser for CSS 2.1 -- See CSS 2.1 G.2 { module Parser where import Tokeniser import CSS } %name parser %tokentype { TokenPosn } %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 :: [TokenPosn] -> a happyError tks = error ("Parse error at " ++ lcn) where lcn = case tks of [] -> "end of file" tk:_ -> "line " ++ show l ++ ", column " ++ show c where AlexPn _ l c = snd tk }