%{ #include #include #include #include "stylesheet.h" int stylelex(); int styleerror(); %} %union { char *str; double num; SSTerm *term; SSExpr *expr; SSDeclaration *decl; SSDeclarationSet *declset; SSSimpleSelector *simpleselector; SSSelector *selector; SSSelectorSet *selectorset; SSID id; } %token IMPORT_SYM IMPORTANT_SYM IDENT STRING NUMBER PERCENTAGE %token LENGTH_PT LENGTH_MM LENGTH_CM LENGTH_PC LENGTH_IN LENGTH_PX %token EMS EXS %token LINK_PSCLASS_AFTER_IDENT VISITED_PSCLASS_AFTER_IDENT %token ACTIVE_PSCLASS_AFTER_IDENT %token FIRST_LINE_AFTER_IDENT %token FIRST_LETTER_AFTER_IDENT %token HASH_AFTER_IDENT CLASS_AFTER_IDENT %token LINK_PSCLASS %token VISITED_PSCLASS %token ACTIVE_PSCLASS %token FIRST_LINE FIRST_LETTER %token HASH CLASS %token URL RGB %token CDO CDC %type IDENT CLASS CLASS_AFTER_IDENT %type solitary_id id id01 %type solitary_class class class01 %type HASH HASH_AFTER_IDENT hexcolor %type STRING URL RGB strorurl %type pseudo_element solitary_pseudo_element pebase %type pseudo_class solitary_pseudo_class pseudo_class01 %type NUMBER PERCENTAGE EMS EXS %type LENGTH_PT LENGTH_MM LENGTH_CM LENGTH_PC LENGTH_IN LENGTH_PX %type term_base term %type expr %type declaration; %type declarations %type simple_selector simple_selectors %type selector %type selectors %% stylesheet : cdo_cdcs imports rulesets | cdo_cdcs imports | cdo_cdcs rulesets | cdo_cdcs | imports rulesets | rulesets | imports | ; rulesets : ruleset1 | rulesets ruleset1 ; imports : import1 | imports import1 ; import1 : import | import cdo_cdcs ; import : IMPORT_SYM strorurl ';' /* E.g., @import url(fun.css); */ ; ruleset1 : ruleset | ruleset cdo_cdcs ; strorurl : STRING | URL ; cdo_cdcs : cdo_cdc | cdo_cdcs cdo_cdc ; cdo_cdc : CDO | CDC ; ruleset : selectors '{' declarations '}' { stylesheet_add($1, $3); } ; declarations : declaration { $$ = declarationset_new($1); } | declarations ';' declaration { $$ = declarationset_new($3); $$->next = $1; } ; selectors : selector { $$ = selectorset_new($1); } | selectors ',' selector { $$ = selectorset_new($3); $$->next = $1; } selector : simple_selectors { $$ = selector_new($1, 0); } | simple_selectors pebase { $$ = selector_new($1, $2); } | solitary_pseudo_element { $$ = selector_new(NULL, $1); } ; /* An "id" is an ID that is attached to an element type ** on its left, as in: P#p007 ** A "solitary_id" is an ID that is not so attached, ** as in: #p007 ** Analogously for classes and pseudo-classes. */ pebase : pseudo_element { $$ = $1; } | solitary_pseudo_element { $$ = $1; } ; simple_selectors : simple_selector { $$ = $1; } | simple_selectors simple_selector { $2->next = $1; $$ = $2; } ; simple_selector : IDENT id01 class01 pseudo_class01 /* eg: H1.subject */ { $$ = simpleselector_new($1, $2, $3, $4); } | solitary_id class01 pseudo_class01 /* eg: #xyz33 */ { $$ = simpleselector_new(None, $1, $2, $3); } | solitary_class pseudo_class01 /* eg: .author */ { $$ = simpleselector_new(None, None, $1, $2); } | solitary_pseudo_class /* eg: :link */ { $$ = simpleselector_new(None, None, None, $1); } ; pseudo_class01 : pseudo_class { $$ = $1; } | { $$ = 0; } ; pseudo_class /* as in: A:link */ : LINK_PSCLASS_AFTER_IDENT { $$ = 1; } | VISITED_PSCLASS_AFTER_IDENT { $$ = 2; } | ACTIVE_PSCLASS_AFTER_IDENT { $$ = 3; } ; solitary_pseudo_class /* as in: :link */ : LINK_PSCLASS { $$ = 1; } | VISITED_PSCLASS { $$ = 2; } | ACTIVE_PSCLASS { $$ = 3; } ; class01 : { $$ = None; } | class { $$ = $1; } ; class /* as in: P.note */ : CLASS_AFTER_IDENT { $$ = $1; } ; solitary_class /* as in: .note */ : CLASS { $$ = $1; } ; pseudo_element /* as in: P:first-line */ : FIRST_LETTER_AFTER_IDENT { $$ = 1; } | FIRST_LINE_AFTER_IDENT { $$ = 2; } ; solitary_pseudo_element /* as in: :first-line */ : FIRST_LETTER { $$ = 1; } | FIRST_LINE { $$ = 2; } ; /* There is a constraint on the id and solitary_id that the ** part after the "#" must be a valid HTML ID value; ** e.g., "#x77" is OK, but "#77" is not. */ id01 : id { $$ = $1; } | /* empty */ { $$ = None; } ; id : HASH_AFTER_IDENT { $$ = StringToSSID($1); free($1); } ; solitary_id : HASH { $$ = StringToSSID($1); free($1); } ; declaration : IDENT ':' expr prio { $$ = declaration_new($1, $3, 1); } | IDENT ':' expr { $$ = declaration_new($1, $3, 0); } | /* empty */ { $$ = declaration_new(None, NULL, 0); } /* Prevents syntax errors... */ ; prio : IMPORTANT_SYM /* !important */ ; /* operator : '/' | ',' | ; expr : term | expr operator term ; */ expr : term { $$ = $1; } ; term : '-' term_base { switch($2->type) { case SSTERM_NUMBER: case SSTERM_PERCENTAGE: case SSTERM_LENGTH_PT: case SSTERM_LENGTH_MM: case SSTERM_LENGTH_CM: case SSTERM_LENGTH_PC: case SSTERM_LENGTH_IN: case SSTERM_LENGTH_PX: case SSTERM_EMS: case SSTERM_EXS: $2->num = -$2->num; break; case SSTERM_STRING: case SSTERM_IDENT: case SSTERM_HEXCOLOR: case SSTERM_URL: case SSTERM_RGB: break; } $$ = $2; } | '+' term_base { $$ = $2; } | term_base { $$ = $1; } ; term_base : NUMBER { $$ = term_new(SSTERM_NUMBER); $$->num = $1; } | STRING { $$ = term_new(SSTERM_STRING); $$->str = $1; } | PERCENTAGE { $$ = term_new(SSTERM_PERCENTAGE); $$->num = $1; } | LENGTH_PT { $$ = term_new(SSTERM_LENGTH_PT); $$->num = $1; } | LENGTH_MM { $$ = term_new(SSTERM_LENGTH_MM); $$->num = $1; } | LENGTH_CM { $$ = term_new(SSTERM_LENGTH_CM); $$->num = $1; } | LENGTH_PC { $$ = term_new(SSTERM_LENGTH_PC); $$->num = $1; } | LENGTH_IN { $$ = term_new(SSTERM_LENGTH_IN); $$->num = $1; } | LENGTH_PX { $$ = term_new(SSTERM_LENGTH_PX); $$->num = $1; } | EMS { $$ = term_new(SSTERM_EMS); $$->num = $1; } | EXS { $$ = term_new(SSTERM_EXS); $$->num = $1; } | IDENT { $$ = term_new(SSTERM_IDENT); $$->id = $1; } | hexcolor { $$ = term_new(SSTERM_HEXCOLOR); $$->str = $1; } | URL { $$ = term_new(SSTERM_URL); $$->str = $1; } | RGB { $$ = term_new(SSTERM_RGB); $$->str = $1; } ; /* There is a constraint on the color that it must ** have either 3 or 6 hex-digits (i.e., [0-9a-fA-F]) ** after the "#"; e.g., "#000" is OK, but "#abcd" is not. */ hexcolor : HASH | HASH_AFTER_IDENT ; %% int style_lineno; StyleSheetList base_sheet; extern FILE *stylein; extern char *styletext; int styleparse(); int style_readstyle(FILE *fp, StyleSheetList *ss) { int ret; stylein = fp; style_lineno = 1; base_sheet = *ss; #ifdef DEBUG fprintf(stderr, "parse start!\n"); #endif if ((ret = styleparse())) { fprintf(stderr, "errer while reading style sheet\n"); } *ss = base_sheet; return ret; } int styleerror(char *msg) { fprintf(stderr,"%d: %s at '%s'\n", style_lineno, msg, styletext); return 0; } int stylewrap(void) { return 1; }