summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/css/CSSGrammar.y
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-13 06:44:40 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-05-13 06:44:40 -0700
commit08014c20784f3db5df3a89b73cce46037b77eb59 (patch)
tree47749210d31e19e6e2f64036fa8fae2ad693476f /Source/WebCore/css/CSSGrammar.y
parent860220379e56aeb66424861ad602b07ee22b4055 (diff)
parent4c3661f7918f8b3f139f824efb7855bedccb4c94 (diff)
downloadexternal_webkit-08014c20784f3db5df3a89b73cce46037b77eb59.zip
external_webkit-08014c20784f3db5df3a89b73cce46037b77eb59.tar.gz
external_webkit-08014c20784f3db5df3a89b73cce46037b77eb59.tar.bz2
Merge changes Ide388898,Ic49f367c,I1158a808,Iacb6ca5d,I2100dd3a,I5c1abe54,Ib0ef9902,I31dbc523,I570314b3
* changes: Merge WebKit at r75315: Update WebKit version Merge WebKit at r75315: Add FrameLoaderClient PageCache stubs Merge WebKit at r75315: Stub out AXObjectCache::remove() Merge WebKit at r75315: Fix ImageBuffer Merge WebKit at r75315: Fix PluginData::initPlugins() Merge WebKit at r75315: Fix conflicts Merge WebKit at r75315: Fix Makefiles Merge WebKit at r75315: Move Android-specific WebCore files to Source Merge WebKit at r75315: Initial merge by git.
Diffstat (limited to 'Source/WebCore/css/CSSGrammar.y')
-rw-r--r--Source/WebCore/css/CSSGrammar.y1552
1 files changed, 1552 insertions, 0 deletions
diff --git a/Source/WebCore/css/CSSGrammar.y b/Source/WebCore/css/CSSGrammar.y
new file mode 100644
index 0000000..ba5855d
--- /dev/null
+++ b/Source/WebCore/css/CSSGrammar.y
@@ -0,0 +1,1552 @@
+%{
+
+/*
+ * Copyright (C) 2002-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
+ * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+
+#include "CSSMediaRule.h"
+#include "CSSParser.h"
+#include "CSSPrimitiveValue.h"
+#include "CSSPropertyNames.h"
+#include "CSSRuleList.h"
+#include "CSSSelector.h"
+#include "CSSStyleSheet.h"
+#include "Document.h"
+#include "HTMLNames.h"
+#include "MediaList.h"
+#include "MediaQueryExp.h"
+#include "WebKitCSSKeyframeRule.h"
+#include "WebKitCSSKeyframesRule.h"
+#include <wtf/FastMalloc.h>
+#include <stdlib.h>
+#include <string.h>
+
+using namespace WebCore;
+using namespace HTMLNames;
+
+#define YYMALLOC fastMalloc
+#define YYFREE fastFree
+
+#define YYENABLE_NLS 0
+#define YYLTYPE_IS_TRIVIAL 1
+#define YYMAXDEPTH 10000
+#define YYDEBUG 0
+
+// FIXME: Replace with %parse-param { CSSParser* parser } once we can depend on bison 2.x
+#define YYPARSE_PARAM parser
+#define YYLEX_PARAM parser
+
+%}
+
+%pure_parser
+
+%union {
+ bool boolean;
+ char character;
+ int integer;
+ double number;
+ CSSParserString string;
+
+ CSSRule* rule;
+ CSSRuleList* ruleList;
+ CSSSelector* selector;
+ Vector<CSSSelector*>* selectorList;
+ CSSSelector::MarginBoxType marginBox;
+ CSSSelector::Relation relation;
+ MediaList* mediaList;
+ MediaQuery* mediaQuery;
+ MediaQuery::Restrictor mediaQueryRestrictor;
+ MediaQueryExp* mediaQueryExp;
+ CSSParserValue value;
+ CSSParserValueList* valueList;
+ Vector<OwnPtr<MediaQueryExp> >* mediaQueryExpList;
+ WebKitCSSKeyframeRule* keyframeRule;
+ WebKitCSSKeyframesRule* keyframesRule;
+ float val;
+}
+
+%{
+
+static inline int cssyyerror(const char*)
+{
+ return 1;
+}
+
+static int cssyylex(YYSTYPE* yylval, void* parser)
+{
+ return static_cast<CSSParser*>(parser)->lex(yylval);
+}
+
+%}
+
+%expect 51
+
+%nonassoc LOWEST_PREC
+
+%left UNIMPORTANT_TOK
+
+%token WHITESPACE SGML_CD
+%token TOKEN_EOF 0
+
+%token INCLUDES
+%token DASHMATCH
+%token BEGINSWITH
+%token ENDSWITH
+%token CONTAINS
+
+%token <string> STRING
+%right <string> IDENT
+%token <string> NTH
+
+%nonassoc <string> HEX
+%nonassoc <string> IDSEL
+%nonassoc ':'
+%nonassoc '.'
+%nonassoc '['
+%nonassoc <string> '*'
+%nonassoc error
+%left '|'
+
+%token IMPORT_SYM
+%token PAGE_SYM
+%token MEDIA_SYM
+%token FONT_FACE_SYM
+%token CHARSET_SYM
+%token NAMESPACE_SYM
+%token WEBKIT_RULE_SYM
+%token WEBKIT_DECLS_SYM
+%token WEBKIT_KEYFRAME_RULE_SYM
+%token WEBKIT_KEYFRAMES_SYM
+%token WEBKIT_VALUE_SYM
+%token WEBKIT_MEDIAQUERY_SYM
+%token WEBKIT_SELECTOR_SYM
+%token <marginBox> TOPLEFTCORNER_SYM
+%token <marginBox> TOPLEFT_SYM
+%token <marginBox> TOPCENTER_SYM
+%token <marginBox> TOPRIGHT_SYM
+%token <marginBox> TOPRIGHTCORNER_SYM
+%token <marginBox> BOTTOMLEFTCORNER_SYM
+%token <marginBox> BOTTOMLEFT_SYM
+%token <marginBox> BOTTOMCENTER_SYM
+%token <marginBox> BOTTOMRIGHT_SYM
+%token <marginBox> BOTTOMRIGHTCORNER_SYM
+%token <marginBox> LEFTTOP_SYM
+%token <marginBox> LEFTMIDDLE_SYM
+%token <marginBox> LEFTBOTTOM_SYM
+%token <marginBox> RIGHTTOP_SYM
+%token <marginBox> RIGHTMIDDLE_SYM
+%token <marginBox> RIGHTBOTTOM_SYM
+
+%token ATKEYWORD
+
+%token IMPORTANT_SYM
+%token MEDIA_ONLY
+%token MEDIA_NOT
+%token MEDIA_AND
+
+%token <number> REMS
+%token <number> QEMS
+%token <number> EMS
+%token <number> EXS
+%token <number> PXS
+%token <number> CMS
+%token <number> MMS
+%token <number> INS
+%token <number> PTS
+%token <number> PCS
+%token <number> DEGS
+%token <number> RADS
+%token <number> GRADS
+%token <number> TURNS
+%token <number> MSECS
+%token <number> SECS
+%token <number> HERTZ
+%token <number> KHERTZ
+%token <string> DIMEN
+%token <number> PERCENTAGE
+%token <number> FLOATTOKEN
+%token <number> INTEGER
+
+%token <string> URI
+%token <string> FUNCTION
+%token <string> NOTFUNCTION
+
+%token <string> UNICODERANGE
+
+%type <relation> combinator
+
+%type <rule> charset
+%type <rule> ignored_charset
+%type <rule> ruleset
+%type <rule> media
+%type <rule> import
+%type <rule> namespace
+%type <rule> page
+%type <rule> margin_box
+%type <rule> font_face
+%type <rule> keyframes
+%type <rule> invalid_rule
+%type <rule> save_block
+%type <rule> invalid_at
+%type <rule> rule
+%type <rule> valid_rule
+%type <ruleList> block_rule_list
+%type <rule> block_rule
+%type <rule> block_valid_rule
+
+%type <string> maybe_ns_prefix
+
+%type <string> namespace_selector
+
+%type <string> string_or_uri
+%type <string> ident_or_string
+%type <string> medium
+%type <string> hexcolor
+%type <marginBox> margin_sym
+
+%type <string> media_feature
+%type <mediaList> media_list
+%type <mediaList> maybe_media_list
+%type <mediaQuery> media_query
+%type <mediaQueryRestrictor> maybe_media_restrictor
+%type <valueList> maybe_media_value
+%type <mediaQueryExp> media_query_exp
+%type <mediaQueryExpList> media_query_exp_list
+%type <mediaQueryExpList> maybe_and_media_query_exp_list
+
+%type <string> keyframe_name
+%type <keyframeRule> keyframe_rule
+%type <keyframesRule> keyframes_rule
+%type <valueList> key_list
+%type <value> key
+
+%type <integer> property
+
+%type <selector> specifier
+%type <selector> specifier_list
+%type <selector> simple_selector
+%type <selector> selector
+%type <selectorList> selector_list
+%type <selector> selector_with_trailing_whitespace
+%type <selector> class
+%type <selector> attrib
+%type <selector> pseudo
+%type <selector> pseudo_page
+%type <selector> page_selector
+
+%type <boolean> declaration_list
+%type <boolean> decl_list
+%type <boolean> declaration
+%type <boolean> declarations_and_margins
+
+%type <boolean> prio
+
+%type <integer> match
+%type <integer> unary_operator
+%type <integer> maybe_unary_operator
+%type <character> operator
+
+%type <valueList> expr
+%type <value> term
+%type <value> unary_term
+%type <value> function
+
+%type <string> element_name
+%type <string> attr_name
+
+%%
+
+stylesheet:
+ maybe_space maybe_charset maybe_sgml rule_list
+ | webkit_rule maybe_space
+ | webkit_decls maybe_space
+ | webkit_value maybe_space
+ | webkit_mediaquery maybe_space
+ | webkit_selector maybe_space
+ | webkit_keyframe_rule maybe_space
+ ;
+
+webkit_rule:
+ WEBKIT_RULE_SYM '{' maybe_space valid_rule maybe_space '}' {
+ static_cast<CSSParser*>(parser)->m_rule = $4;
+ }
+;
+
+webkit_keyframe_rule:
+ WEBKIT_KEYFRAME_RULE_SYM '{' maybe_space keyframe_rule maybe_space '}' {
+ static_cast<CSSParser*>(parser)->m_keyframe = $4;
+ }
+;
+
+webkit_decls:
+ WEBKIT_DECLS_SYM '{' maybe_space_before_declaration declaration_list '}' {
+ /* can be empty */
+ }
+;
+
+webkit_value:
+ WEBKIT_VALUE_SYM '{' maybe_space expr '}' {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if ($4) {
+ p->m_valueList = p->sinkFloatingValueList($4);
+ int oldParsedProperties = p->m_numParsedProperties;
+ if (!p->parseValue(p->m_id, p->m_important))
+ p->rollbackLastProperties(p->m_numParsedProperties - oldParsedProperties);
+ delete p->m_valueList;
+ p->m_valueList = 0;
+ }
+ }
+;
+
+webkit_mediaquery:
+ WEBKIT_MEDIAQUERY_SYM WHITESPACE maybe_space media_query '}' {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->m_mediaQuery = p->sinkFloatingMediaQuery($4);
+ }
+;
+
+webkit_selector:
+ WEBKIT_SELECTOR_SYM '{' maybe_space selector_list '}' {
+ if ($4) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if (p->m_selectorListForParseSelector)
+ p->m_selectorListForParseSelector->adoptSelectorVector(*$4);
+ }
+ }
+;
+
+maybe_space:
+ /* empty */ %prec UNIMPORTANT_TOK
+ | maybe_space WHITESPACE
+ ;
+
+maybe_sgml:
+ /* empty */
+ | maybe_sgml SGML_CD
+ | maybe_sgml WHITESPACE
+ ;
+
+maybe_charset:
+ /* empty */
+ | charset {
+ }
+ ;
+
+closing_brace:
+ '}'
+ | %prec LOWEST_PREC TOKEN_EOF
+ ;
+
+charset:
+ CHARSET_SYM maybe_space STRING maybe_space ';' {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = static_cast<CSSParser*>(parser)->createCharsetRule($3);
+ if ($$ && p->m_styleSheet)
+ p->m_styleSheet->append($$);
+ }
+ | CHARSET_SYM error invalid_block {
+ }
+ | CHARSET_SYM error ';' {
+ }
+;
+
+ignored_charset:
+ CHARSET_SYM maybe_space STRING maybe_space ';' {
+ // Ignore any @charset rule not at the beginning of the style sheet.
+ $$ = 0;
+ }
+;
+
+rule_list:
+ /* empty */
+ | rule_list rule maybe_sgml {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if ($2 && p->m_styleSheet)
+ p->m_styleSheet->append($2);
+ }
+ ;
+
+valid_rule:
+ before_ruleset ruleset {
+ $$ = $2;
+ }
+ | media
+ | page
+ | font_face
+ | keyframes
+ | namespace
+ | import
+ ;
+
+rule:
+ valid_rule {
+ static_cast<CSSParser*>(parser)->m_hadSyntacticallyValidCSSRule = true;
+ }
+ | ignored_charset
+ | invalid_rule
+ | invalid_at
+ ;
+
+block_rule_list:
+ /* empty */ { $$ = 0; }
+ | block_rule_list block_rule maybe_sgml {
+ $$ = $1;
+ if ($2) {
+ if (!$$)
+ $$ = static_cast<CSSParser*>(parser)->createRuleList();
+ $$->append($2);
+ }
+ }
+ ;
+
+block_valid_rule:
+ ruleset
+ | page
+ | font_face
+ | keyframes
+ ;
+
+block_rule:
+ block_valid_rule
+ | invalid_rule
+ | invalid_at
+ | namespace
+ | import
+ | media
+ ;
+
+
+import:
+ IMPORT_SYM maybe_space string_or_uri maybe_space maybe_media_list ';' {
+ $$ = static_cast<CSSParser*>(parser)->createImportRule($3, $5);
+ }
+ | IMPORT_SYM maybe_space string_or_uri maybe_space maybe_media_list invalid_block {
+ $$ = 0;
+ }
+ | IMPORT_SYM error ';' {
+ $$ = 0;
+ }
+ | IMPORT_SYM error invalid_block {
+ $$ = 0;
+ }
+ ;
+
+namespace:
+NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space ';' {
+ static_cast<CSSParser*>(parser)->addNamespace($3, $4);
+ $$ = 0;
+}
+| NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space invalid_block {
+ $$ = 0;
+}
+| NAMESPACE_SYM error invalid_block {
+ $$ = 0;
+}
+| NAMESPACE_SYM error ';' {
+ $$ = 0;
+}
+;
+
+maybe_ns_prefix:
+/* empty */ { $$.characters = 0; }
+| IDENT maybe_space { $$ = $1; }
+;
+
+string_or_uri:
+STRING
+| URI
+;
+
+media_feature:
+ IDENT maybe_space {
+ $$ = $1;
+ }
+ ;
+
+maybe_media_value:
+ /*empty*/ {
+ $$ = 0;
+ }
+ | ':' maybe_space expr maybe_space {
+ $$ = $3;
+ }
+ ;
+
+media_query_exp:
+ '(' maybe_space media_feature maybe_space maybe_media_value ')' maybe_space {
+ $3.lower();
+ $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExp($3, $5);
+ }
+ ;
+
+media_query_exp_list:
+ media_query_exp {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingMediaQueryExpList();
+ $$->append(p->sinkFloatingMediaQueryExp($1));
+ }
+ | media_query_exp_list maybe_space MEDIA_AND maybe_space media_query_exp {
+ $$ = $1;
+ $$->append(static_cast<CSSParser*>(parser)->sinkFloatingMediaQueryExp($5));
+ }
+ ;
+
+maybe_and_media_query_exp_list:
+ /*empty*/ {
+ $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExpList();
+ }
+ | MEDIA_AND maybe_space media_query_exp_list {
+ $$ = $3;
+ }
+ ;
+
+maybe_media_restrictor:
+ /*empty*/ {
+ $$ = MediaQuery::None;
+ }
+ | MEDIA_ONLY {
+ $$ = MediaQuery::Only;
+ }
+ | MEDIA_NOT {
+ $$ = MediaQuery::Not;
+ }
+ ;
+
+media_query:
+ media_query_exp_list {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingMediaQuery(p->sinkFloatingMediaQueryExpList($1));
+ }
+ |
+ maybe_media_restrictor maybe_space medium maybe_and_media_query_exp_list {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $3.lower();
+ $$ = p->createFloatingMediaQuery($1, $3, p->sinkFloatingMediaQueryExpList($4));
+ }
+ ;
+
+maybe_media_list:
+ /* empty */ {
+ $$ = static_cast<CSSParser*>(parser)->createMediaList();
+ }
+ | media_list
+ ;
+
+media_list:
+ media_query {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createMediaList();
+ $$->appendMediaQuery(p->sinkFloatingMediaQuery($1));
+ }
+ | media_list ',' maybe_space media_query {
+ $$ = $1;
+ if ($$)
+ $$->appendMediaQuery(static_cast<CSSParser*>(parser)->sinkFloatingMediaQuery($4));
+ }
+ | media_list error {
+ $$ = 0;
+ }
+ ;
+
+media:
+ MEDIA_SYM maybe_space media_list '{' maybe_space block_rule_list save_block {
+ $$ = static_cast<CSSParser*>(parser)->createMediaRule($3, $6);
+ }
+ | MEDIA_SYM maybe_space '{' maybe_space block_rule_list save_block {
+ $$ = static_cast<CSSParser*>(parser)->createMediaRule(0, $5);
+ }
+ ;
+
+medium:
+ IDENT maybe_space {
+ $$ = $1;
+ }
+ ;
+
+keyframes:
+ WEBKIT_KEYFRAMES_SYM maybe_space keyframe_name maybe_space '{' maybe_space keyframes_rule '}' {
+ $$ = $7;
+ $7->setNameInternal($3);
+ }
+ ;
+
+keyframe_name:
+ IDENT
+ | STRING
+ ;
+
+keyframes_rule:
+ /* empty */ { $$ = static_cast<CSSParser*>(parser)->createKeyframesRule(); }
+ | keyframes_rule keyframe_rule maybe_space {
+ $$ = $1;
+ if ($2)
+ $$->append($2);
+ }
+ ;
+
+keyframe_rule:
+ key_list maybe_space '{' maybe_space declaration_list '}' {
+ $$ = static_cast<CSSParser*>(parser)->createKeyframeRule($1);
+ }
+ ;
+
+key_list:
+ key {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingValueList();
+ $$->addValue(p->sinkFloatingValue($1));
+ }
+ | key_list maybe_space ',' maybe_space key {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = $1;
+ if ($$)
+ $$->addValue(p->sinkFloatingValue($5));
+ }
+ ;
+
+key:
+ PERCENTAGE { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
+ | IDENT {
+ $$.id = 0; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_NUMBER;
+ CSSParserString& str = $1;
+ if (equalIgnoringCase("from", str.characters, str.length))
+ $$.fValue = 0;
+ else if (equalIgnoringCase("to", str.characters, str.length))
+ $$.fValue = 100;
+ else
+ YYERROR;
+ }
+ ;
+
+page:
+ PAGE_SYM maybe_space page_selector maybe_space
+ '{' maybe_space declarations_and_margins closing_brace {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if ($3)
+ $$ = p->createPageRule(p->sinkFloatingSelector($3));
+ else {
+ // Clear properties in the invalid @page rule.
+ p->clearProperties();
+ // Also clear margin at-rules here once we fully implement margin at-rules parsing.
+ $$ = 0;
+ }
+ }
+ | PAGE_SYM error invalid_block {
+ $$ = 0;
+ }
+ | PAGE_SYM error ';' {
+ $$ = 0;
+ }
+ ;
+
+page_selector:
+ IDENT {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
+ $$->setForPage();
+ }
+ | IDENT pseudo_page {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = $2;
+ if ($$) {
+ $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
+ $$->setForPage();
+ }
+ }
+ | pseudo_page {
+ $$ = $1;
+ if ($$)
+ $$->setForPage();
+ }
+ | /* empty */ {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->setForPage();
+ }
+ ;
+
+declarations_and_margins:
+ declaration_list
+ | declarations_and_margins margin_box maybe_space declaration_list
+ ;
+
+margin_box:
+ margin_sym {
+ static_cast<CSSParser*>(parser)->startDeclarationsForMarginBox();
+ } maybe_space '{' maybe_space declaration_list closing_brace {
+ $$ = static_cast<CSSParser*>(parser)->createMarginAtRule($1);
+ }
+ ;
+
+margin_sym :
+ TOPLEFTCORNER_SYM {
+ $$ = CSSSelector::TopLeftCornerMarginBox;
+ }
+ | TOPLEFT_SYM {
+ $$ = CSSSelector::TopLeftMarginBox;
+ }
+ | TOPCENTER_SYM {
+ $$ = CSSSelector::TopCenterMarginBox;
+ }
+ | TOPRIGHT_SYM {
+ $$ = CSSSelector::TopRightMarginBox;
+ }
+ | TOPRIGHTCORNER_SYM {
+ $$ = CSSSelector::TopRightCornerMarginBox;
+ }
+ | BOTTOMLEFTCORNER_SYM {
+ $$ = CSSSelector::BottomLeftCornerMarginBox;
+ }
+ | BOTTOMLEFT_SYM {
+ $$ = CSSSelector::BottomLeftMarginBox;
+ }
+ | BOTTOMCENTER_SYM {
+ $$ = CSSSelector::BottomCenterMarginBox;
+ }
+ | BOTTOMRIGHT_SYM {
+ $$ = CSSSelector::BottomRightMarginBox;
+ }
+ | BOTTOMRIGHTCORNER_SYM {
+ $$ = CSSSelector::BottomRightCornerMarginBox;
+ }
+ | LEFTTOP_SYM {
+ $$ = CSSSelector::LeftTopMarginBox;
+ }
+ | LEFTMIDDLE_SYM {
+ $$ = CSSSelector::LeftMiddleMarginBox;
+ }
+ | LEFTBOTTOM_SYM {
+ $$ = CSSSelector::LeftBottomMarginBox;
+ }
+ | RIGHTTOP_SYM {
+ $$ = CSSSelector::RightTopMarginBox;
+ }
+ | RIGHTMIDDLE_SYM {
+ $$ = CSSSelector::RightMiddleMarginBox;
+ }
+ | RIGHTBOTTOM_SYM {
+ $$ = CSSSelector::RightBottomMarginBox;
+ }
+ ;
+
+font_face:
+ FONT_FACE_SYM maybe_space
+ '{' maybe_space declaration_list '}' maybe_space {
+ $$ = static_cast<CSSParser*>(parser)->createFontFaceRule();
+ }
+ | FONT_FACE_SYM error invalid_block {
+ $$ = 0;
+ }
+ | FONT_FACE_SYM error ';' {
+ $$ = 0;
+ }
+;
+
+combinator:
+ '+' maybe_space { $$ = CSSSelector::DirectAdjacent; }
+ | '~' maybe_space { $$ = CSSSelector::IndirectAdjacent; }
+ | '>' maybe_space { $$ = CSSSelector::Child; }
+ ;
+
+maybe_unary_operator:
+ unary_operator { $$ = $1; }
+ | { $$ = 1; }
+ ;
+
+unary_operator:
+ '-' { $$ = -1; }
+ | '+' { $$ = 1; }
+ ;
+
+maybe_space_before_declaration:
+ maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyStart();
+ }
+ ;
+
+before_ruleset:
+ /* empty */ {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markSelectorListStart();
+ }
+ ;
+
+before_rule_opening_brace:
+ /* empty */ {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markSelectorListEnd();
+ }
+ ;
+
+ruleset:
+ selector_list before_rule_opening_brace '{' maybe_space_before_declaration declaration_list closing_brace {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createStyleRule($1);
+ }
+ ;
+
+selector_list:
+ selector %prec UNIMPORTANT_TOK {
+ if ($1) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->reusableSelectorVector();
+ deleteAllValues(*$$);
+ $$->shrink(0);
+ $$->append(p->sinkFloatingSelector($1));
+ p->updateLastSelectorLineAndPosition();
+ }
+ }
+ | selector_list ',' maybe_space selector %prec UNIMPORTANT_TOK {
+ if ($1 && $4) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = $1;
+ $$->append(p->sinkFloatingSelector($4));
+ p->updateLastSelectorLineAndPosition();
+ } else
+ $$ = 0;
+ }
+ | selector_list error {
+ $$ = 0;
+ }
+ ;
+
+selector_with_trailing_whitespace:
+ selector WHITESPACE {
+ $$ = $1;
+ }
+ ;
+
+selector:
+ simple_selector {
+ $$ = $1;
+ }
+ | selector_with_trailing_whitespace
+ {
+ $$ = $1;
+ }
+ | selector_with_trailing_whitespace simple_selector
+ {
+ $$ = $2;
+ if (!$1)
+ $$ = 0;
+ else if ($$) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ CSSSelector* end = $$;
+ while (end->tagHistory())
+ end = end->tagHistory();
+ end->m_relation = CSSSelector::Descendant;
+ end->setTagHistory(p->sinkFloatingSelector($1));
+ if (Document* doc = p->document())
+ doc->setUsesDescendantRules(true);
+ }
+ }
+ | selector combinator simple_selector {
+ $$ = $3;
+ if (!$1)
+ $$ = 0;
+ else if ($$) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ CSSSelector* end = $$;
+ while (end->tagHistory())
+ end = end->tagHistory();
+ end->m_relation = $2;
+ end->setTagHistory(p->sinkFloatingSelector($1));
+ if ($2 == CSSSelector::Child) {
+ if (Document* doc = p->document())
+ doc->setUsesDescendantRules(true);
+ } else if ($2 == CSSSelector::DirectAdjacent || $2 == CSSSelector::IndirectAdjacent) {
+ if (Document* doc = p->document())
+ doc->setUsesSiblingRules(true);
+ }
+ }
+ }
+ | selector error {
+ $$ = 0;
+ }
+ ;
+
+namespace_selector:
+ /* empty */ '|' { $$.characters = 0; $$.length = 0; }
+ | '*' '|' { static UChar star = '*'; $$.characters = &star; $$.length = 1; }
+ | IDENT '|' { $$ = $1; }
+;
+
+simple_selector:
+ element_name {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
+ }
+ | element_name specifier_list {
+ $$ = $2;
+ if ($$) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
+ }
+ }
+ | specifier_list {
+ $$ = $1;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if ($$ && p->m_defaultNamespace != starAtom)
+ $$->m_tag = QualifiedName(nullAtom, starAtom, p->m_defaultNamespace);
+ }
+ | namespace_selector element_name {
+ AtomicString namespacePrefix = $1;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ if (p->m_styleSheet)
+ $$->m_tag = QualifiedName(namespacePrefix, $2,
+ p->m_styleSheet->determineNamespace(namespacePrefix));
+ else // FIXME: Shouldn't this case be an error?
+ $$->m_tag = QualifiedName(nullAtom, $2, p->m_defaultNamespace);
+ }
+ | namespace_selector element_name specifier_list {
+ $$ = $3;
+ if ($$) {
+ AtomicString namespacePrefix = $1;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if (p->m_styleSheet)
+ $$->m_tag = QualifiedName(namespacePrefix, $2,
+ p->m_styleSheet->determineNamespace(namespacePrefix));
+ else // FIXME: Shouldn't this case be an error?
+ $$->m_tag = QualifiedName(nullAtom, $2, p->m_defaultNamespace);
+ }
+ }
+ | namespace_selector specifier_list {
+ $$ = $2;
+ if ($$) {
+ AtomicString namespacePrefix = $1;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if (p->m_styleSheet)
+ $$->m_tag = QualifiedName(namespacePrefix, starAtom,
+ p->m_styleSheet->determineNamespace(namespacePrefix));
+ }
+ }
+ ;
+
+element_name:
+ IDENT {
+ CSSParserString& str = $1;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ Document* doc = p->document();
+ if (doc && doc->isHTMLDocument())
+ str.lower();
+ $$ = str;
+ }
+ | '*' {
+ static UChar star = '*';
+ $$.characters = &star;
+ $$.length = 1;
+ }
+ ;
+
+specifier_list:
+ specifier {
+ $$ = $1;
+ }
+ | specifier_list specifier {
+ if (!$2)
+ $$ = 0;
+ else if ($1) {
+ $$ = $1;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ CSSSelector* end = $1;
+ while (end->tagHistory())
+ end = end->tagHistory();
+ end->m_relation = CSSSelector::SubSelector;
+ end->setTagHistory(p->sinkFloatingSelector($2));
+ }
+ }
+ | specifier_list error {
+ $$ = 0;
+ }
+;
+
+specifier:
+ IDSEL {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->m_match = CSSSelector::Id;
+ if (!p->m_strict)
+ $1.lower();
+ $$->m_value = $1;
+ }
+ | HEX {
+ if ($1.characters[0] >= '0' && $1.characters[0] <= '9') {
+ $$ = 0;
+ } else {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->m_match = CSSSelector::Id;
+ if (!p->m_strict)
+ $1.lower();
+ $$->m_value = $1;
+ }
+ }
+ | class
+ | attrib
+ | pseudo
+ ;
+
+class:
+ '.' IDENT {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->m_match = CSSSelector::Class;
+ if (!p->m_strict)
+ $2.lower();
+ $$->m_value = $2;
+ }
+ ;
+
+attr_name:
+ IDENT maybe_space {
+ CSSParserString& str = $1;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ Document* doc = p->document();
+ if (doc && doc->isHTMLDocument())
+ str.lower();
+ $$ = str;
+ }
+ ;
+
+attrib:
+ '[' maybe_space attr_name ']' {
+ $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
+ $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
+ $$->m_match = CSSSelector::Set;
+ }
+ | '[' maybe_space attr_name match maybe_space ident_or_string maybe_space ']' {
+ $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
+ $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
+ $$->m_match = (CSSSelector::Match)$4;
+ $$->m_value = $6;
+ }
+ | '[' maybe_space namespace_selector attr_name ']' {
+ AtomicString namespacePrefix = $3;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->setAttribute(QualifiedName(namespacePrefix, $4,
+ p->m_styleSheet->determineNamespace(namespacePrefix)));
+ $$->m_match = CSSSelector::Set;
+ }
+ | '[' maybe_space namespace_selector attr_name match maybe_space ident_or_string maybe_space ']' {
+ AtomicString namespacePrefix = $3;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->setAttribute(QualifiedName(namespacePrefix, $4,
+ p->m_styleSheet->determineNamespace(namespacePrefix)));
+ $$->m_match = (CSSSelector::Match)$5;
+ $$->m_value = $7;
+ }
+ ;
+
+match:
+ '=' {
+ $$ = CSSSelector::Exact;
+ }
+ | INCLUDES {
+ $$ = CSSSelector::List;
+ }
+ | DASHMATCH {
+ $$ = CSSSelector::Hyphen;
+ }
+ | BEGINSWITH {
+ $$ = CSSSelector::Begin;
+ }
+ | ENDSWITH {
+ $$ = CSSSelector::End;
+ }
+ | CONTAINS {
+ $$ = CSSSelector::Contain;
+ }
+ ;
+
+ident_or_string:
+ IDENT
+ | STRING
+ ;
+
+pseudo_page:
+ ':' IDENT {
+ $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
+ $$->m_match = CSSSelector::PagePseudoClass;
+ $2.lower();
+ $$->m_value = $2;
+ CSSSelector::PseudoType type = $$->pseudoType();
+ if (type == CSSSelector::PseudoUnknown)
+ $$ = 0;
+ }
+
+pseudo:
+ ':' IDENT {
+ $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
+ $$->m_match = CSSSelector::PseudoClass;
+ $2.lower();
+ $$->m_value = $2;
+ CSSSelector::PseudoType type = $$->pseudoType();
+ if (type == CSSSelector::PseudoUnknown)
+ $$ = 0;
+ else if (type == CSSSelector::PseudoEmpty ||
+ type == CSSSelector::PseudoFirstChild ||
+ type == CSSSelector::PseudoFirstOfType ||
+ type == CSSSelector::PseudoLastChild ||
+ type == CSSSelector::PseudoLastOfType ||
+ type == CSSSelector::PseudoOnlyChild ||
+ type == CSSSelector::PseudoOnlyOfType) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ Document* doc = p->document();
+ if (doc)
+ doc->setUsesSiblingRules(true);
+ } else if (type == CSSSelector::PseudoFirstLine) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if (Document* doc = p->document())
+ doc->setUsesFirstLineRules(true);
+ } else if (type == CSSSelector::PseudoBefore ||
+ type == CSSSelector::PseudoAfter) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if (Document* doc = p->document())
+ doc->setUsesBeforeAfterRules(true);
+ } else if (type == CSSSelector::PseudoLink || type == CSSSelector::PseudoVisited) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if (Document* doc = p->document())
+ doc->setUsesLinkRules(true);
+ }
+ }
+ | ':' ':' IDENT {
+ $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
+ $$->m_match = CSSSelector::PseudoElement;
+ $3.lower();
+ $$->m_value = $3;
+ CSSSelector::PseudoType type = $$->pseudoType();
+ if (type == CSSSelector::PseudoUnknown)
+ $$ = 0;
+ else if (type == CSSSelector::PseudoFirstLine) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if (Document* doc = p->document())
+ doc->setUsesFirstLineRules(true);
+ } else if (type == CSSSelector::PseudoBefore ||
+ type == CSSSelector::PseudoAfter) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if (Document* doc = p->document())
+ doc->setUsesBeforeAfterRules(true);
+ }
+ }
+ // used by :nth-*(ax+b)
+ | ':' FUNCTION maybe_space NTH maybe_space ')' {
+ CSSParser *p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->m_match = CSSSelector::PseudoClass;
+ $$->setArgument($4);
+ $$->m_value = $2;
+ CSSSelector::PseudoType type = $$->pseudoType();
+ if (type == CSSSelector::PseudoUnknown)
+ $$ = 0;
+ else if (type == CSSSelector::PseudoNthChild ||
+ type == CSSSelector::PseudoNthOfType ||
+ type == CSSSelector::PseudoNthLastChild ||
+ type == CSSSelector::PseudoNthLastOfType) {
+ if (p->document())
+ p->document()->setUsesSiblingRules(true);
+ }
+ }
+ // used by :nth-*
+ | ':' FUNCTION maybe_space maybe_unary_operator INTEGER maybe_space ')' {
+ CSSParser *p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->m_match = CSSSelector::PseudoClass;
+ $$->setArgument(String::number($4 * $5));
+ $$->m_value = $2;
+ CSSSelector::PseudoType type = $$->pseudoType();
+ if (type == CSSSelector::PseudoUnknown)
+ $$ = 0;
+ else if (type == CSSSelector::PseudoNthChild ||
+ type == CSSSelector::PseudoNthOfType ||
+ type == CSSSelector::PseudoNthLastChild ||
+ type == CSSSelector::PseudoNthLastOfType) {
+ if (p->document())
+ p->document()->setUsesSiblingRules(true);
+ }
+ }
+ // used by :nth-*(odd/even) and :lang
+ | ':' FUNCTION maybe_space IDENT maybe_space ')' {
+ CSSParser *p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->m_match = CSSSelector::PseudoClass;
+ $$->setArgument($4);
+ $2.lower();
+ $$->m_value = $2;
+ CSSSelector::PseudoType type = $$->pseudoType();
+ if (type == CSSSelector::PseudoUnknown)
+ $$ = 0;
+ else if (type == CSSSelector::PseudoNthChild ||
+ type == CSSSelector::PseudoNthOfType ||
+ type == CSSSelector::PseudoNthLastChild ||
+ type == CSSSelector::PseudoNthLastOfType) {
+ if (isValidNthToken($4)) {
+ if (p->document())
+ p->document()->setUsesSiblingRules(true);
+ } else
+ $$ = 0;
+ }
+ }
+ // used by :not
+ | ':' NOTFUNCTION maybe_space simple_selector maybe_space ')' {
+ if (!$4 || !$4->isSimple())
+ $$ = 0;
+ else {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->m_match = CSSSelector::PseudoClass;
+ $$->setSimpleSelector(p->sinkFloatingSelector($4));
+ $2.lower();
+ $$->m_value = $2;
+ }
+ }
+ ;
+
+declaration_list:
+ declaration {
+ $$ = $1;
+ }
+ | decl_list declaration {
+ $$ = $1;
+ if ( $2 )
+ $$ = $2;
+ }
+ | decl_list {
+ $$ = $1;
+ }
+ | error invalid_block_list error {
+ $$ = false;
+ }
+ | error {
+ $$ = false;
+ }
+ | decl_list error {
+ $$ = $1;
+ }
+ | decl_list invalid_block_list {
+ $$ = $1;
+ }
+ ;
+
+decl_list:
+ declaration ';' maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyStart();
+ $$ = $1;
+ }
+ | declaration invalid_block_list maybe_space {
+ $$ = false;
+ }
+ | declaration invalid_block_list ';' maybe_space {
+ $$ = false;
+ }
+ | error ';' maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyStart();
+ $$ = false;
+ }
+ | error invalid_block_list error ';' maybe_space {
+ $$ = false;
+ }
+ | decl_list declaration ';' maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyStart();
+ $$ = $1;
+ if ($2)
+ $$ = $2;
+ }
+ | decl_list error ';' maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyStart();
+ $$ = $1;
+ }
+ | decl_list error invalid_block_list error ';' maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyStart();
+ $$ = $1;
+ }
+ ;
+
+declaration:
+ property ':' maybe_space expr prio {
+ $$ = false;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ bool isPropertyParsed = false;
+ if ($1 && $4) {
+ p->m_valueList = p->sinkFloatingValueList($4);
+ int oldParsedProperties = p->m_numParsedProperties;
+ $$ = p->parseValue($1, $5);
+ if (!$$)
+ p->rollbackLastProperties(p->m_numParsedProperties - oldParsedProperties);
+ else
+ isPropertyParsed = true;
+ delete p->m_valueList;
+ p->m_valueList = 0;
+ }
+ p->markPropertyEnd($5, isPropertyParsed);
+ }
+ |
+ property error {
+ $$ = false;
+ }
+ |
+ property ':' maybe_space error expr prio {
+ /* The default movable type template has letter-spacing: .none; Handle this by looking for
+ error tokens at the start of an expr, recover the expr and then treat as an error, cleaning
+ up and deleting the shifted expr. */
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyEnd(false, false);
+ $$ = false;
+ }
+ |
+ property ':' maybe_space expr prio error {
+ /* When we encounter something like p {color: red !important fail;} we should drop the declaration */
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyEnd(false, false);
+ $$ = false;
+ }
+ |
+ IMPORTANT_SYM maybe_space {
+ /* Handle this case: div { text-align: center; !important } Just reduce away the stray !important. */
+ $$ = false;
+ }
+ |
+ property ':' maybe_space {
+ /* div { font-family: } Just reduce away this property with no value. */
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyEnd(false, false);
+ $$ = false;
+ }
+ |
+ property ':' maybe_space error {
+ /* if we come across rules with invalid values like this case: p { weight: *; }, just discard the rule */
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyEnd(false, false);
+ $$ = false;
+ }
+ |
+ property invalid_block {
+ /* if we come across: div { color{;color:maroon} }, ignore everything within curly brackets */
+ $$ = false;
+ }
+ ;
+
+property:
+ IDENT maybe_space {
+ $$ = cssPropertyID($1);
+ }
+ ;
+
+prio:
+ IMPORTANT_SYM maybe_space { $$ = true; }
+ | /* empty */ { $$ = false; }
+ ;
+
+expr:
+ term {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingValueList();
+ $$->addValue(p->sinkFloatingValue($1));
+ }
+ | expr operator term {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = $1;
+ if ($$) {
+ if ($2) {
+ CSSParserValue v;
+ v.id = 0;
+ v.unit = CSSParserValue::Operator;
+ v.iValue = $2;
+ $$->addValue(v);
+ }
+ $$->addValue(p->sinkFloatingValue($3));
+ }
+ }
+ | expr invalid_block_list {
+ $$ = 0;
+ }
+ | expr invalid_block_list error {
+ $$ = 0;
+ }
+ | expr error {
+ $$ = 0;
+ }
+ ;
+
+operator:
+ '/' maybe_space {
+ $$ = '/';
+ }
+ | ',' maybe_space {
+ $$ = ',';
+ }
+ | /* empty */ {
+ $$ = 0;
+ }
+ ;
+
+term:
+ unary_term { $$ = $1; }
+ | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
+ | STRING maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; }
+ | IDENT maybe_space {
+ $$.id = cssValueKeywordID($1);
+ $$.unit = CSSPrimitiveValue::CSS_IDENT;
+ $$.string = $1;
+ }
+ /* We might need to actually parse the number from a dimension, but we can't just put something that uses $$.string into unary_term. */
+ | DIMEN maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
+ | unary_operator DIMEN maybe_space { $$.id = 0; $$.string = $2; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
+ | URI maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI; }
+ | UNICODERANGE maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE; }
+ | hexcolor { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; }
+ | '#' maybe_space { $$.id = 0; $$.string = CSSParserString(); $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } /* Handle error case: "color: #;" */
+ /* FIXME: according to the specs a function can have a unary_operator in front. I know no case where this makes sense */
+ | function {
+ $$ = $1;
+ }
+ | '%' maybe_space { /* Handle width: %; */
+ $$.id = 0; $$.unit = 0;
+ }
+ ;
+
+unary_term:
+ INTEGER maybe_space { $$.id = 0; $$.isInt = true; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
+ | FLOATTOKEN maybe_space { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
+ | PERCENTAGE maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PERCENTAGE; }
+ | PXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PX; }
+ | CMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CM; }
+ | MMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MM; }
+ | INS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_IN; }
+ | PTS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PT; }
+ | PCS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PC; }
+ | DEGS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DEG; }
+ | RADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_RAD; }
+ | GRADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_GRAD; }
+ | TURNS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_TURN; }
+ | MSECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MS; }
+ | SECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_S; }
+ | HERTZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_HZ; }
+ | KHERTZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_KHZ; }
+ | EMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EMS; }
+ | QEMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSParserValue::Q_EMS; }
+ | EXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EXS; }
+ | REMS maybe_space {
+ $$.id = 0;
+ $$.fValue = $1;
+ $$.unit = CSSPrimitiveValue::CSS_REMS;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if (Document* doc = p->document())
+ doc->setUsesRemUnits(true);
+ }
+ ;
+
+function:
+ FUNCTION maybe_space expr ')' maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ CSSParserFunction* f = p->createFloatingFunction();
+ f->name = $1;
+ f->args = p->sinkFloatingValueList($3);
+ $$.id = 0;
+ $$.unit = CSSParserValue::Function;
+ $$.function = f;
+ } |
+ FUNCTION maybe_space error {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ CSSParserFunction* f = p->createFloatingFunction();
+ f->name = $1;
+ f->args = 0;
+ $$.id = 0;
+ $$.unit = CSSParserValue::Function;
+ $$.function = f;
+ }
+ ;
+/*
+ * 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:
+ HEX maybe_space { $$ = $1; }
+ | IDSEL maybe_space { $$ = $1; }
+ ;
+
+
+/* error handling rules */
+
+save_block:
+ closing_brace {
+ $$ = 0;
+ }
+ | error closing_brace {
+ $$ = 0;
+ }
+ ;
+
+invalid_at:
+ ATKEYWORD error invalid_block {
+ $$ = 0;
+ }
+ | ATKEYWORD error ';' {
+ $$ = 0;
+ }
+ ;
+
+invalid_rule:
+ error invalid_block {
+ $$ = 0;
+ }
+
+/*
+ Seems like the two rules below are trying too much and violating
+ http://www.hixie.ch/tests/evil/mixed/csserrorhandling.html
+
+ | error ';' {
+ $$ = 0;
+ }
+ | error '}' {
+ $$ = 0;
+ }
+*/
+ ;
+
+invalid_block:
+ '{' error invalid_block_list error closing_brace {
+ static_cast<CSSParser*>(parser)->invalidBlockHit();
+ }
+ | '{' error closing_brace {
+ static_cast<CSSParser*>(parser)->invalidBlockHit();
+ }
+ ;
+
+invalid_block_list:
+ invalid_block
+ | invalid_block_list error invalid_block
+;
+
+%%