blob: ad5e331c40a7896f97aa8fe07429ca843388a4e0 [file] [log] [blame]
%{
/*
* Copyright (C) 2002-2003 Lars Knoll (knoll@kde.org)
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
* Copyright (C) 2008 Eric Seidel <eric@webkit.org>
* Copyright (C) 2012 Intel Corporation. All rights reserved.
*
* 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 "CSSPropertyNames.h"
#include "HTMLNames.h"
#include "core/css/CSSKeyframeRule.h"
#include "core/css/CSSKeyframesRule.h"
#include "core/css/CSSParser.h"
#include "core/css/CSSParserMode.h"
#include "core/css/CSSPrimitiveValue.h"
#include "core/css/CSSSelector.h"
#include "core/css/CSSSelectorList.h"
#include "core/css/MediaList.h"
#include "core/css/MediaQueryExp.h"
#include "core/css/StyleRule.h"
#include "core/css/StyleSheetContents.h"
#include "core/dom/Document.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
#if YYDEBUG > 0
#define YYPRINT(File,Type,Value) if (isCSSTokenAString(Type)) YYFPRINTF(File, "%s", String((Value).string).utf8().data())
#endif
%}
%pure_parser
%parse-param { CSSParser* parser }
%lex-param { CSSParser* parser }
%union {
bool boolean;
char character;
int integer;
double number;
CSSParserString string;
StyleRuleBase* rule;
Vector<RefPtr<StyleRuleBase> >* ruleList;
CSSParserSelector* selector;
Vector<OwnPtr<CSSParserSelector> >* selectorList;
CSSSelector::MarginBoxType marginBox;
CSSSelector::Relation relation;
MediaQuerySet* mediaList;
MediaQuery* mediaQuery;
MediaQuery::Restrictor mediaQueryRestrictor;
MediaQueryExp* mediaQueryExp;
CSSParserValue value;
CSSParserValueList* valueList;
Vector<OwnPtr<MediaQueryExp> >* mediaQueryExpList;
StyleKeyframe* keyframe;
Vector<RefPtr<StyleKeyframe> >* keyframeRuleList;
float val;
CSSPropertyID id;
CSSParserLocation location;
}
%{
static inline int cssyyerror(void*, const char*)
{
return 1;
}
static inline bool isCSSTokenAString(int yytype)
{
switch (yytype) {
case IDENT:
case STRING:
case NTH:
case HEX:
case IDSEL:
case DIMEN:
case INVALIDDIMEN:
case URI:
case FUNCTION:
case ANYFUNCTION:
case HOSTFUNCTION:
case NOTFUNCTION:
case CALCFUNCTION:
case MINFUNCTION:
case MAXFUNCTION:
case VARFUNCTION:
case VAR_DEFINITION:
case UNICODERANGE:
return true;
default:
return false;
}
}
inline static CSSParserValue makeOperatorValue(int value)
{
CSSParserValue v;
v.id = CSSValueInvalid;
v.unit = CSSParserValue::Operator;
v.iValue = value;
return v;
}
%}
%expect 0
%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 SUPPORTS_SYM
%token FONT_FACE_SYM
%token HOST_SYM
%token CHARSET_SYM
%token NAMESPACE_SYM
%token VIEWPORT_RULE_SYM
%token INTERNAL_DECLS_SYM
%token INTERNAL_MEDIALIST_SYM
%token INTERNAL_RULE_SYM
%token INTERNAL_SELECTOR_SYM
%token INTERNAL_VALUE_SYM
%token INTERNAL_KEYFRAME_RULE_SYM
%token INTERNAL_KEYFRAME_KEY_LIST_SYM
%token INTERNAL_SUPPORTS_CONDITION_SYM
%token KEYFRAMES_SYM
%token WEBKIT_KEYFRAMES_SYM
%token WEBKIT_REGION_RULE_SYM
%token WEBKIT_FILTER_RULE_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 MEDIA_OR
%token SUPPORTS_NOT
%token SUPPORTS_AND
%token SUPPORTS_OR
%token <number> REMS
%token <number> CHS
%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 <string> INVALIDDIMEN
%token <number> PERCENTAGE
%token <number> FLOATTOKEN
%token <number> INTEGER
%token <number> VW
%token <number> VH
%token <number> VMIN
%token <number> VMAX
%token <number> DPPX
%token <number> DPI
%token <number> DPCM
%token <number> FR
%token <string> URI
%token <string> FUNCTION
%token <string> ANYFUNCTION
%token <string> CUEFUNCTION
%token <string> NOTFUNCTION
%token <string> DISTRIBUTEDFUNCTION
%token <string> CALCFUNCTION
%token <string> MINFUNCTION
%token <string> MAXFUNCTION
%token <string> VARFUNCTION
%token <string> VAR_DEFINITION
%token <string> PARTFUNCTION
%token <string> HOSTFUNCTION
%token <string> UNICODERANGE
%type <relation> combinator
%type <rule> 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> host
%type <rule> keyframes
%type <rule> invalid_rule
%type <rule> rule
%type <rule> valid_rule
%type <ruleList> block_rule_body
%type <ruleList> block_rule_list
%type <ruleList> region_block_rule_body
%type <ruleList> region_block_rule_list
%type <rule> block_rule
%type <rule> block_valid_rule
%type <rule> region
%type <rule> supports
%type <rule> viewport
%type <rule> filter
%type <string> maybe_ns_prefix
%type <string> namespace_selector
%type <string> string_or_uri
%type <string> ident_or_string
%type <string> medium
%type <marginBox> margin_sym
%type <mediaList> media_list
%type <mediaList> maybe_media_list
%type <mediaList> mq_list
%type <mediaQuery> media_query
%type <mediaQuery> valid_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 <boolean> supports_condition
%type <boolean> supports_condition_in_parens
%type <boolean> supports_negation
%type <boolean> supports_conjunction
%type <boolean> supports_disjunction
%type <boolean> supports_declaration_condition
%type <string> keyframe_name
%type <keyframe> keyframe_rule
%type <keyframeRuleList> keyframes_rule
%type <keyframeRuleList> keyframe_rule_list
%type <valueList> key_list
%type <value> key
%type <id> property
%type <selector> specifier
%type <selector> specifier_list
%type <selector> simple_selector
%type <selector> selector
%type <selector> relative_selector
%type <selectorList> selector_list
%type <selectorList> simple_selector_list
%type <selectorList> region_selector
%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 <value> calc_func_term
%type <character> calc_func_operator
%type <valueList> calc_func_expr
%type <valueList> calc_func_expr_list
%type <valueList> calc_func_paren_expr
%type <value> calc_function
%type <string> min_or_max
%type <value> min_or_max_function
%type <string> element_name
%type <string> attr_name
%type <location> error_location
%%
stylesheet:
maybe_charset maybe_sgml rule_list
| internal_decls
| internal_rule
| internal_selector
| internal_value
| internal_medialist
| internal_keyframe_rule
| internal_keyframe_key_list
| internal_supports_condition
;
internal_rule:
INTERNAL_RULE_SYM maybe_space valid_rule maybe_space TOKEN_EOF {
parser->m_rule = $3;
}
;
internal_keyframe_rule:
INTERNAL_KEYFRAME_RULE_SYM maybe_space keyframe_rule maybe_space TOKEN_EOF {
parser->m_keyframe = $3;
}
;
internal_keyframe_key_list:
INTERNAL_KEYFRAME_KEY_LIST_SYM maybe_space key_list TOKEN_EOF {
parser->m_valueList = parser->sinkFloatingValueList($3);
}
;
internal_decls:
INTERNAL_DECLS_SYM maybe_space_before_declaration declaration_list TOKEN_EOF {
/* can be empty */
}
;
internal_value:
INTERNAL_VALUE_SYM maybe_space expr TOKEN_EOF {
parser->m_valueList = parser->sinkFloatingValueList($3);
int oldParsedProperties = parser->m_parsedProperties.size();
if (!parser->parseValue(parser->m_id, parser->m_important))
parser->rollbackLastProperties(parser->m_parsedProperties.size() - oldParsedProperties);
parser->m_valueList = nullptr;
}
;
internal_medialist:
INTERNAL_MEDIALIST_SYM maybe_space location_label maybe_media_list TOKEN_EOF {
parser->m_mediaList = $4;
}
;
internal_selector:
INTERNAL_SELECTOR_SYM maybe_space selector_list TOKEN_EOF {
if (parser->m_selectorListForParseSelector)
parser->m_selectorListForParseSelector->adoptSelectorVector(*$3);
}
;
internal_supports_condition:
INTERNAL_SUPPORTS_CONDITION_SYM maybe_space supports_condition TOKEN_EOF {
parser->m_supportsCondition = $3;
}
;
space:
WHITESPACE
| space WHITESPACE
;
maybe_space:
/* empty */ %prec UNIMPORTANT_TOK
| space
;
maybe_sgml:
/* empty */
| maybe_sgml SGML_CD
| maybe_sgml WHITESPACE
;
maybe_charset:
/* empty */
| charset
;
closing_brace:
'}'
| %prec LOWEST_PREC TOKEN_EOF
;
closing_parenthesis:
')'
| %prec LOWEST_PREC TOKEN_EOF
;
closing_square_bracket:
']'
| %prec LOWEST_PREC TOKEN_EOF
;
semi_or_eof:
';'
| TOKEN_EOF
;
charset:
CHARSET_SYM maybe_space STRING maybe_space semi_or_eof {
if (parser->m_styleSheet)
parser->m_styleSheet->parserSetEncodingFromCharsetRule($3);
parser->startEndUnknownRule();
$$ = 0;
}
| CHARSET_SYM at_rule_recovery {
$$ = 0;
}
;
rule_list:
/* empty */
| rule_list rule maybe_sgml {
if ($2 && parser->m_styleSheet)
parser->m_styleSheet->parserAppendRule($2);
}
;
valid_rule:
ruleset
| media
| page
| font_face
| keyframes
| namespace
| import
| region
| supports
| host
| viewport
| filter
;
rule:
valid_rule {
parser->m_hadSyntacticallyValidCSSRule = true;
}
| invalid_rule
;
block_rule_body:
block_rule_list
| block_rule_list error error_location rule_error_recovery {
parser->reportError($3, CSSParser::InvalidRuleError);
}
;
block_rule_list:
/* empty */ { $$ = 0; }
| block_rule_list block_rule maybe_sgml {
$$ = $1;
if ($2) {
if (!$$)
$$ = parser->createRuleList();
$$->append($2);
}
}
;
region_block_rule_body:
region_block_rule_list
| region_block_rule_list error error_location rule_error_recovery {
parser->reportError($3, CSSParser::InvalidRuleError);
}
;
region_block_rule_list:
/* empty */ { $$ = 0; }
| region_block_rule_list block_valid_rule maybe_sgml {
$$ = $1;
if ($2) {
if (!$$)
$$ = parser->createRuleList();
$$->append($2);
}
}
;
block_valid_rule:
ruleset
| page
| font_face
| media
| keyframes
| supports
| viewport
| filter
;
block_rule:
block_valid_rule
| invalid_rule
| namespace
| import
| region
;
at_import_header_end_maybe_space:
maybe_space {
parser->endRuleHeader();
parser->startRuleBody();
}
;
before_import_rule:
/* empty */ {
parser->startRuleHeader(CSSRuleSourceData::IMPORT_RULE);
}
;
import:
before_import_rule IMPORT_SYM at_import_header_end_maybe_space string_or_uri maybe_space location_label maybe_media_list semi_or_eof {
$$ = parser->createImportRule($4, $7);
}
| before_import_rule IMPORT_SYM at_import_header_end_maybe_space string_or_uri maybe_space location_label maybe_media_list invalid_block {
$$ = 0;
parser->endRuleBody(true);
}
| before_import_rule IMPORT_SYM at_rule_recovery {
$$ = 0;
parser->endRuleBody(true);
}
;
before_namespace_rule:
/* empty */ {
// FIXME: There should be parser->startRuleHeader.
}
;
namespace:
before_namespace_rule NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space semi_or_eof {
parser->addNamespace($4, $5);
$$ = 0;
}
| before_namespace_rule NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space invalid_block {
$$ = 0;
}
| before_namespace_rule NAMESPACE_SYM at_rule_recovery {
$$ = 0;
}
;
maybe_ns_prefix:
/* empty */ { $$.clear(); }
| IDENT maybe_space
;
string_or_uri:
STRING
| URI
;
maybe_media_value:
/*empty*/ {
$$ = 0;
}
| ':' maybe_space expr {
$$ = $3;
}
;
media_query_exp:
'(' maybe_space IDENT maybe_space maybe_media_value closing_parenthesis {
parser->tokenToLowerCase($3);
$$ = parser->createFloatingMediaQueryExp($3, $5);
if (!$$)
YYERROR;
}
| '(' error error_recovery closing_parenthesis {
YYERROR;
}
;
media_query_exp_list:
media_query_exp {
$$ = parser->createFloatingMediaQueryExpList();
$$->append(parser->sinkFloatingMediaQueryExp($1));
}
| media_query_exp_list space MEDIA_AND space media_query_exp {
$$ = $1;
$$->append(parser->sinkFloatingMediaQueryExp($5));
}
;
maybe_and_media_query_exp_list:
maybe_space {
$$ = parser->createFloatingMediaQueryExpList();
}
| space MEDIA_AND space media_query_exp_list maybe_space {
$$ = $4;
}
;
maybe_media_restrictor:
/*empty*/ {
$$ = MediaQuery::None;
}
| MEDIA_ONLY space {
$$ = MediaQuery::Only;
}
| MEDIA_NOT space {
$$ = MediaQuery::Not;
}
;
valid_media_query:
media_query_exp_list maybe_space {
$$ = parser->createFloatingMediaQuery(parser->sinkFloatingMediaQueryExpList($1));
}
| maybe_media_restrictor medium maybe_and_media_query_exp_list {
parser->tokenToLowerCase($2);
$$ = parser->createFloatingMediaQuery($1, $2, parser->sinkFloatingMediaQueryExpList($3));
}
;
media_query:
valid_media_query
| valid_media_query error error_location rule_error_recovery {
parser->reportError(parser->lastLocationLabel(), CSSParser::InvalidMediaQueryError);
$$ = parser->createFloatingNotAllQuery();
}
| error error_location rule_error_recovery {
parser->reportError(parser->lastLocationLabel(), CSSParser::InvalidMediaQueryError);
$$ = parser->createFloatingNotAllQuery();
}
;
maybe_media_list:
/* empty */ {
$$ = parser->createMediaQuerySet();
}
| media_list
;
media_list:
media_query {
$$ = parser->createMediaQuerySet();
$$->addMediaQuery(parser->sinkFloatingMediaQuery($1));
}
| mq_list media_query {
$$ = $1;
$$->addMediaQuery(parser->sinkFloatingMediaQuery($2));
}
| mq_list {
$$ = $1;
$$->addMediaQuery(parser->sinkFloatingMediaQuery(parser->createFloatingNotAllQuery()));
}
;
mq_list:
media_query ',' maybe_space location_label {
$$ = parser->createMediaQuerySet();
$$->addMediaQuery(parser->sinkFloatingMediaQuery($1));
}
| mq_list media_query ',' maybe_space location_label {
$$ = $1;
$$->addMediaQuery(parser->sinkFloatingMediaQuery($2));
}
;
at_rule_body_start:
/* empty */ {
parser->startRuleBody();
}
;
before_media_rule:
/* empty */ {
parser->startRuleHeader(CSSRuleSourceData::MEDIA_RULE);
}
;
at_rule_header_end_maybe_space:
maybe_space {
parser->endRuleHeader();
}
;
media:
before_media_rule MEDIA_SYM maybe_space location_label media_list at_rule_header_end '{' at_rule_body_start maybe_space block_rule_body closing_brace {
$$ = parser->createMediaRule($5, $10);
}
| before_media_rule MEDIA_SYM at_rule_header_end_maybe_space '{' at_rule_body_start maybe_space block_rule_body closing_brace {
$$ = parser->createMediaRule(0, $7);
}
| before_media_rule MEDIA_SYM maybe_space location_label media_list semi_or_eof {
$$ = 0;
parser->endRuleBody(true);
}
| before_media_rule MEDIA_SYM at_rule_recovery {
$$ = 0;
parser->endRuleBody(true);
}
;
medium:
IDENT
;
supports:
before_supports_rule SUPPORTS_SYM maybe_space supports_condition at_supports_rule_header_end '{' at_rule_body_start maybe_space block_rule_body closing_brace {
$$ = parser->createSupportsRule($4, $9);
}
| before_supports_rule SUPPORTS_SYM error error_location rule_error_recovery at_rule_end {
$$ = 0;
parser->reportError($4, CSSParser::InvalidSupportsConditionError);
parser->endRuleBody(true);
parser->popSupportsRuleData();
}
;
before_supports_rule:
/* empty */ {
parser->startRuleHeader(CSSRuleSourceData::SUPPORTS_RULE);
parser->markSupportsRuleHeaderStart();
}
;
at_supports_rule_header_end:
/* empty */ {
parser->endRuleHeader();
parser->markSupportsRuleHeaderEnd();
}
;
supports_condition:
supports_condition_in_parens
| supports_negation
| supports_conjunction
| supports_disjunction
;
supports_negation:
SUPPORTS_NOT maybe_space supports_condition_in_parens {
$$ = !$3;
}
;
supports_conjunction:
supports_condition_in_parens SUPPORTS_AND maybe_space supports_condition_in_parens {
$$ = $1 && $4;
}
| supports_conjunction SUPPORTS_AND maybe_space supports_condition_in_parens {
$$ = $1 && $4;
}
;
supports_disjunction:
supports_condition_in_parens SUPPORTS_OR maybe_space supports_condition_in_parens {
$$ = $1 || $4;
}
| supports_disjunction SUPPORTS_OR maybe_space supports_condition_in_parens {
$$ = $1 || $4;
}
;
supports_condition_in_parens:
'(' maybe_space supports_condition closing_parenthesis maybe_space {
$$ = $3;
}
| supports_declaration_condition
| '(' error error_location error_recovery closing_parenthesis maybe_space {
parser->reportError($3, CSSParser::InvalidSupportsConditionError);
$$ = false;
}
;
supports_declaration_condition:
'(' maybe_space IDENT maybe_space ':' maybe_space expr prio closing_parenthesis maybe_space {
$$ = false;
CSSPropertyID id = cssPropertyID($3);
if (id != CSSPropertyInvalid) {
parser->m_valueList = parser->sinkFloatingValueList($7);
int oldParsedProperties = parser->m_parsedProperties.size();
$$ = parser->parseValue(id, $8);
// We just need to know if the declaration is supported as it is written. Rollback any additions.
if ($$)
parser->rollbackLastProperties(parser->m_parsedProperties.size() - oldParsedProperties);
}
parser->m_valueList = nullptr;
parser->endProperty($8, false);
}
| '(' maybe_space IDENT maybe_space ':' maybe_space error error_recovery closing_parenthesis maybe_space {
$$ = false;
parser->endProperty(false, false, CSSParser::GeneralError);
}
;
before_keyframes_rule:
/* empty */ {
parser->startRuleHeader(CSSRuleSourceData::KEYFRAMES_RULE);
}
;
keyframes:
before_keyframes_rule KEYFRAMES_SYM maybe_space keyframe_name at_rule_header_end_maybe_space '{' at_rule_body_start maybe_space location_label keyframes_rule closing_brace {
$$ = parser->createKeyframesRule($4, parser->sinkFloatingKeyframeVector($10), false /* isPrefixed */);
}
|
before_keyframes_rule WEBKIT_KEYFRAMES_SYM maybe_space keyframe_name at_rule_header_end_maybe_space '{' at_rule_body_start maybe_space location_label keyframes_rule closing_brace {
$$ = parser->createKeyframesRule($4, parser->sinkFloatingKeyframeVector($10), true /* isPrefixed */);
}
| before_keyframes_rule KEYFRAMES_SYM at_rule_recovery {
$$ = 0;
parser->endRuleBody(true);
}
| before_keyframes_rule WEBKIT_KEYFRAMES_SYM at_rule_recovery {
$$ = 0;
parser->endRuleBody(true);
}
;
keyframe_name:
IDENT
| STRING
;
keyframes_rule:
keyframe_rule_list
| keyframe_rule_list keyframes_error_recovery {
parser->clearProperties();
};
keyframe_rule_list:
/* empty */ {
$$ = parser->createFloatingKeyframeVector();
parser->resumeErrorLogging();
}
| keyframe_rule_list keyframe_rule maybe_space location_label {
$$ = $1;
$$->append($2);
}
| keyframe_rule_list keyframes_error_recovery invalid_block maybe_space location_label {
parser->clearProperties();
parser->resumeErrorLogging();
}
;
keyframe_rule:
key_list '{' maybe_space declaration_list closing_brace {
$$ = parser->createKeyframe($1);
}
;
key_list:
key maybe_space {
$$ = parser->createFloatingValueList();
$$->addValue(parser->sinkFloatingValue($1));
}
| key_list ',' maybe_space key maybe_space {
$$ = $1;
$$->addValue(parser->sinkFloatingValue($4));
}
;
key:
maybe_unary_operator PERCENTAGE {
$$.setFromNumber($1 * $2);
}
| IDENT {
if ($1.equalIgnoringCase("from"))
$$.setFromNumber(0);
else if ($1.equalIgnoringCase("to"))
$$.setFromNumber(100);
else {
YYERROR;
}
}
;
keyframes_error_recovery:
error rule_error_recovery {
parser->reportError(parser->lastLocationLabel(), CSSParser::InvalidKeyframeSelectorError);
}
;
before_page_rule:
/* empty */ {
parser->startRuleHeader(CSSRuleSourceData::PAGE_RULE);
}
;
page:
before_page_rule PAGE_SYM maybe_space page_selector at_rule_header_end
'{' at_rule_body_start maybe_space_before_declaration declarations_and_margins closing_brace {
if ($4)
$$ = parser->createPageRule(parser->sinkFloatingSelector($4));
else {
// Clear properties in the invalid @page rule.
parser->clearProperties();
// Also clear margin at-rules here once we fully implement margin at-rules parsing.
$$ = 0;
parser->endRuleBody(true);
}
}
| before_page_rule PAGE_SYM at_rule_recovery {
parser->endRuleBody(true);
$$ = 0;
}
;
page_selector:
IDENT maybe_space {
$$ = parser->createFloatingSelectorWithTagName(QualifiedName(nullAtom, $1, parser->m_defaultNamespace));
$$->setForPage();
}
| IDENT pseudo_page maybe_space {
$$ = $2;
$$->prependTagSelector(QualifiedName(nullAtom, $1, parser->m_defaultNamespace));
$$->setForPage();
}
| pseudo_page maybe_space {
$$ = $1;
$$->setForPage();
}
| /* empty */ {
$$ = parser->createFloatingSelector();
$$->setForPage();
}
;
declarations_and_margins:
declaration_list
| declarations_and_margins margin_box maybe_space declaration_list
;
margin_box:
margin_sym {
parser->startDeclarationsForMarginBox();
} maybe_space '{' maybe_space declaration_list closing_brace {
$$ = 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;
}
;
before_font_face_rule:
/* empty */ {
parser->startRuleHeader(CSSRuleSourceData::FONT_FACE_RULE);
}
;
font_face:
before_font_face_rule FONT_FACE_SYM at_rule_header_end_maybe_space
'{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace {
$$ = parser->createFontFaceRule();
}
| before_font_face_rule FONT_FACE_SYM at_rule_recovery {
$$ = 0;
parser->endRuleBody(true);
}
;
before_host_rule:
/* empty */ {
parser->startRuleHeader(CSSRuleSourceData::HOST_RULE);
}
;
host:
before_host_rule HOST_SYM at_rule_header_end_maybe_space
'{' at_rule_body_start maybe_space block_rule_body closing_brace {
$$ = parser->createHostRule($7);
}
| before_host_rule HOST_SYM at_rule_recovery {
$$ = 0;
parser->endRuleBody(true);
}
;
before_viewport_rule:
/* empty */ {
parser->markViewportRuleBodyStart();
parser->startRuleHeader(CSSRuleSourceData::VIEWPORT_RULE);
}
;
viewport:
before_viewport_rule VIEWPORT_RULE_SYM at_rule_header_end_maybe_space
'{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace {
$$ = parser->createViewportRule();
parser->markViewportRuleBodyEnd();
}
| before_viewport_rule VIEWPORT_RULE_SYM at_rule_recovery {
$$ = 0;
parser->endRuleBody(true);
parser->markViewportRuleBodyEnd();
}
;
region_selector:
selector_list {
parser->setReusableRegionSelectorVector($1);
$$ = parser->reusableRegionSelectorVector();
}
;
before_region_rule:
/* empty */ {
parser->startRuleHeader(CSSRuleSourceData::REGION_RULE);
}
;
region:
before_region_rule WEBKIT_REGION_RULE_SYM maybe_space region_selector at_rule_header_end '{' at_rule_body_start maybe_space region_block_rule_body closing_brace {
$$ = parser->createRegionRule($4, $9);
}
| before_region_rule WEBKIT_REGION_RULE_SYM at_rule_recovery {
$$ = 0;
parser->endRuleBody(true);
}
;
before_filter_rule:
/* empty */ {
parser->startRuleHeader(CSSRuleSourceData::FILTER_RULE);
parser->m_inFilterRule = true;
}
;
filter:
before_filter_rule WEBKIT_FILTER_RULE_SYM maybe_space IDENT at_rule_header_end_maybe_space
'{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace {
parser->m_inFilterRule = false;
$$ = parser->createFilterRule($4);
}
| before_filter_rule WEBKIT_FILTER_RULE_SYM at_rule_recovery {
$$ = 0;
}
;
combinator:
'+' maybe_space { $$ = CSSSelector::DirectAdjacent; }
| '~' maybe_space { $$ = CSSSelector::IndirectAdjacent; }
| '>' maybe_space { $$ = CSSSelector::Child; }
| '^' maybe_space {
if (!RuntimeEnabledFeatures::shadowDOMEnabled())
YYERROR;
$$ = CSSSelector::ChildTree;
}
| '^' '^' maybe_space {
if (!RuntimeEnabledFeatures::shadowDOMEnabled())
YYERROR;
$$ = CSSSelector::DescendantTree;
}
;
maybe_unary_operator:
unary_operator
| /* empty */ { $$ = 1; }
;
unary_operator:
'-' { $$ = -1; }
| '+' { $$ = 1; }
;
maybe_space_before_declaration:
maybe_space {
parser->startProperty();
}
;
before_selector_list:
/* empty */ {
parser->startRuleHeader(CSSRuleSourceData::STYLE_RULE);
parser->startSelector();
}
;
at_rule_header_end:
/* empty */ {
parser->endRuleHeader();
}
;
at_selector_end:
/* empty */ {
parser->endSelector();
}
;
ruleset:
before_selector_list selector_list at_selector_end at_rule_header_end '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace {
$$ = parser->createStyleRule($2);
}
;
before_selector_group_item:
/* empty */ {
parser->startSelector();
}
selector_list:
selector %prec UNIMPORTANT_TOK {
$$ = parser->reusableSelectorVector();
$$->shrink(0);
$$->append(parser->sinkFloatingSelector($1));
}
| selector_list at_selector_end ',' maybe_space before_selector_group_item selector %prec UNIMPORTANT_TOK {
$$ = $1;
$$->append(parser->sinkFloatingSelector($6));
}
;
relative_selector:
combinator selector {
$$ = $2;
CSSParserSelector* end = $$;
while (end->tagHistory())
end = end->tagHistory();
end->setRelation($1);
}
| selector
;
selector:
simple_selector
| selector WHITESPACE
| selector WHITESPACE simple_selector
{
$$ = $3;
CSSParserSelector* end = $$;
while (end->tagHistory())
end = end->tagHistory();
end->setRelation(CSSSelector::Descendant);
if ($1->isContentPseudoElement())
end->setRelationIsAffectedByPseudoContent();
end->setTagHistory(parser->sinkFloatingSelector($1));
}
| selector combinator simple_selector {
$$ = $3;
CSSParserSelector* end = $$;
while (end->tagHistory())
end = end->tagHistory();
end->setRelation($2);
if ($1->isContentPseudoElement())
end->setRelationIsAffectedByPseudoContent();
end->setTagHistory(parser->sinkFloatingSelector($1));
}
;
namespace_selector:
/* empty */ '|' { $$.clear(); }
| '*' '|' { static const LChar star = '*'; $$.init(&star, 1); }
| IDENT '|'
;
simple_selector:
element_name {
$$ = parser->createFloatingSelectorWithTagName(QualifiedName(nullAtom, $1, parser->m_defaultNamespace));
}
| element_name specifier_list {
$$ = parser->rewriteSpecifiersWithElementName(nullAtom, $1, $2);
if (!$$)
YYERROR;
}
| specifier_list {
$$ = parser->rewriteSpecifiersWithNamespaceIfNeeded($1);
if (!$$)
YYERROR;
}
| namespace_selector element_name {
$$ = parser->createFloatingSelectorWithTagName(parser->determineNameInNamespace($1, $2));
if (!$$)
YYERROR;
}
| namespace_selector element_name specifier_list {
$$ = parser->rewriteSpecifiersWithElementName($1, $2, $3);
if (!$$)
YYERROR;
}
| namespace_selector specifier_list {
$$ = parser->rewriteSpecifiersWithElementName($1, starAtom, $2);
if (!$$)
YYERROR;
}
;
simple_selector_list:
simple_selector %prec UNIMPORTANT_TOK {
$$ = parser->createFloatingSelectorVector();
$$->append(parser->sinkFloatingSelector($1));
}
| simple_selector_list maybe_space ',' maybe_space simple_selector %prec UNIMPORTANT_TOK {
$$ = $1;
$$->append(parser->sinkFloatingSelector($5));
}
;
element_name:
IDENT {
if (parser->m_context.isHTMLDocument)
parser->tokenToLowerCase($1);
$$ = $1;
}
| '*' {
static const LChar star = '*';
$$.init(&star, 1);
}
;
specifier_list:
specifier
| specifier_list specifier {
$$ = parser->rewriteSpecifiers($1, $2);
}
;
specifier:
IDSEL {
$$ = parser->createFloatingSelector();
$$->setMatch(CSSSelector::Id);
if (isQuirksModeBehavior(parser->m_context.mode))
parser->tokenToLowerCase($1);
$$->setValue($1);
}
| HEX {
if ($1[0] >= '0' && $1[0] <= '9') {
YYERROR;
} else {
$$ = parser->createFloatingSelector();
$$->setMatch(CSSSelector::Id);
if (isQuirksModeBehavior(parser->m_context.mode))
parser->tokenToLowerCase($1);
$$->setValue($1);
}
}
| class
| attrib
| pseudo
;
class:
'.' IDENT {
$$ = parser->createFloatingSelector();
$$->setMatch(CSSSelector::Class);
if (isQuirksModeBehavior(parser->m_context.mode))
parser->tokenToLowerCase($2);
$$->setValue($2);
}
;
attr_name:
IDENT maybe_space {
if (parser->m_context.isHTMLDocument)
parser->tokenToLowerCase($1);
$$ = $1;
}
;
attrib:
'[' maybe_space attr_name closing_square_bracket {
$$ = parser->createFloatingSelector();
$$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
$$->setMatch(CSSSelector::Set);
}
| '[' maybe_space attr_name match maybe_space ident_or_string maybe_space closing_square_bracket {
$$ = parser->createFloatingSelector();
$$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
$$->setMatch((CSSSelector::Match)$4);
$$->setValue($6);
}
| '[' maybe_space namespace_selector attr_name closing_square_bracket {
$$ = parser->createFloatingSelector();
$$->setAttribute(parser->determineNameInNamespace($3, $4));
$$->setMatch(CSSSelector::Set);
}
| '[' maybe_space namespace_selector attr_name match maybe_space ident_or_string maybe_space closing_square_bracket {
$$ = parser->createFloatingSelector();
$$->setAttribute(parser->determineNameInNamespace($3, $4));
$$->setMatch((CSSSelector::Match)$5);
$$->setValue($7);
}
| '[' selector_recovery closing_square_bracket {
YYERROR;
}
;
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 {
if ($2.isFunction())
YYERROR;
$$ = parser->createFloatingSelector();
$$->setMatch(CSSSelector::PagePseudoClass);
parser->tokenToLowerCase($2);
$$->setValue($2);
CSSSelector::PseudoType type = $$->pseudoType();
if (type == CSSSelector::PseudoUnknown)
YYERROR;
}
pseudo:
':' error_location IDENT {
if ($3.isFunction())
YYERROR;
$$ = parser->createFloatingSelector();
$$->setMatch(CSSSelector::PseudoClass);
parser->tokenToLowerCase($3);
$$->setValue($3);
CSSSelector::PseudoType type = $$->pseudoType();
if (type == CSSSelector::PseudoUnknown) {
parser->reportError($2, CSSParser::InvalidSelectorPseudoError);
YYERROR;
}
}
| ':' ':' error_location IDENT {
if ($4.isFunction())
YYERROR;
$$ = parser->createFloatingSelector();
$$->setMatch(CSSSelector::PseudoElement);
parser->tokenToLowerCase($4);
$$->setValue($4);
// FIXME: This call is needed to force selector to compute the pseudoType early enough.
CSSSelector::PseudoType type = $$->pseudoType();
if (type == CSSSelector::PseudoUnknown) {
parser->reportError($3, CSSParser::InvalidSelectorPseudoError);
YYERROR;
}
}
// used by ::cue(:past/:future)
| ':' ':' CUEFUNCTION maybe_space simple_selector_list maybe_space closing_parenthesis {
$$ = parser->createFloatingSelector();
$$->setMatch(CSSSelector::PseudoElement);
$$->adoptSelectorVector(*parser->sinkFloatingSelectorVector($5));
$$->setValue($3);
CSSSelector::PseudoType type = $$->pseudoType();
if (type != CSSSelector::PseudoCue)
YYERROR;
}
| ':' ':' CUEFUNCTION selector_recovery closing_parenthesis {
YYERROR;
}
| ':' ':' DISTRIBUTEDFUNCTION maybe_space relative_selector closing_parenthesis {
$$ = parser->createFloatingSelector();
$$->setMatch(CSSSelector::PseudoElement);
$$->setFunctionArgumentSelector($5);
parser->tokenToLowerCase($3);
$$->setValue($3);
}
| ':' ':' DISTRIBUTEDFUNCTION selector_recovery closing_parenthesis {
YYERROR;
}
// use by :-webkit-any.
// FIXME: should we support generic selectors here or just simple_selectors?
// Use simple_selector_list for now to match -moz-any.
// See http://lists.w3.org/Archives/Public/www-style/2010Sep/0566.html for some
// related discussion with respect to :not.
| ':' ANYFUNCTION maybe_space simple_selector_list maybe_space closing_parenthesis {
$$ = parser->createFloatingSelector();
$$->setMatch(CSSSelector::PseudoClass);
$$->adoptSelectorVector(*parser->sinkFloatingSelectorVector($4));
parser->tokenToLowerCase($2);
$$->setValue($2);
CSSSelector::PseudoType type = $$->pseudoType();
if (type != CSSSelector::PseudoAny)
YYERROR;
}
| ':' ANYFUNCTION selector_recovery closing_parenthesis {
YYERROR;
}
// used by :nth-*(ax+b)
| ':' FUNCTION maybe_space NTH maybe_space closing_parenthesis {
$$ = parser->createFloatingSelector();
$$->setMatch(CSSSelector::PseudoClass);
$$->setArgument($4);
$$->setValue($2);
CSSSelector::PseudoType type = $$->pseudoType();
if (type == CSSSelector::PseudoUnknown)
YYERROR;
}
// used by :nth-*
| ':' FUNCTION maybe_space maybe_unary_operator INTEGER maybe_space closing_parenthesis {
$$ = parser->createFloatingSelector();
$$->setMatch(CSSSelector::PseudoClass);
$$->setArgument(String::number($4 * $5));
$$->setValue($2);
CSSSelector::PseudoType type = $$->pseudoType();
if (type == CSSSelector::PseudoUnknown)
YYERROR;
}
// used by :nth-*(odd/even) and :lang
| ':' FUNCTION maybe_space IDENT maybe_space closing_parenthesis {
$$ = parser->createFloatingSelector();
$$->setMatch(CSSSelector::PseudoClass);
$$->setArgument($4);
parser->tokenToLowerCase($2);
$$->setValue($2);
CSSSelector::PseudoType type = $$->pseudoType();
if (type == CSSSelector::PseudoUnknown)
YYERROR;
else if (type == CSSSelector::PseudoNthChild ||
type == CSSSelector::PseudoNthOfType ||
type == CSSSelector::PseudoNthLastChild ||
type == CSSSelector::PseudoNthLastOfType) {
if (!isValidNthToken($4))
YYERROR;
}
}
| ':' FUNCTION selector_recovery closing_parenthesis {
YYERROR;
}
// used by :not
| ':' NOTFUNCTION maybe_space simple_selector maybe_space closing_parenthesis {
if (!$4->isSimple())
YYERROR;
else {
$$ = parser->createFloatingSelector();
$$->setMatch(CSSSelector::PseudoClass);
Vector<OwnPtr<CSSParserSelector> > selectorVector;
selectorVector.append(parser->sinkFloatingSelector($4));
$$->adoptSelectorVector(selectorVector);
parser->tokenToLowerCase($2);
$$->setValue($2);
}
}
| ':' NOTFUNCTION selector_recovery closing_parenthesis {
YYERROR;
}
| ':' ':' PARTFUNCTION maybe_space IDENT maybe_space closing_parenthesis {
$$ = parser->createFloatingSelector();
$$->setMatch(CSSSelector::PseudoElement);
$$->setArgument($5);
if ($5.startsWithIgnoringCase("-webkit"))
$$->setMatchUserAgentOnly();
parser->tokenToLowerCase($3);
$$->setValue($3);
CSSSelector::PseudoType type = $$->pseudoType();
if (type != CSSSelector::PseudoPart)
YYERROR;
}
| ':' ':' PARTFUNCTION selector_recovery closing_parenthesis {
YYERROR;
}
| ':' HOSTFUNCTION maybe_space simple_selector_list maybe_space closing_parenthesis {
$$ = parser->createFloatingSelector();
$$->setMatch(CSSSelector::PseudoClass);
$$->adoptSelectorVector(*parser->sinkFloatingSelectorVector($4));
parser->tokenToLowerCase($2);
$$->setValue($2);
CSSSelector::PseudoType type = $$->pseudoType();
if (type != CSSSelector::PseudoHost)
YYERROR;
}
// used by :host()
| ':' HOSTFUNCTION maybe_space closing_parenthesis {
$$ = parser->createFloatingSelector();
$$->setMatch(CSSSelector::PseudoClass);
parser->tokenToLowerCase($2);
$$->setValue($2.atomicSubstring(0, $2.length() - 1));
CSSSelector::PseudoType type = $$->pseudoType();
if (type != CSSSelector::PseudoHost)
YYERROR;
}
| ':' HOSTFUNCTION selector_recovery closing_parenthesis {
YYERROR;
}
;
selector_recovery:
error error_location error_recovery;
declaration_list:
/* empty */ { $$ = false; }
| declaration
| decl_list declaration {
$$ = $1 || $2;
}
| decl_list
;
decl_list:
declaration ';' maybe_space {
parser->startProperty();
$$ = $1;
}
| decl_list declaration ';' maybe_space {
parser->startProperty();
$$ = $1 || $2;
}
;
declaration:
VAR_DEFINITION maybe_space ':' maybe_space expr prio {
parser->storeVariableDeclaration($1, parser->sinkFloatingValueList($5), $6);
$$ = true;
parser->endProperty($6, true);
}
|
property ':' maybe_space error_location expr prio {
$$ = false;
bool isPropertyParsed = false;
if ($1 != CSSPropertyInvalid) {
parser->m_valueList = parser->sinkFloatingValueList($5);
int oldParsedProperties = parser->m_parsedProperties.size();
$$ = parser->parseValue($1, $6);
if (!$$) {
parser->rollbackLastProperties(parser->m_parsedProperties.size() - oldParsedProperties);
parser->reportError($4, CSSParser::InvalidPropertyValueError);
} else
isPropertyParsed = true;
parser->m_valueList = nullptr;
}
parser->endProperty($6, isPropertyParsed);
}
|
property ':' maybe_space error_location expr prio error error_recovery {
/* When we encounter something like p {color: red !important fail;} we should drop the declaration */
parser->reportError($4, CSSParser::InvalidPropertyValueError);
parser->endProperty(false, false);
$$ = false;
}
|
property ':' maybe_space error_location error error_recovery {
parser->reportError($4, CSSParser::InvalidPropertyValueError);
parser->endProperty(false, false);
$$ = false;
}
|
property error error_location error_recovery {
parser->reportError($3, CSSParser::PropertyDeclarationError);
parser->endProperty(false, false, CSSParser::GeneralError);
$$ = false;
}
|
error error_location error_recovery {
parser->reportError($2, CSSParser::PropertyDeclarationError);
$$ = false;
}
;
property:
error_location IDENT maybe_space {
$$ = cssPropertyID($2);
parser->setCurrentProperty($$);
if ($$ == CSSPropertyInvalid)
parser->reportError($1, CSSParser::InvalidPropertyError);
}
;
prio:
IMPORTANT_SYM maybe_space { $$ = true; }
| /* empty */ { $$ = false; }
;
expr:
term {
$$ = parser->createFloatingValueList();
$$->addValue(parser->sinkFloatingValue($1));
}
| expr operator term {
$$ = $1;
$$->addValue(makeOperatorValue($2));
$$->addValue(parser->sinkFloatingValue($3));
}
| expr term {
$$ = $1;
$$->addValue(parser->sinkFloatingValue($2));
}
;
expr_recovery:
error error_location error_recovery {
parser->reportError($2, CSSParser::PropertyDeclarationError);
}
;
operator:
'/' maybe_space {
$$ = '/';
}
| ',' maybe_space {
$$ = ',';
}
;
term:
unary_term maybe_space
| unary_operator unary_term maybe_space { $$ = $2; $$.fValue *= $1; }
| STRING maybe_space { $$.id = CSSValueInvalid; $$.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 = CSSValueInvalid; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
| unary_operator DIMEN maybe_space { $$.id = CSSValueInvalid; $$.string = $2; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
| URI maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI; }
| UNICODERANGE maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE; }
| HEX maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; }
| '#' maybe_space { $$.id = CSSValueInvalid; $$.string = CSSParserString(); $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } /* Handle error case: "color: #;" */
| VARFUNCTION maybe_space IDENT closing_parenthesis maybe_space {
$$.id = CSSValueInvalid;
$$.string = $3;
$$.unit = CSSPrimitiveValue::CSS_VARIABLE_NAME;
}
| VARFUNCTION maybe_space expr_recovery closing_parenthesis {
YYERROR;
}
/* FIXME: according to the specs a function can have a unary_operator in front. I know no case where this makes sense */
| function maybe_space
| calc_function maybe_space
| min_or_max_function maybe_space
| '%' maybe_space { /* Handle width: %; */
$$.id = CSSValueInvalid; $$.unit = 0;
}
;
unary_term:
INTEGER { $$.setFromNumber($1); $$.isInt = true; }
| FLOATTOKEN { $$.setFromNumber($1); }
| PERCENTAGE { $$.setFromNumber($1, CSSPrimitiveValue::CSS_PERCENTAGE); }
| PXS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_PX); }
| CMS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_CM); }
| MMS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_MM); }
| INS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_IN); }
| PTS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_PT); }
| PCS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_PC); }
| DEGS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_DEG); }
| RADS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_RAD); }
| GRADS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_GRAD); }
| TURNS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_TURN); }
| MSECS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_MS); }
| SECS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_S); }
| HERTZ { $$.setFromNumber($1, CSSPrimitiveValue::CSS_HZ); }
| KHERTZ { $$.setFromNumber($1, CSSPrimitiveValue::CSS_KHZ); }
| EMS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_EMS); }
| QEMS { $$.setFromNumber($1, CSSParserValue::Q_EMS); }
| EXS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_EXS); }
| REMS {
$$.setFromNumber($1, CSSPrimitiveValue::CSS_REMS);
if (parser->m_styleSheet)
parser->m_styleSheet->parserSetUsesRemUnits(true);
}
| CHS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_CHS); }
| VW { $$.setFromNumber($1, CSSPrimitiveValue::CSS_VW); }
| VH { $$.setFromNumber($1, CSSPrimitiveValue::CSS_VH); }
| VMIN { $$.setFromNumber($1, CSSPrimitiveValue::CSS_VMIN); }
| VMAX { $$.setFromNumber($1, CSSPrimitiveValue::CSS_VMAX); }
| DPPX { $$.setFromNumber($1, CSSPrimitiveValue::CSS_DPPX); }
| DPI { $$.setFromNumber($1, CSSPrimitiveValue::CSS_DPI); }
| DPCM { $$.setFromNumber($1, CSSPrimitiveValue::CSS_DPCM); }
| FR { $$.setFromNumber($1, CSSPrimitiveValue::CSS_FR); }
;
function:
FUNCTION maybe_space expr closing_parenthesis {
$$.setFromFunction(parser->createFloatingFunction($1, parser->sinkFloatingValueList($3)));
} |
FUNCTION maybe_space closing_parenthesis {
$$.setFromFunction(parser->createFloatingFunction($1, parser->sinkFloatingValueList(parser->createFloatingValueList())));
} |
FUNCTION maybe_space expr_recovery closing_parenthesis {
YYERROR;
}
;
calc_func_term:
unary_term
| VARFUNCTION maybe_space IDENT closing_parenthesis {
$$.id = CSSValueInvalid;
$$.string = $3;
$$.unit = CSSPrimitiveValue::CSS_VARIABLE_NAME;
}
| unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
;
calc_func_operator:
space '+' space {
$$ = '+';
}
| space '-' space {
$$ = '-';
}
| calc_maybe_space '*' maybe_space {
$$ = '*';
}
| calc_maybe_space '/' maybe_space {
$$ = '/';
}
;
calc_maybe_space:
/* empty */
| WHITESPACE
;
calc_func_paren_expr:
'(' maybe_space calc_func_expr calc_maybe_space closing_parenthesis {
$$ = $3;
$$->insertValueAt(0, makeOperatorValue('('));
$$->addValue(makeOperatorValue(')'));
}
| '(' maybe_space expr_recovery closing_parenthesis {
YYERROR;
}
;
calc_func_expr:
calc_func_term {
$$ = parser->createFloatingValueList();
$$->addValue(parser->sinkFloatingValue($1));
}
| calc_func_expr calc_func_operator calc_func_term {
$$ = $1;
$$->addValue(makeOperatorValue($2));
$$->addValue(parser->sinkFloatingValue($3));
}
| calc_func_expr calc_func_operator calc_func_paren_expr {
$$ = $1;
$$->addValue(makeOperatorValue($2));
$$->extend(*($3));
}
| calc_func_paren_expr
;
calc_func_expr_list:
calc_func_expr calc_maybe_space
| calc_func_expr_list ',' maybe_space calc_func_expr calc_maybe_space {
$$ = $1;
$$->addValue(makeOperatorValue(','));
$$->extend(*($4));
}
;
calc_function:
CALCFUNCTION maybe_space calc_func_expr calc_maybe_space closing_parenthesis {
$$.setFromFunction(parser->createFloatingFunction($1, parser->sinkFloatingValueList($3)));
}
| CALCFUNCTION maybe_space expr_recovery closing_parenthesis {
YYERROR;
}
;
min_or_max:
MINFUNCTION
| MAXFUNCTION
;
min_or_max_function:
min_or_max maybe_space calc_func_expr_list closing_parenthesis {
$$.setFromFunction(parser->createFloatingFunction($1, parser->sinkFloatingValueList($3)));
}
| min_or_max maybe_space expr_recovery closing_parenthesis {
YYERROR;
}
;
invalid_at:
ATKEYWORD
| margin_sym
;
at_rule_recovery:
at_rule_header_recovery at_invalid_rule_header_end at_rule_end
;
at_rule_header_recovery:
error error_location rule_error_recovery {
parser->reportError($2, CSSParser::InvalidRuleError);
}
;
at_rule_end:
at_invalid_rule_header_end semi_or_eof
| at_invalid_rule_header_end invalid_block
;
invalid_rule:
error error_location rule_error_recovery at_invalid_rule_header_end invalid_block {
parser->reportError($2, CSSParser::InvalidRuleError);
$$ = 0;
}
| error_location invalid_at rule_error_recovery at_invalid_rule_header_end at_rule_end {
parser->resumeErrorLogging();
parser->reportError($1, CSSParser::InvalidRuleError);
$$ = 0;
}
;
at_invalid_rule_header_end:
/* empty */ {
parser->endInvalidRuleHeader();
}
;
invalid_block:
'{' error_recovery closing_brace {
parser->invalidBlockHit();
}
;
invalid_square_brackets_block:
'[' error_recovery closing_square_bracket
;
invalid_parentheses_block:
opening_parenthesis error_recovery closing_parenthesis;
opening_parenthesis:
'(' | FUNCTION | CALCFUNCTION | VARFUNCTION | MINFUNCTION | MAXFUNCTION | ANYFUNCTION | NOTFUNCTION | CUEFUNCTION | DISTRIBUTEDFUNCTION | HOSTFUNCTION
;
error_location: {
$$ = parser->currentLocation();
}
;
location_label: {
parser->setLocationLabel(parser->currentLocation());
}
;
error_recovery:
/* empty */
| error_recovery error
| error_recovery invalid_block
| error_recovery invalid_square_brackets_block
| error_recovery invalid_parentheses_block
;
rule_error_recovery:
/* empty */
| rule_error_recovery error
| rule_error_recovery invalid_square_brackets_block
| rule_error_recovery invalid_parentheses_block
;
%%