1/*
2 *  Copyright (C) 2002-2003 Lars Knoll (knoll@kde.org)
3 *  Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
4 *  Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
5 *  Copyright (C) 2008 Eric Seidel <eric@webkit.org>
6 *  Copyright (C) 2012 Intel Corporation. All rights reserved.
7 *
8 *  This library is free software; you can redistribute it and/or
9 *  modify it under the terms of the GNU Lesser General Public
10 *  License as published by the Free Software Foundation; either
11 *  version 2 of the License, or (at your option) any later version.
12 *
13 *  This library is distributed in the hope that it will be useful,
14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 *  Lesser General Public License for more details.
17 *
18 *  You should have received a copy of the GNU Lesser General Public
19 *  License along with this library; if not, write to the Free Software
20 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21 *
22 */
23
24%pure_parser
25
26%parse-param { CSSParser* parser }
27%lex-param { CSSParser* parser }
28
29%union {
30    bool boolean;
31    char character;
32    int integer;
33    double number;
34    CSSParserString string;
35
36    StyleRuleBase* rule;
37    Vector<RefPtr<StyleRuleBase> >* ruleList;
38    CSSParserSelector* selector;
39    Vector<OwnPtr<CSSParserSelector> >* selectorList;
40    CSSSelector::MarginBoxType marginBox;
41    CSSSelector::Relation relation;
42    MediaQuerySet* mediaList;
43    MediaQuery* mediaQuery;
44    MediaQuery::Restrictor mediaQueryRestrictor;
45    MediaQueryExp* mediaQueryExp;
46    CSSParserValue value;
47    CSSParserValueList* valueList;
48    Vector<OwnPtr<MediaQueryExp> >* mediaQueryExpList;
49    StyleKeyframe* keyframe;
50    Vector<RefPtr<StyleKeyframe> >* keyframeRuleList;
51    float val;
52    CSSPropertyID id;
53    CSSParser::Location location;
54}
55
56%{
57
58static inline int cssyyerror(void*, const char*)
59{
60    return 1;
61}
62
63static inline bool isCSSTokenAString(int yytype)
64{
65    switch (yytype) {
66    case IDENT:
67    case STRING:
68    case NTH:
69    case HEX:
70    case IDSEL:
71    case DIMEN:
72    case INVALIDDIMEN:
73    case URI:
74    case FUNCTION:
75    case ANYFUNCTION:
76    case NOTFUNCTION:
77    case CALCFUNCTION:
78    case MINFUNCTION:
79    case MAXFUNCTION:
80    case VAR_DEFINITION:
81    case UNICODERANGE:
82        return true;
83    default:
84        return false;
85    }
86}
87
88%}
89
90#if ENABLE_SHADOW_DOM
91%expect 32
92#else
93%expect 31
94#endif
95
96%nonassoc LOWEST_PREC
97
98%left UNIMPORTANT_TOK
99
100%token WHITESPACE SGML_CD
101%token TOKEN_EOF 0
102
103%token INCLUDES
104%token DASHMATCH
105%token BEGINSWITH
106%token ENDSWITH
107%token CONTAINS
108
109%token <string> STRING
110%right <string> IDENT
111%token <string> NTH
112
113%nonassoc <string> HEX
114%nonassoc <string> IDSEL
115%nonassoc ':'
116%nonassoc '.'
117%nonassoc '['
118%nonassoc <string> '*'
119%nonassoc error
120%left '|'
121
122%token IMPORT_SYM
123%token PAGE_SYM
124%token MEDIA_SYM
125#if ENABLE_CSS3_CONDITIONAL_RULES
126%token SUPPORTS_SYM
127#endif
128%token FONT_FACE_SYM
129#if ENABLE_SHADOW_DOM
130%token HOST_SYM
131#endif
132%token CHARSET_SYM
133%token NAMESPACE_SYM
134%token VARFUNCTION
135%token WEBKIT_RULE_SYM
136%token WEBKIT_DECLS_SYM
137%token WEBKIT_KEYFRAME_RULE_SYM
138%token WEBKIT_KEYFRAMES_SYM
139%token WEBKIT_VALUE_SYM
140%token WEBKIT_MEDIAQUERY_SYM
141%token WEBKIT_SELECTOR_SYM
142%token WEBKIT_REGION_RULE_SYM
143%token WEBKIT_VIEWPORT_RULE_SYM
144#if ENABLE_CSS3_CONDITIONAL_RULES
145%token WEBKIT_SUPPORTS_CONDITION_SYM
146#endif
147#if ENABLE_CSS_SHADERS
148%token WEBKIT_FILTER_RULE_SYM
149#endif
150%token <marginBox> TOPLEFTCORNER_SYM
151%token <marginBox> TOPLEFT_SYM
152%token <marginBox> TOPCENTER_SYM
153%token <marginBox> TOPRIGHT_SYM
154%token <marginBox> TOPRIGHTCORNER_SYM
155%token <marginBox> BOTTOMLEFTCORNER_SYM
156%token <marginBox> BOTTOMLEFT_SYM
157%token <marginBox> BOTTOMCENTER_SYM
158%token <marginBox> BOTTOMRIGHT_SYM
159%token <marginBox> BOTTOMRIGHTCORNER_SYM
160%token <marginBox> LEFTTOP_SYM
161%token <marginBox> LEFTMIDDLE_SYM
162%token <marginBox> LEFTBOTTOM_SYM
163%token <marginBox> RIGHTTOP_SYM
164%token <marginBox> RIGHTMIDDLE_SYM
165%token <marginBox> RIGHTBOTTOM_SYM
166
167%token ATKEYWORD
168
169%token IMPORTANT_SYM
170%token MEDIA_ONLY
171%token MEDIA_NOT
172%token MEDIA_AND
173#if ENABLE_CSS3_CONDITIONAL_RULES
174%token SUPPORTS_NOT
175%token SUPPORTS_AND
176%token SUPPORTS_OR
177#endif
178
179%token <number> REMS
180%token <number> CHS
181%token <number> QEMS
182%token <number> EMS
183%token <number> EXS
184%token <number> PXS
185%token <number> CMS
186%token <number> MMS
187%token <number> INS
188%token <number> PTS
189%token <number> PCS
190%token <number> DEGS
191%token <number> RADS
192%token <number> GRADS
193%token <number> TURNS
194%token <number> MSECS
195%token <number> SECS
196%token <number> HERTZ
197%token <number> KHERTZ
198%token <string> DIMEN
199%token <string> INVALIDDIMEN
200%token <number> PERCENTAGE
201%token <number> FLOATTOKEN
202%token <number> INTEGER
203%token <number> VW
204%token <number> VH
205%token <number> VMIN
206%token <number> VMAX
207%token <number> DPPX
208%token <number> DPI
209%token <number> DPCM
210
211%token <string> URI
212%token <string> FUNCTION
213%token <string> ANYFUNCTION
214#if ENABLE_VIDEO_TRACK
215%token <string> CUEFUNCTION
216#endif
217%token <string> NOTFUNCTION
218%token <string> CALCFUNCTION
219%token <string> MINFUNCTION
220%token <string> MAXFUNCTION
221%token <string> VAR_DEFINITION
222
223%token <string> UNICODERANGE
224
225%type <relation> combinator
226
227%type <rule> charset
228%type <rule> ignored_charset
229%type <rule> ruleset
230%type <rule> media
231%type <rule> import
232%type <rule> namespace
233%type <rule> page
234%type <rule> margin_box
235%type <rule> font_face
236#if ENABLE_SHADOW_DOM
237%type <rule> host
238#endif
239%type <rule> keyframes
240%type <rule> invalid_rule
241%type <rule> save_block
242%type <rule> invalid_at
243%type <rule> rule
244%type <rule> valid_rule
245%type <ruleList> block_rule_list
246%type <ruleList> region_block_rule_list
247%type <rule> block_rule
248%type <rule> block_valid_rule
249%type <rule> region
250#if ENABLE_CSS3_CONDITIONAL_RULES
251%type <rule> supports
252#endif
253#if ENABLE_CSS_DEVICE_ADAPTATION
254%type <rule> viewport
255#endif
256#if ENABLE_CSS_SHADERS
257%type <rule> filter
258#endif
259
260%type <string> maybe_ns_prefix
261
262%type <string> namespace_selector
263
264%type <string> string_or_uri
265%type <string> ident_or_string
266%type <string> medium
267%type <marginBox> margin_sym
268
269%type <string> media_feature
270%type <mediaList> media_list
271%type <mediaList> maybe_media_list
272%type <mediaQuery> media_query
273%type <mediaQueryRestrictor> maybe_media_restrictor
274%type <valueList> maybe_media_value
275%type <mediaQueryExp> media_query_exp
276%type <mediaQueryExpList> media_query_exp_list
277%type <mediaQueryExpList> maybe_and_media_query_exp_list
278
279#if ENABLE_CSS3_CONDITIONAL_RULES
280%type <boolean> supports_condition
281%type <boolean> supports_condition_in_parens
282%type <boolean> supports_negation
283%type <boolean> supports_conjunction
284%type <boolean> supports_disjunction
285%type <boolean> supports_declaration_condition
286%type <boolean> supports_error
287#endif
288
289%type <string> keyframe_name
290%type <keyframe> keyframe_rule
291%type <keyframeRuleList> keyframes_rule
292%type <valueList> key_list
293%type <value> key
294
295%type <id> property
296
297%type <selector> specifier
298%type <selector> specifier_list
299%type <selector> simple_selector
300%type <selector> selector
301%type <selectorList> selector_list
302%type <selectorList> simple_selector_list
303%type <selectorList> region_selector
304%type <selector> selector_with_trailing_whitespace
305%type <selector> class
306%type <selector> attrib
307%type <selector> pseudo
308%type <selector> pseudo_page
309%type <selector> page_selector
310
311%type <boolean> declaration_list
312%type <boolean> decl_list
313%type <boolean> declaration
314%type <boolean> declarations_and_margins
315
316%type <boolean> prio
317
318%type <integer> match
319%type <integer> unary_operator
320%type <integer> maybe_unary_operator
321%type <character> operator
322
323%type <valueList> expr
324%type <value> term
325%type <value> unary_term
326%type <value> function
327%type <value> calc_func_term
328%type <character> calc_func_operator
329%type <valueList> calc_func_expr
330%type <valueList> calc_func_expr_list
331%type <valueList> calc_func_paren_expr
332%type <value> calc_function
333%type <string> min_or_max
334%type <value> min_or_max_function
335
336%type <string> element_name
337%type <string> attr_name
338
339%type <location> error_location
340
341%%
342
343stylesheet:
344    maybe_space maybe_charset maybe_sgml rule_list
345  | webkit_rule maybe_space
346  | webkit_decls maybe_space
347  | webkit_value maybe_space
348  | webkit_mediaquery maybe_space
349  | webkit_selector maybe_space
350  | webkit_keyframe_rule maybe_space
351#if ENABLE_CSS3_CONDITIONAL_RULES
352  | webkit_supports_condition maybe_space
353#endif
354  ;
355
356webkit_rule:
357    WEBKIT_RULE_SYM '{' maybe_space valid_rule maybe_space '}' {
358        parser->m_rule = $4;
359    }
360;
361
362webkit_keyframe_rule:
363    WEBKIT_KEYFRAME_RULE_SYM '{' maybe_space keyframe_rule maybe_space '}' {
364        parser->m_keyframe = $4;
365    }
366;
367
368webkit_decls:
369    WEBKIT_DECLS_SYM '{' maybe_space_before_declaration declaration_list '}' {
370        /* can be empty */
371    }
372;
373
374webkit_value:
375    WEBKIT_VALUE_SYM '{' maybe_space expr '}' {
376        if ($4) {
377            parser->m_valueList = parser->sinkFloatingValueList($4);
378            int oldParsedProperties = parser->m_parsedProperties.size();
379            if (!parser->parseValue(parser->m_id, parser->m_important))
380                parser->rollbackLastProperties(parser->m_parsedProperties.size() - oldParsedProperties);
381            parser->m_valueList = nullptr;
382        }
383    }
384;
385
386webkit_mediaquery:
387     WEBKIT_MEDIAQUERY_SYM WHITESPACE maybe_space media_query '}' {
388         parser->m_mediaQuery = parser->sinkFloatingMediaQuery($4);
389     }
390;
391
392webkit_selector:
393    WEBKIT_SELECTOR_SYM '{' maybe_space selector_list '}' {
394        if ($4) {
395            if (parser->m_selectorListForParseSelector)
396                parser->m_selectorListForParseSelector->adoptSelectorVector(*$4);
397        }
398    }
399;
400
401#if ENABLE_CSS3_CONDITIONAL_RULES
402webkit_supports_condition:
403    WEBKIT_SUPPORTS_CONDITION_SYM '{' maybe_space supports_condition '}' {
404        parser->m_supportsCondition = $4;
405    }
406;
407#endif
408
409maybe_space:
410    /* empty */ %prec UNIMPORTANT_TOK
411  | maybe_space WHITESPACE
412  ;
413
414maybe_sgml:
415    /* empty */
416  | maybe_sgml SGML_CD
417  | maybe_sgml WHITESPACE
418  ;
419
420maybe_charset:
421   /* empty */
422  | charset {
423  }
424  ;
425
426closing_brace:
427    '}'
428  | %prec LOWEST_PREC TOKEN_EOF
429  ;
430
431closing_parenthesis:
432    ')'
433  | %prec LOWEST_PREC TOKEN_EOF
434  ;
435
436charset:
437  CHARSET_SYM maybe_space STRING maybe_space ';' {
438     if (parser->m_styleSheet)
439         parser->m_styleSheet->parserSetEncodingFromCharsetRule($3);
440     if (parser->isExtractingSourceData() && parser->m_currentRuleDataStack->isEmpty() && parser->m_ruleSourceDataResult)
441         parser->addNewRuleToSourceTree(CSSRuleSourceData::createUnknown());
442     $$ = 0;
443  }
444  | CHARSET_SYM error invalid_block {
445  }
446  | CHARSET_SYM error ';' {
447  }
448;
449
450ignored_charset:
451    CHARSET_SYM maybe_space STRING maybe_space ';' {
452        // Ignore any @charset rule not at the beginning of the style sheet.
453        $$ = 0;
454    }
455    | CHARSET_SYM maybe_space ';' {
456        $$ = 0;
457    }
458;
459
460rule_list:
461   /* empty */
462 | rule_list rule maybe_sgml {
463     if ($2 && parser->m_styleSheet)
464         parser->m_styleSheet->parserAppendRule($2);
465 }
466 ;
467
468valid_rule:
469    ruleset
470  | media
471  | page
472  | font_face
473  | keyframes
474  | namespace
475  | import
476  | region
477#if ENABLE_CSS3_CONDITIONAL_RULES
478  | supports
479#endif
480#if ENABLE_SHADOW_DOM
481  | host
482#endif
483#if ENABLE_CSS_DEVICE_ADAPTATION
484  | viewport
485#endif
486#if ENABLE_CSS_SHADERS
487  | filter
488#endif
489  ;
490
491rule:
492    valid_rule {
493        parser->m_hadSyntacticallyValidCSSRule = true;
494    }
495  | ignored_charset
496  | invalid_rule
497  | invalid_at
498  ;
499
500block_rule_list:
501    /* empty */ { $$ = 0; }
502  | block_rule_list block_rule maybe_sgml {
503      $$ = $1;
504      if ($2) {
505          if (!$$)
506              $$ = parser->createRuleList();
507          $$->append($2);
508      }
509  }
510  ;
511
512region_block_rule_list:
513    /* empty */ { $$ = 0; }
514  | region_block_rule_list block_valid_rule maybe_sgml {
515      $$ = $1;
516      if ($2) {
517          if (!$$)
518              $$ = parser->createRuleList();
519          $$->append($2);
520      }
521  }
522  ;
523
524block_valid_rule:
525    ruleset
526  | page
527  | font_face
528  | media
529  | keyframes
530#if ENABLE_CSS3_CONDITIONAL_RULES
531  | supports
532#endif
533#if ENABLE_CSS_DEVICE_ADAPTATION
534  | viewport
535#endif
536#if ENABLE_CSS_SHADERS
537  | filter
538#endif
539  ;
540
541block_rule:
542    block_valid_rule
543  | invalid_rule
544  | invalid_at
545  | namespace
546  | import
547  | region
548  ;
549
550at_import_header_end_maybe_space:
551    maybe_space {
552        parser->markRuleHeaderEnd();
553        parser->markRuleBodyStart();
554    }
555    ;
556
557before_import_rule:
558    /* empty */ {
559        parser->markRuleHeaderStart(CSSRuleSourceData::IMPORT_RULE);
560    }
561    ;
562
563import:
564    before_import_rule IMPORT_SYM at_import_header_end_maybe_space string_or_uri maybe_space maybe_media_list ';' {
565        $$ = parser->createImportRule($4, $6);
566    }
567  | before_import_rule IMPORT_SYM at_import_header_end_maybe_space string_or_uri maybe_space maybe_media_list TOKEN_EOF {
568        $$ = parser->createImportRule($4, $6);
569    }
570  | before_import_rule IMPORT_SYM at_import_header_end_maybe_space string_or_uri maybe_space maybe_media_list invalid_block {
571        $$ = 0;
572        parser->popRuleData();
573    }
574  | before_import_rule IMPORT_SYM error ';' {
575        $$ = 0;
576        parser->popRuleData();
577    }
578  | before_import_rule IMPORT_SYM error invalid_block {
579        $$ = 0;
580        parser->popRuleData();
581    }
582  ;
583
584namespace:
585NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space ';' {
586    parser->addNamespace($3, $4);
587    $$ = 0;
588}
589| NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space invalid_block {
590    $$ = 0;
591}
592| NAMESPACE_SYM error invalid_block {
593    $$ = 0;
594}
595| NAMESPACE_SYM error ';' {
596    $$ = 0;
597}
598;
599
600maybe_ns_prefix:
601/* empty */ { $$.clear(); }
602| IDENT maybe_space { $$ = $1; }
603;
604
605string_or_uri:
606STRING
607| URI
608;
609
610media_feature:
611    IDENT maybe_space {
612        $$ = $1;
613    }
614    ;
615
616maybe_media_value:
617    /*empty*/ {
618        $$ = 0;
619    }
620    | ':' maybe_space expr maybe_space {
621        $$ = $3;
622    }
623    ;
624
625media_query_exp:
626    maybe_media_restrictor maybe_space '(' maybe_space media_feature maybe_space maybe_media_value ')' maybe_space {
627        // If restrictor is specified, media query expression is invalid.
628        // Create empty media query expression and continue parsing media query.
629        if ($1 != MediaQuery::None)
630            $$ = parser->createFloatingMediaQueryExp("", 0);
631        else {
632            $5.lower();
633            $$ = parser->createFloatingMediaQueryExp($5, $7);
634        }
635    }
636    ;
637
638media_query_exp_list:
639    media_query_exp {
640        $$ = parser->createFloatingMediaQueryExpList();
641        $$->append(parser->sinkFloatingMediaQueryExp($1));
642    }
643    | media_query_exp_list maybe_space MEDIA_AND maybe_space media_query_exp {
644        $$ = $1;
645        $$->append(parser->sinkFloatingMediaQueryExp($5));
646    }
647    ;
648
649maybe_and_media_query_exp_list:
650    /*empty*/ {
651        $$ = parser->createFloatingMediaQueryExpList();
652    }
653    | MEDIA_AND maybe_space media_query_exp_list {
654        $$ = $3;
655    }
656    ;
657
658maybe_media_restrictor:
659    /*empty*/ {
660        $$ = MediaQuery::None;
661    }
662    | MEDIA_ONLY {
663        $$ = MediaQuery::Only;
664    }
665    | MEDIA_NOT {
666        $$ = MediaQuery::Not;
667    }
668    ;
669
670media_query:
671    media_query_exp_list {
672        $$ = parser->createFloatingMediaQuery(parser->sinkFloatingMediaQueryExpList($1));
673    }
674    |
675    maybe_media_restrictor maybe_space medium maybe_and_media_query_exp_list {
676        $3.lower();
677        $$ = parser->createFloatingMediaQuery($1, $3, parser->sinkFloatingMediaQueryExpList($4));
678    }
679    ;
680
681maybe_media_list:
682     /* empty */ {
683        $$ = parser->createMediaQuerySet();
684     }
685     | media_list
686     ;
687
688media_list:
689    media_query {
690        $$ = parser->createMediaQuerySet();
691        $$->addMediaQuery(parser->sinkFloatingMediaQuery($1));
692        parser->updateLastMediaLine($$);
693    }
694    | media_list ',' maybe_space media_query {
695        $$ = $1;
696        if ($$) {
697            $$->addMediaQuery(parser->sinkFloatingMediaQuery($4));
698            parser->updateLastMediaLine($$);
699        }
700    }
701    | media_list error {
702        $$ = 0;
703    }
704    ;
705
706at_rule_body_start:
707    /* empty */ {
708        parser->markRuleBodyStart();
709    }
710    ;
711
712before_media_rule:
713    /* empty */ {
714        parser->markRuleHeaderStart(CSSRuleSourceData::MEDIA_RULE);
715    }
716    ;
717
718at_rule_header_end_maybe_space:
719    maybe_space {
720        parser->markRuleHeaderEnd();
721    }
722    ;
723
724media:
725    before_media_rule MEDIA_SYM maybe_space media_list at_rule_header_end '{' at_rule_body_start maybe_space block_rule_list save_block {
726        $$ = parser->createMediaRule($4, $9);
727    }
728    | before_media_rule MEDIA_SYM at_rule_header_end_maybe_space '{' at_rule_body_start maybe_space block_rule_list save_block {
729        $$ = parser->createMediaRule(0, $7);
730    }
731    | before_media_rule MEDIA_SYM at_rule_header_end_maybe_space ';' {
732        $$ = 0;
733        parser->popRuleData();
734    }
735    ;
736
737medium:
738  IDENT maybe_space {
739      $$ = $1;
740  }
741  ;
742
743#if ENABLE_CSS3_CONDITIONAL_RULES
744supports:
745    before_supports_rule SUPPORTS_SYM maybe_space supports_condition at_supports_rule_header_end '{' at_rule_body_start maybe_space block_rule_list save_block {
746        $$ = parser->createSupportsRule($4, $9);
747    }
748    | before_supports_rule SUPPORTS_SYM supports_error {
749        $$ = 0;
750        parser->popRuleData();
751        parser->popSupportsRuleData();
752    }
753    ;
754
755supports_error:
756    error ';'
757    | error invalid_block
758
759before_supports_rule:
760    /* empty */ {
761        parser->markRuleHeaderStart(CSSRuleSourceData::SUPPORTS_RULE);
762        parser->markSupportsRuleHeaderStart();
763    }
764    ;
765
766at_supports_rule_header_end:
767    /* empty */ {
768        parser->markRuleHeaderEnd();
769        parser->markSupportsRuleHeaderEnd();
770    }
771    ;
772
773supports_condition:
774    supports_condition_in_parens
775    | supports_negation
776    | supports_conjunction
777    | supports_disjunction
778    ;
779
780supports_negation:
781    SUPPORTS_NOT maybe_space supports_condition_in_parens {
782        $$ = !$3;
783    }
784    ;
785
786supports_conjunction:
787    supports_condition_in_parens SUPPORTS_AND maybe_space supports_condition_in_parens {
788        $$ = $1 && $4;
789    }
790    | supports_conjunction SUPPORTS_AND maybe_space supports_condition_in_parens {
791        $$ = $1 && $4;
792    }
793    ;
794
795supports_disjunction:
796    supports_condition_in_parens SUPPORTS_OR maybe_space supports_condition_in_parens {
797        $$ = $1 || $4;
798    }
799    | supports_disjunction SUPPORTS_OR maybe_space supports_condition_in_parens {
800        $$ = $1 || $4;
801    }
802    ;
803
804supports_condition_in_parens:
805    '(' maybe_space supports_condition ')' maybe_space {
806        $$ = $3;
807    }
808    | supports_declaration_condition
809    | '(' error ')'
810    ;
811
812supports_declaration_condition:
813    '(' maybe_space property ':' maybe_space expr prio ')' maybe_space {
814        $$ = false;
815        CSSParser* p = static_cast<CSSParser*>(parser);
816        if ($3 && $6) {
817            p->m_valueList = p->sinkFloatingValueList($6);
818            int oldParsedProperties = p->m_parsedProperties.size();
819            $$ = p->parseValue(static_cast<CSSPropertyID>($3), $7);
820            // We just need to know if the declaration is supported as it is written. Rollback any additions.
821            if ($$)
822                p->rollbackLastProperties(p->m_parsedProperties.size() - oldParsedProperties);
823            p->m_valueList = nullptr;
824        }
825        p->markPropertyEnd($7, false);
826    }
827    ;
828#endif
829
830before_keyframes_rule:
831    /* empty */ {
832        parser->markRuleHeaderStart(CSSRuleSourceData::KEYFRAMES_RULE);
833    }
834    ;
835
836keyframes:
837    before_keyframes_rule WEBKIT_KEYFRAMES_SYM maybe_space keyframe_name at_rule_header_end_maybe_space '{' at_rule_body_start maybe_space keyframes_rule closing_brace {
838        $$ = parser->createKeyframesRule($4, parser->sinkFloatingKeyframeVector($9));
839    }
840    ;
841
842keyframe_name:
843    IDENT
844    | STRING
845    ;
846
847keyframes_rule:
848    /* empty */ { $$ = parser->createFloatingKeyframeVector(); }
849    | keyframes_rule keyframe_rule maybe_space {
850        $$ = $1;
851        if ($2)
852            $$->append($2);
853    }
854    ;
855
856keyframe_rule:
857    key_list maybe_space '{' maybe_space declaration_list closing_brace {
858        $$ = parser->createKeyframe($1);
859    }
860    ;
861
862key_list:
863    key {
864        $$ = parser->createFloatingValueList();
865        $$->addValue(parser->sinkFloatingValue($1));
866    }
867    | key_list maybe_space ',' maybe_space key {
868        $$ = $1;
869        if ($$)
870            $$->addValue(parser->sinkFloatingValue($5));
871    }
872    ;
873
874key:
875    maybe_unary_operator PERCENTAGE { $$.id = 0; $$.isInt = false; $$.fValue = $1 * $2; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
876    | IDENT {
877        $$.id = 0; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_NUMBER;
878        CSSParserString& str = $1;
879        if (str.equalIgnoringCase("from"))
880            $$.fValue = 0;
881        else if (str.equalIgnoringCase("to"))
882            $$.fValue = 100;
883        else {
884            $$.unit = 0;
885            YYERROR;
886        }
887    }
888    | error {
889        $$.unit = 0;
890    }
891    ;
892
893before_page_rule:
894    /* empty */ {
895        parser->markRuleHeaderStart(CSSRuleSourceData::PAGE_RULE);
896    }
897    ;
898
899page:
900    before_page_rule PAGE_SYM maybe_space page_selector at_rule_header_end_maybe_space
901    '{' at_rule_body_start maybe_space_before_declaration declarations_and_margins closing_brace {
902        if ($4)
903            $$ = parser->createPageRule(parser->sinkFloatingSelector($4));
904        else {
905            // Clear properties in the invalid @page rule.
906            parser->clearProperties();
907            // Also clear margin at-rules here once we fully implement margin at-rules parsing.
908            $$ = 0;
909            parser->popRuleData();
910        }
911    }
912    | before_page_rule PAGE_SYM error invalid_block {
913      parser->popRuleData();
914      $$ = 0;
915    }
916    | before_page_rule PAGE_SYM error ';' {
917      parser->popRuleData();
918      $$ = 0;
919    }
920    ;
921
922page_selector:
923    IDENT {
924        $$ = parser->createFloatingSelectorWithTagName(QualifiedName(nullAtom, $1, parser->m_defaultNamespace));
925        $$->setForPage();
926    }
927    | IDENT pseudo_page {
928        $$ = $2;
929        if ($$) {
930            $$->prependTagSelector(QualifiedName(nullAtom, $1, parser->m_defaultNamespace));
931            $$->setForPage();
932        }
933    }
934    | pseudo_page {
935        $$ = $1;
936        if ($$)
937            $$->setForPage();
938    }
939    | /* empty */ {
940        $$ = parser->createFloatingSelector();
941        $$->setForPage();
942    }
943    ;
944
945declarations_and_margins:
946    declaration_list
947    | declarations_and_margins margin_box maybe_space declaration_list
948    ;
949
950margin_box:
951    margin_sym {
952        parser->startDeclarationsForMarginBox();
953    } maybe_space '{' maybe_space declaration_list closing_brace {
954        $$ = parser->createMarginAtRule($1);
955    }
956    ;
957
958margin_sym :
959    TOPLEFTCORNER_SYM {
960        $$ = CSSSelector::TopLeftCornerMarginBox;
961    }
962    | TOPLEFT_SYM {
963        $$ = CSSSelector::TopLeftMarginBox;
964    }
965    | TOPCENTER_SYM {
966        $$ = CSSSelector::TopCenterMarginBox;
967    }
968    | TOPRIGHT_SYM {
969        $$ = CSSSelector::TopRightMarginBox;
970    }
971    | TOPRIGHTCORNER_SYM {
972        $$ = CSSSelector::TopRightCornerMarginBox;
973    }
974    | BOTTOMLEFTCORNER_SYM {
975        $$ = CSSSelector::BottomLeftCornerMarginBox;
976    }
977    | BOTTOMLEFT_SYM {
978        $$ = CSSSelector::BottomLeftMarginBox;
979    }
980    | BOTTOMCENTER_SYM {
981        $$ = CSSSelector::BottomCenterMarginBox;
982    }
983    | BOTTOMRIGHT_SYM {
984        $$ = CSSSelector::BottomRightMarginBox;
985    }
986    | BOTTOMRIGHTCORNER_SYM {
987        $$ = CSSSelector::BottomRightCornerMarginBox;
988    }
989    | LEFTTOP_SYM {
990        $$ = CSSSelector::LeftTopMarginBox;
991    }
992    | LEFTMIDDLE_SYM {
993        $$ = CSSSelector::LeftMiddleMarginBox;
994    }
995    | LEFTBOTTOM_SYM {
996        $$ = CSSSelector::LeftBottomMarginBox;
997    }
998    | RIGHTTOP_SYM {
999        $$ = CSSSelector::RightTopMarginBox;
1000    }
1001    | RIGHTMIDDLE_SYM {
1002        $$ = CSSSelector::RightMiddleMarginBox;
1003    }
1004    | RIGHTBOTTOM_SYM {
1005        $$ = CSSSelector::RightBottomMarginBox;
1006    }
1007    ;
1008
1009before_font_face_rule:
1010    /* empty */ {
1011        parser->markRuleHeaderStart(CSSRuleSourceData::FONT_FACE_RULE);
1012    }
1013    ;
1014
1015font_face:
1016    before_font_face_rule FONT_FACE_SYM at_rule_header_end_maybe_space
1017    '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace {
1018        $$ = parser->createFontFaceRule();
1019    }
1020    | before_font_face_rule FONT_FACE_SYM error invalid_block {
1021      $$ = 0;
1022      parser->popRuleData();
1023    }
1024    | before_font_face_rule FONT_FACE_SYM error ';' {
1025      $$ = 0;
1026      parser->popRuleData();
1027    }
1028;
1029
1030#if ENABLE_SHADOW_DOM
1031before_host_rule:
1032    /* empty */ {
1033        parser->markRuleHeaderStart(CSSRuleSourceData::HOST_RULE);
1034    }
1035    ;
1036
1037host:
1038    before_host_rule HOST_SYM at_rule_header_end_maybe_space
1039    '{' at_rule_body_start maybe_space block_rule_list save_block {
1040        $$ = parser->createHostRule($7);
1041    }
1042    | before_host_rule HOST_SYM at_rule_header_end_maybe_space ';' {
1043        $$ = 0;
1044        parser->popRuleData();
1045    }
1046    ;
1047#endif
1048
1049#if ENABLE_CSS_DEVICE_ADAPTATION
1050before_viewport_rule:
1051    /* empty */ {
1052        parser->markViewportRuleBodyStart();
1053        parser->markRuleHeaderStart(CSSRuleSourceData::VIEWPORT_RULE);
1054    }
1055    ;
1056
1057viewport:
1058    before_viewport_rule WEBKIT_VIEWPORT_RULE_SYM at_rule_header_end_maybe_space
1059    '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace {
1060        $$ = parser->createViewportRule();
1061        parser->markViewportRuleBodyEnd();
1062    }
1063    | before_viewport_rule WEBKIT_VIEWPORT_RULE_SYM error invalid_block {
1064        $$ = 0;
1065        parser->popRuleData();
1066        parser->markViewportRuleBodyEnd();
1067    }
1068    | before_viewport_rule WEBKIT_VIEWPORT_RULE_SYM error ';' {
1069        $$ = 0;
1070        parser->popRuleData();
1071        parser->markViewportRuleBodyEnd();
1072    }
1073;
1074#endif
1075
1076region_selector:
1077    selector_list {
1078        if ($1) {
1079            parser->setReusableRegionSelectorVector($1);
1080            $$ = parser->reusableRegionSelectorVector();
1081        }
1082        else
1083            $$ = 0;
1084    }
1085;
1086
1087before_region_rule:
1088    /* empty */ {
1089        parser->markRuleHeaderStart(CSSRuleSourceData::REGION_RULE);
1090    }
1091    ;
1092
1093region:
1094    before_region_rule WEBKIT_REGION_RULE_SYM WHITESPACE region_selector at_rule_header_end '{' at_rule_body_start maybe_space region_block_rule_list save_block {
1095        if ($4)
1096            $$ = parser->createRegionRule($4, $9);
1097        else {
1098            $$ = 0;
1099            parser->popRuleData();
1100        }
1101    }
1102;
1103
1104#if ENABLE_CSS_SHADERS
1105before_filter_rule:
1106    /* empty */ {
1107        parser->markRuleHeaderStart(CSSRuleSourceData::FILTER_RULE);
1108        parser->m_inFilterRule = true;
1109    }
1110    ;
1111
1112filter:
1113    before_filter_rule WEBKIT_FILTER_RULE_SYM WHITESPACE IDENT at_rule_header_end_maybe_space
1114    '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace {
1115        parser->m_inFilterRule = false;
1116        $$ = parser->createFilterRule($4);
1117    }
1118    ;
1119#endif
1120
1121combinator:
1122    '+' maybe_space { $$ = CSSSelector::DirectAdjacent; }
1123  | '~' maybe_space { $$ = CSSSelector::IndirectAdjacent; }
1124  | '>' maybe_space { $$ = CSSSelector::Child; }
1125  ;
1126
1127maybe_unary_operator:
1128    unary_operator { $$ = $1; }
1129    | { $$ = 1; }
1130    ;
1131
1132unary_operator:
1133    '-' { $$ = -1; }
1134  | '+' { $$ = 1; }
1135  ;
1136
1137maybe_space_before_declaration:
1138    maybe_space {
1139        parser->markPropertyStart();
1140    }
1141  ;
1142
1143before_selector_list:
1144    /* empty */ {
1145        parser->markRuleHeaderStart(CSSRuleSourceData::STYLE_RULE);
1146        parser->markSelectorStart();
1147    }
1148  ;
1149
1150at_rule_header_end:
1151    /* empty */ {
1152        parser->markRuleHeaderEnd();
1153    }
1154  ;
1155
1156at_selector_end:
1157    /* empty */ {
1158        parser->markSelectorEnd();
1159    }
1160  ;
1161
1162ruleset:
1163    before_selector_list selector_list at_selector_end at_rule_header_end '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace {
1164        $$ = parser->createStyleRule($2);
1165    }
1166  ;
1167
1168before_selector_group_item:
1169    /* empty */ {
1170        parser->markSelectorStart();
1171    }
1172
1173selector_list:
1174    selector %prec UNIMPORTANT_TOK {
1175        if ($1) {
1176            $$ = parser->reusableSelectorVector();
1177            $$->shrink(0);
1178            $$->append(parser->sinkFloatingSelector($1));
1179            parser->updateLastSelectorLineAndPosition();
1180        }
1181    }
1182    | selector_list at_selector_end ',' maybe_space before_selector_group_item selector %prec UNIMPORTANT_TOK {
1183        if ($1 && $6) {
1184            $$ = $1;
1185            $$->append(parser->sinkFloatingSelector($6));
1186            parser->updateLastSelectorLineAndPosition();
1187        } else
1188            $$ = 0;
1189    }
1190  | selector_list error {
1191        $$ = 0;
1192    }
1193   ;
1194
1195selector_with_trailing_whitespace:
1196    selector WHITESPACE {
1197        $$ = $1;
1198    }
1199    ;
1200
1201selector:
1202    simple_selector {
1203        $$ = $1;
1204    }
1205    | selector_with_trailing_whitespace
1206    {
1207        $$ = $1;
1208    }
1209    | selector_with_trailing_whitespace simple_selector
1210    {
1211        $$ = $2;
1212        if (!$1)
1213            $$ = 0;
1214        else if ($$)
1215            $$->appendTagHistory(CSSSelector::Descendant, parser->sinkFloatingSelector($1));
1216    }
1217    | selector combinator simple_selector {
1218        $$ = $3;
1219        if (!$1)
1220            $$ = 0;
1221        else if ($$)
1222            $$->appendTagHistory($2, parser->sinkFloatingSelector($1));
1223    }
1224    | selector error {
1225        $$ = 0;
1226    }
1227    ;
1228
1229namespace_selector:
1230    /* empty */ '|' { $$.clear(); }
1231    | '*' '|' { static LChar star = '*'; $$.init(&star, 1); }
1232    | IDENT '|' { $$ = $1; }
1233;
1234
1235simple_selector:
1236    element_name {
1237        $$ = parser->createFloatingSelectorWithTagName(QualifiedName(nullAtom, $1, parser->m_defaultNamespace));
1238    }
1239    | element_name specifier_list {
1240        $$ = $2;
1241        if ($$)
1242            $$ = parser->rewriteSpecifiersWithElementName(nullAtom, $1, $$);
1243    }
1244    | specifier_list {
1245        $$ = $1;
1246        if ($$)
1247            $$ = parser->rewriteSpecifiersWithNamespaceIfNeeded($$);
1248    }
1249    | namespace_selector element_name {
1250        $$ = parser->createFloatingSelectorWithTagName(parser->determineNameInNamespace($1, $2));
1251    }
1252    | namespace_selector element_name specifier_list {
1253        $$ = $3;
1254        if ($$)
1255            $$ = parser->rewriteSpecifiersWithElementName($1, $2, $$);
1256    }
1257    | namespace_selector specifier_list {
1258        $$ = $2;
1259        if ($$)
1260            $$ = parser->rewriteSpecifiersWithElementName($1, starAtom, $$);
1261    }
1262  ;
1263
1264simple_selector_list:
1265    simple_selector %prec UNIMPORTANT_TOK {
1266        if ($1) {
1267            $$ = parser->createFloatingSelectorVector();
1268            $$->append(parser->sinkFloatingSelector($1));
1269        } else
1270            $$ = 0;
1271    }
1272    | simple_selector_list maybe_space ',' maybe_space simple_selector %prec UNIMPORTANT_TOK {
1273        if ($1 && $5) {
1274            $$ = $1;
1275            $$->append(parser->sinkFloatingSelector($5));
1276        } else
1277            $$ = 0;
1278    }
1279    | simple_selector_list error {
1280        $$ = 0;
1281    }
1282  ;
1283
1284element_name:
1285    IDENT {
1286        CSSParserString& str = $1;
1287        if (parser->m_context.isHTMLDocument)
1288            str.lower();
1289        $$ = str;
1290    }
1291    | '*' {
1292        static LChar star = '*';
1293        $$.init(&star, 1);
1294    }
1295  ;
1296
1297specifier_list:
1298    specifier {
1299        $$ = $1;
1300    }
1301    | specifier_list specifier {
1302        if (!$2)
1303            $$ = 0;
1304        else if ($1)
1305            $$ = parser->rewriteSpecifiers($1, $2);
1306    }
1307    | specifier_list error {
1308        $$ = 0;
1309    }
1310;
1311
1312specifier:
1313    IDSEL {
1314        $$ = parser->createFloatingSelector();
1315        $$->setMatch(CSSSelector::Id);
1316        if (parser->m_context.mode == CSSQuirksMode)
1317            $1.lower();
1318        $$->setValue($1);
1319    }
1320  | HEX {
1321        if ($1[0] >= '0' && $1[0] <= '9') {
1322            $$ = 0;
1323        } else {
1324            $$ = parser->createFloatingSelector();
1325            $$->setMatch(CSSSelector::Id);
1326            if (parser->m_context.mode == CSSQuirksMode)
1327                $1.lower();
1328            $$->setValue($1);
1329        }
1330    }
1331  | class
1332  | attrib
1333  | pseudo
1334    ;
1335
1336class:
1337    '.' IDENT {
1338        $$ = parser->createFloatingSelector();
1339        $$->setMatch(CSSSelector::Class);
1340        if (parser->m_context.mode == CSSQuirksMode)
1341            $2.lower();
1342        $$->setValue($2);
1343    }
1344  ;
1345
1346attr_name:
1347    IDENT maybe_space {
1348        CSSParserString& str = $1;
1349        if (parser->m_context.isHTMLDocument)
1350            str.lower();
1351        $$ = str;
1352    }
1353    ;
1354
1355attrib:
1356    '[' maybe_space attr_name ']' {
1357        $$ = parser->createFloatingSelector();
1358        $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
1359        $$->setMatch(CSSSelector::Set);
1360    }
1361    | '[' maybe_space attr_name match maybe_space ident_or_string maybe_space ']' {
1362        $$ = parser->createFloatingSelector();
1363        $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
1364        $$->setMatch((CSSSelector::Match)$4);
1365        $$->setValue($6);
1366    }
1367    | '[' maybe_space namespace_selector attr_name ']' {
1368        $$ = parser->createFloatingSelector();
1369        $$->setAttribute(parser->determineNameInNamespace($3, $4));
1370        $$->setMatch(CSSSelector::Set);
1371    }
1372    | '[' maybe_space namespace_selector attr_name match maybe_space ident_or_string maybe_space ']' {
1373        $$ = parser->createFloatingSelector();
1374        $$->setAttribute(parser->determineNameInNamespace($3, $4));
1375        $$->setMatch((CSSSelector::Match)$5);
1376        $$->setValue($7);
1377    }
1378  ;
1379
1380match:
1381    '=' {
1382        $$ = CSSSelector::Exact;
1383    }
1384    | INCLUDES {
1385        $$ = CSSSelector::List;
1386    }
1387    | DASHMATCH {
1388        $$ = CSSSelector::Hyphen;
1389    }
1390    | BEGINSWITH {
1391        $$ = CSSSelector::Begin;
1392    }
1393    | ENDSWITH {
1394        $$ = CSSSelector::End;
1395    }
1396    | CONTAINS {
1397        $$ = CSSSelector::Contain;
1398    }
1399    ;
1400
1401ident_or_string:
1402    IDENT
1403  | STRING
1404    ;
1405
1406pseudo_page:
1407    ':' IDENT {
1408        $$ = parser->createFloatingSelector();
1409        $$->setMatch(CSSSelector::PagePseudoClass);
1410        $2.lower();
1411        $$->setValue($2);
1412        CSSSelector::PseudoType type = $$->pseudoType();
1413        if (type == CSSSelector::PseudoUnknown)
1414            $$ = 0;
1415    }
1416
1417pseudo:
1418    ':' IDENT {
1419        $$ = parser->createFloatingSelector();
1420        $$->setMatch(CSSSelector::PseudoClass);
1421        $2.lower();
1422        $$->setValue($2);
1423        CSSSelector::PseudoType type = $$->pseudoType();
1424        if (type == CSSSelector::PseudoUnknown)
1425            $$ = 0;
1426    }
1427    | ':' ':' IDENT {
1428        $$ = parser->createFloatingSelector();
1429        $$->setMatch(CSSSelector::PseudoElement);
1430        $3.lower();
1431        $$->setValue($3);
1432        // FIXME: This call is needed to force selector to compute the pseudoType early enough.
1433        CSSSelector::PseudoType type = $$->pseudoType();
1434        if (type == CSSSelector::PseudoUnknown)
1435            $$ = 0;
1436    }
1437#if ENABLE_VIDEO_TRACK
1438    // used by ::cue(:past/:future)
1439    | ':' ':' CUEFUNCTION maybe_space simple_selector_list maybe_space ')' {
1440        if ($5) {
1441            $$ = parser->createFloatingSelector();
1442            $$->setMatch(CSSSelector::PseudoClass);
1443            $$->adoptSelectorVector(*parser->sinkFloatingSelectorVector($5));
1444            $$->setValue($3);
1445            CSSSelector::PseudoType type = $$->pseudoType();
1446            if (type != CSSSelector::PseudoCue)
1447                $$ = 0;
1448        } else
1449            $$ = 0;
1450    }
1451#endif
1452    // use by :-webkit-any.
1453    // FIXME: should we support generic selectors here or just simple_selectors?
1454    // Use simple_selector_list for now to match -moz-any.
1455    // See http://lists.w3.org/Archives/Public/www-style/2010Sep/0566.html for some
1456    // related discussion with respect to :not.
1457    | ':' ANYFUNCTION maybe_space simple_selector_list maybe_space ')' {
1458        if ($4) {
1459            $$ = parser->createFloatingSelector();
1460            $$->setMatch(CSSSelector::PseudoClass);
1461            $$->adoptSelectorVector(*parser->sinkFloatingSelectorVector($4));
1462            $2.lower();
1463            $$->setValue($2);
1464            CSSSelector::PseudoType type = $$->pseudoType();
1465            if (type != CSSSelector::PseudoAny)
1466                $$ = 0;
1467        } else
1468            $$ = 0;
1469    }
1470    // used by :nth-*(ax+b)
1471    | ':' FUNCTION maybe_space NTH maybe_space ')' {
1472        $$ = parser->createFloatingSelector();
1473        $$->setMatch(CSSSelector::PseudoClass);
1474        $$->setArgument($4);
1475        $$->setValue($2);
1476        CSSSelector::PseudoType type = $$->pseudoType();
1477        if (type == CSSSelector::PseudoUnknown)
1478            $$ = 0;
1479    }
1480    // used by :nth-*
1481    | ':' FUNCTION maybe_space maybe_unary_operator INTEGER maybe_space ')' {
1482        $$ = parser->createFloatingSelector();
1483        $$->setMatch(CSSSelector::PseudoClass);
1484        $$->setArgument(String::number($4 * $5));
1485        $$->setValue($2);
1486        CSSSelector::PseudoType type = $$->pseudoType();
1487        if (type == CSSSelector::PseudoUnknown)
1488            $$ = 0;
1489    }
1490    // used by :nth-*(odd/even) and :lang
1491    | ':' FUNCTION maybe_space IDENT maybe_space ')' {
1492        $$ = parser->createFloatingSelector();
1493        $$->setMatch(CSSSelector::PseudoClass);
1494        $$->setArgument($4);
1495        $2.lower();
1496        $$->setValue($2);
1497        CSSSelector::PseudoType type = $$->pseudoType();
1498        if (type == CSSSelector::PseudoUnknown)
1499            $$ = 0;
1500        else if (type == CSSSelector::PseudoNthChild ||
1501                 type == CSSSelector::PseudoNthOfType ||
1502                 type == CSSSelector::PseudoNthLastChild ||
1503                 type == CSSSelector::PseudoNthLastOfType) {
1504            if (!isValidNthToken($4))
1505                $$ = 0;
1506        }
1507    }
1508    // used by :not
1509    | ':' NOTFUNCTION maybe_space simple_selector maybe_space ')' {
1510        if (!$4 || !$4->isSimple())
1511            $$ = 0;
1512        else {
1513            $$ = parser->createFloatingSelector();
1514            $$->setMatch(CSSSelector::PseudoClass);
1515
1516            Vector<OwnPtr<CSSParserSelector> > selectorVector;
1517            selectorVector.append(parser->sinkFloatingSelector($4));
1518            $$->adoptSelectorVector(selectorVector);
1519
1520            $2.lower();
1521            $$->setValue($2);
1522        }
1523    }
1524  ;
1525
1526declaration_list:
1527    /* empty */ { $$ = false; }
1528    | declaration {
1529        $$ = $1;
1530    }
1531    | decl_list declaration {
1532        $$ = $1;
1533        if ( $2 )
1534            $$ = $2;
1535    }
1536    | decl_list {
1537        $$ = $1;
1538    }
1539    | decl_list_recovery {
1540        $$ = false;
1541    }
1542    | decl_list decl_list_recovery {
1543        $$ = $1;
1544    }
1545    ;
1546
1547decl_list:
1548    declaration ';' maybe_space {
1549        parser->markPropertyStart();
1550        $$ = $1;
1551    }
1552    | decl_list_recovery ';' maybe_space {
1553        parser->markPropertyStart();
1554        $$ = false;
1555    }
1556    | decl_list declaration ';' maybe_space {
1557        parser->markPropertyStart();
1558        $$ = $1;
1559        if ($2)
1560            $$ = $2;
1561    }
1562    | decl_list decl_list_recovery ';' maybe_space {
1563        parser->markPropertyStart();
1564        $$ = $1;
1565    }
1566    ;
1567
1568decl_list_recovery:
1569    error error_location error_recovery {
1570        parser->syntaxError($2, CSSParser::PropertyDeclarationError);
1571    }
1572    ;
1573
1574declaration:
1575    VAR_DEFINITION maybe_space ':' maybe_space expr prio {
1576#if ENABLE_CSS_VARIABLES
1577        parser->storeVariableDeclaration($1, parser->sinkFloatingValueList($5), $6);
1578        $$ = true;
1579        parser->markPropertyEnd($6, true);
1580#else
1581        $$ = false;
1582#endif
1583    }
1584    |
1585    property ':' maybe_space expr prio {
1586        $$ = false;
1587        bool isPropertyParsed = false;
1588        if ($1 && $4) {
1589            parser->m_valueList = parser->sinkFloatingValueList($4);
1590            int oldParsedProperties = parser->m_parsedProperties.size();
1591            $$ = parser->parseValue(static_cast<CSSPropertyID>($1), $5);
1592            if (!$$)
1593                parser->rollbackLastProperties(parser->m_parsedProperties.size() - oldParsedProperties);
1594            else
1595                isPropertyParsed = true;
1596            parser->m_valueList = nullptr;
1597        }
1598        parser->markPropertyEnd($5, isPropertyParsed);
1599    }
1600    |
1601    property declaration_recovery {
1602        $$ = false;
1603    }
1604    |
1605    property ':' maybe_space expr prio declaration_recovery {
1606        /* When we encounter something like p {color: red !important fail;} we should drop the declaration */
1607        parser->markPropertyEnd(false, false);
1608        $$ = false;
1609    }
1610    |
1611    IMPORTANT_SYM maybe_space declaration_recovery {
1612        /* Handle this case: div { text-align: center; !important } Just reduce away the stray !important. */
1613        $$ = false;
1614    }
1615    |
1616    property ':' maybe_space declaration_recovery {
1617        /* if we come across rules with invalid values like this case: p { weight: *; }, just discard the rule */
1618        parser->markPropertyEnd(false, false);
1619        $$ = false;
1620    }
1621  ;
1622
1623declaration_recovery:
1624    error error_location error_recovery {
1625        parser->syntaxError($2);
1626    }
1627  ;
1628
1629property:
1630    IDENT maybe_space {
1631        $$ = cssPropertyID($1);
1632    }
1633  ;
1634
1635prio:
1636    IMPORTANT_SYM maybe_space { $$ = true; }
1637    | /* empty */ { $$ = false; }
1638  ;
1639
1640expr:
1641    term {
1642        $$ = parser->createFloatingValueList();
1643        $$->addValue(parser->sinkFloatingValue($1));
1644    }
1645    | expr operator term {
1646        $$ = $1;
1647        if ($$) {
1648            if ($2) {
1649                CSSParserValue v;
1650                v.id = 0;
1651                v.unit = CSSParserValue::Operator;
1652                v.iValue = $2;
1653                $$->addValue(v);
1654            }
1655            $$->addValue(parser->sinkFloatingValue($3));
1656        }
1657    }
1658    | expr expr_recovery {
1659        $$ = 0;
1660    }
1661  ;
1662
1663expr_recovery:
1664    error error_location error_recovery
1665  ;
1666
1667operator:
1668    '/' maybe_space {
1669        $$ = '/';
1670    }
1671  | ',' maybe_space {
1672        $$ = ',';
1673    }
1674  | /* empty */ {
1675        $$ = 0;
1676  }
1677  ;
1678
1679term:
1680  unary_term maybe_space { $$ = $1; }
1681  | unary_operator unary_term maybe_space { $$ = $2; $$.fValue *= $1; }
1682  | STRING maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; }
1683  | IDENT maybe_space {
1684      $$.id = cssValueKeywordID($1);
1685      $$.unit = CSSPrimitiveValue::CSS_IDENT;
1686      $$.string = $1;
1687  }
1688  /* We might need to actually parse the number from a dimension, but we can't just put something that uses $$.string into unary_term. */
1689  | DIMEN maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
1690  | unary_operator DIMEN maybe_space { $$.id = 0; $$.string = $2; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
1691  | URI maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI; }
1692  | UNICODERANGE maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE; }
1693  | HEX maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; }
1694  | '#' maybe_space { $$.id = 0; $$.string = CSSParserString(); $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } /* Handle error case: "color: #;" */
1695  | VARFUNCTION maybe_space IDENT closing_parenthesis maybe_space {
1696#if ENABLE_CSS_VARIABLES
1697      $$.id = 0;
1698      $$.string = $3;
1699      $$.unit = CSSPrimitiveValue::CSS_VARIABLE_NAME;
1700#endif
1701  }
1702  /* FIXME: according to the specs a function can have a unary_operator in front. I know no case where this makes sense */
1703  | function maybe_space {
1704      $$ = $1;
1705  }
1706  | calc_function maybe_space {
1707      $$ = $1;
1708  }
1709  | min_or_max_function maybe_space {
1710      $$ = $1;
1711  }
1712  | '%' maybe_space { /* Handle width: %; */
1713      $$.id = 0; $$.unit = 0;
1714  }
1715  ;
1716
1717unary_term:
1718  INTEGER { $$.id = 0; $$.isInt = true; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
1719  | FLOATTOKEN { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
1720  | PERCENTAGE { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PERCENTAGE; }
1721  | PXS { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PX; }
1722  | CMS { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CM; }
1723  | MMS { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MM; }
1724  | INS { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_IN; }
1725  | PTS { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PT; }
1726  | PCS { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PC; }
1727  | DEGS { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DEG; }
1728  | RADS { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_RAD; }
1729  | GRADS { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_GRAD; }
1730  | TURNS { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_TURN; }
1731  | MSECS { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MS; }
1732  | SECS { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_S; }
1733  | HERTZ { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_HZ; }
1734  | KHERTZ { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_KHZ; }
1735  | EMS { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EMS; }
1736  | QEMS { $$.id = 0; $$.fValue = $1; $$.unit = CSSParserValue::Q_EMS; }
1737  | EXS { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EXS; }
1738  | REMS {
1739      $$.id = 0;
1740      $$.fValue = $1;
1741      $$.unit = CSSPrimitiveValue::CSS_REMS;
1742      if (parser->m_styleSheet)
1743          parser->m_styleSheet->parserSetUsesRemUnits(true);
1744  }
1745  | CHS { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CHS; }
1746  | VW { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_VW; }
1747  | VH { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_VH; }
1748  | VMIN { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_VMIN; }
1749  | VMAX { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_VMAX; }
1750  | DPPX { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DPPX; }
1751  | DPI { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DPI; }
1752  | DPCM { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DPCM; }
1753  ;
1754
1755function:
1756    FUNCTION maybe_space expr closing_parenthesis {
1757        CSSParserFunction* f = parser->createFloatingFunction();
1758        f->name = $1;
1759        f->args = parser->sinkFloatingValueList($3);
1760        $$.id = 0;
1761        $$.unit = CSSParserValue::Function;
1762        $$.function = f;
1763    } |
1764    FUNCTION maybe_space closing_parenthesis {
1765        CSSParserFunction* f = parser->createFloatingFunction();
1766        f->name = $1;
1767        CSSParserValueList* valueList = parser->createFloatingValueList();
1768        f->args = parser->sinkFloatingValueList(valueList);
1769        $$.id = 0;
1770        $$.unit = CSSParserValue::Function;
1771        $$.function = f;
1772    } |
1773    FUNCTION maybe_space expr_recovery closing_parenthesis {
1774        CSSParserFunction* f = parser->createFloatingFunction();
1775        f->name = $1;
1776        f->args = nullptr;
1777        $$.id = 0;
1778        $$.unit = CSSParserValue::Function;
1779        $$.function = f;
1780  }
1781  ;
1782
1783calc_func_term:
1784  unary_term { $$ = $1; }
1785  | VARFUNCTION maybe_space IDENT closing_parenthesis {
1786#if ENABLE_CSS_VARIABLES
1787      $$.id = 0;
1788      $$.string = $3;
1789      $$.unit = CSSPrimitiveValue::CSS_VARIABLE_NAME;
1790#endif
1791  }
1792  | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
1793  ;
1794
1795calc_func_operator:
1796    WHITESPACE '+' WHITESPACE {
1797        $$ = '+';
1798    }
1799    | WHITESPACE '-' WHITESPACE {
1800        $$ = '-';
1801    }
1802    | calc_maybe_space '*' maybe_space {
1803        $$ = '*';
1804    }
1805    | calc_maybe_space '/' maybe_space {
1806        $$ = '/';
1807    }
1808  ;
1809
1810calc_maybe_space:
1811    /* empty */
1812    | WHITESPACE
1813  ;
1814
1815calc_func_paren_expr:
1816    '(' maybe_space calc_func_expr calc_maybe_space closing_parenthesis {
1817        if ($3) {
1818            $$ = $3;
1819            CSSParserValue v;
1820            v.id = 0;
1821            v.unit = CSSParserValue::Operator;
1822            v.iValue = '(';
1823            $$->insertValueAt(0, v);
1824            v.iValue = ')';
1825            $$->addValue(v);
1826        } else
1827            $$ = 0;
1828    }
1829  ;
1830
1831calc_func_expr:
1832    calc_func_term {
1833        $$ = parser->createFloatingValueList();
1834        $$->addValue(parser->sinkFloatingValue($1));
1835    }
1836    | calc_func_expr calc_func_operator calc_func_term {
1837        if ($1 && $2) {
1838            $$ = $1;
1839            CSSParserValue v;
1840            v.id = 0;
1841            v.unit = CSSParserValue::Operator;
1842            v.iValue = $2;
1843            $$->addValue(v);
1844            $$->addValue(parser->sinkFloatingValue($3));
1845        } else
1846            $$ = 0;
1847
1848    }
1849    | calc_func_expr calc_func_operator calc_func_paren_expr {
1850        if ($1 && $2 && $3) {
1851            $$ = $1;
1852            CSSParserValue v;
1853            v.id = 0;
1854            v.unit = CSSParserValue::Operator;
1855            v.iValue = $2;
1856            $$->addValue(v);
1857            $$->extend(*($3));
1858        } else
1859            $$ = 0;
1860    }
1861    | calc_func_paren_expr
1862    | calc_func_expr error {
1863        $$ = 0;
1864    }
1865  ;
1866
1867calc_func_expr_list:
1868    calc_func_expr calc_maybe_space {
1869        $$ = $1;
1870    }
1871    | calc_func_expr_list ',' maybe_space calc_func_expr calc_maybe_space {
1872        if ($1 && $4) {
1873            $$ = $1;
1874            CSSParserValue v;
1875            v.id = 0;
1876            v.unit = CSSParserValue::Operator;
1877            v.iValue = ',';
1878            $$->addValue(v);
1879            $$->extend(*($4));
1880        } else
1881            $$ = 0;
1882    }
1883  ;
1884
1885calc_function:
1886    CALCFUNCTION maybe_space calc_func_expr calc_maybe_space closing_parenthesis {
1887        CSSParserFunction* f = parser->createFloatingFunction();
1888        f->name = $1;
1889        f->args = parser->sinkFloatingValueList($3);
1890        $$.id = 0;
1891        $$.unit = CSSParserValue::Function;
1892        $$.function = f;
1893    }
1894    | CALCFUNCTION maybe_space expr_recovery closing_parenthesis {
1895        YYERROR;
1896    }
1897    ;
1898
1899
1900min_or_max:
1901    MINFUNCTION {
1902        $$ = $1;
1903    }
1904    | MAXFUNCTION {
1905        $$ = $1;
1906    }
1907    ;
1908
1909min_or_max_function:
1910    min_or_max maybe_space calc_func_expr_list closing_parenthesis {
1911        CSSParserFunction* f = parser->createFloatingFunction();
1912        f->name = $1;
1913        f->args = parser->sinkFloatingValueList($3);
1914        $$.id = 0;
1915        $$.unit = CSSParserValue::Function;
1916        $$.function = f;
1917    }
1918    | min_or_max maybe_space expr_recovery closing_parenthesis {
1919        YYERROR;
1920    }
1921    ;
1922
1923/* error handling rules */
1924
1925save_block:
1926    closing_brace {
1927        $$ = 0;
1928    }
1929  | error closing_brace {
1930        $$ = 0;
1931    }
1932    ;
1933
1934invalid_at:
1935    ATKEYWORD error invalid_block {
1936        $$ = 0;
1937    }
1938  | ATKEYWORD error ';' {
1939        $$ = 0;
1940    }
1941    ;
1942
1943invalid_rule:
1944    error invalid_block {
1945        $$ = 0;
1946    }
1947
1948/*
1949  Seems like the two rules below are trying too much and violating
1950  http://www.hixie.ch/tests/evil/mixed/csserrorhandling.html
1951
1952  | error ';' {
1953        $$ = 0;
1954    }
1955  | error '}' {
1956        $$ = 0;
1957    }
1958*/
1959    ;
1960
1961invalid_block:
1962    '{' error invalid_block_list error closing_brace {
1963        parser->invalidBlockHit();
1964    }
1965  | '{' error closing_brace {
1966        parser->invalidBlockHit();
1967    }
1968    ;
1969
1970invalid_block_list:
1971    invalid_block
1972  | invalid_block_list error invalid_block
1973;
1974
1975error_location: {
1976        $$ = parser->currentLocation();
1977    }
1978    ;
1979
1980error_recovery:
1981    /* empty */
1982  | error_recovery invalid_block
1983  | error_recovery error
1984    ;
1985
1986%%
1987
1988