// CSS Preprocessor
// Copyright (c) 2015-2019 Made to Order Software Corp. All Rights Reserved
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// Documentation only file
/** \page parser_rules Parser Rules
* \tableofcontents
*
* \htmlonly
*
* \endhtmlonly
*
* \note
* Many of the SVG images below were taken from the
* CSS Syntax Module Level 3
* document.
*
* The parser is composed of the following rules:
*
* \section parser_input Parser Input (CSS Preprocessor Detail)
*
* The parser input are nodes representing tokens as returned by a
* lexer object.
*
* The parser has multiple entry points to accomodate the various
* type of input data a CSS parser is expected to support. These
* are:
*
* \li Style Tag -- in an HTML document, data in:
* \code
*
* \endcode
* \li Inline Style -- in an HTML document, style found in the style attribute:
* \code
*
...
* \endcode
* \li CSS file -- a .css file with CSS rules
*
* \section stylesheet Stylesheet "stylesheet" and "stylesheet-list" (CSS 3)
*
* \htmlonly
*
*
*
* \endhtmlonly
*
* The stylesheet is an entry point used to parse rules found in a
* \
* \endcode
*
* Other documents do not accept the CDO and CDC tokens.
*
* There are our corresponding YACC-like rules:
*
* \code
* stylesheet:
* | stylesheet-list
*
* stylesheet-list: CDO
* | CDC
* | WHITESPACE
* | qualified-rule
* | at-rule
* | stylesheet-list stylesheet-list
* \endcode
*
* \section rule_list Rule List "rule" and "rule-list" (CSS 3)
*
* \htmlonly
*
*
*
* \endhtmlonly
*
* The Rule List includes qualified rules, @ rules, and whitespace tokens.
*
* There are our corresponding YACC-like rules:
*
* \code
* rule-list:
* | rule
* | rule rule-list
*
* rule: WHITESPACE
* | qualified-rule
* | at-rule
* \endcode
*
* \section at_rule At-Rule "at-rule" (CSS 3)
*
* \htmlonly
*
*
*
* \endhtmlonly
*
* At values define special rules. Some of the at-values are defined by
* the CSS Preprocessor as extensions. However, the parser has not
* specifics to handle such.
*
* There is our corresponding YACC-like rule:
*
* \code
* at-rule: AT-KEYWORD-TOKEN component-value block
* | AT-KEYWORD-TOKEN component-value ';'
* \endcode
*
* \section qualified_rule Qualified Rule "qualified-rule" (CSS 3)
*
* \htmlonly
*
*
*
* \endhtmlonly
*
* Qualified rules are selectors followed by a block. The selector list can
* be empty.
*
* \warning
* Although it is not clear from the graph, a
* {}-block ends a list of
* component-value.
*
* Note that a component value is just whatever preserved token so you
* can create a field with the qualified-rule grammar:
*
* \code
* IDENTIFIER ':' '{' ... '}'
* \endcode
*
* In order to support the SASS syntax, we have an exception that allows
* us to set variables in the "global scope". So the following works:
*
* \code
* $green: green;
* \endcode
*
* Even when you are in the global scope. This is not a valid rule that
* otherwise matches a valid CSS3 qualified rule. Note that a variable
* rule can also be terminated by a block since the content of a variable
* can be set to an entire block of data.
*
* There is our corresponding YACC-like rule:
*
* \code
* qualified-rule: component-value-list block
* | VARIABLE WHITESPACE ':' component-value-list
* \endcode
*
* \section declaration_list Declaration List "declaration-list" (CSS 3)
*
* \htmlonly
*
*
*
* \endhtmlonly
*
* A declaration list is a list of
* declarations separated by semi-colons.
* Such a list can be started with an at-rule.
*
* Whitespaces can appear to separate various elements in such a list.
*
* There is our corresponding YACC-like rule:
*
* \code
* declaration-list: WHITESPACE
* | WHITESPACE declaration ';' declaration-list
* | WHITESPACE at-rule declaration-list
* \endcode
*
* \section declaration Declaration "declaration" (CSS 3, CSS Preprocessor)
*
* \htmlonly
*
*
*
* \endhtmlonly
*
* A declaration is a component value with the particularity of starting
* with an \ref identifier "IDENTIFIER" which is followed by
* a colon (:).
*
* To support variables, we also accept a \ref variable "VARIABLE"
* followed by a colon (:).
*
* And to support declarations of functions, we support
* \ref variable_function "VARIABLE_FUNCTION" followed by a colon (:).
*
* We also support two special extensions:
*
* * One named \ref global "!global" which is used with variable
* declarations to mark a variable as a global variable wherever
* it gets defined:
*
* \code
* a {
* $width: 3em !global;
* width: $width;
* }
* span {
* width: $width; // works because $width was marked !global
* }
* \endcode
*
* * The other named \ref default "!default" which is used with
* variable declarations to mark that specific declaration
* as a default value meaning that if the variable is already
* defined, it does not get modified:
*
* \code
* $width: 5em;
*
* a {
* $width: 3em !default; // keeps 5em
* width: $width;
* }
* span {
* $width: 3em;
* width: $width; // use the 3em
* }
* \endcode
*
* There is our corresponding YACC-like rule:
*
* \code
* declaration: IDENTIFIER WHITESPACE ':' component-value-list
* | IDENTIFIER WHITESPACE ':' component-value-list !important
* | IDENTIFIER WHITESPACE ':' component-value-list !global
* | IDENTIFIER WHITESPACE ':' component-value-list !default
* \endcode
*
* However, we do not enforce the exclamation flag name until later when
* we know exactly how it is getting used.
*
* \section important !important "!important" (CSS 3)
*
* \htmlonly
*
*
*
* \endhtmlonly
*
* The !important keyword can be used to prevent overloading certain
* declaration. It is generally not recommended unless you are not
* in full control of your entire CSS rules.
*
* There is our corresponding YACC-like rule:
*
* \code
* !important: '!' WHITESPACE IDENTIFIER(=="important") WHITESPACE
* \endcode
*
* \section global !global "!global" (CSS Preprocessor Extension)
*
* \htmlonly
*
*
*
* \endhtmlonly
*
* The !global keyword can be used to mark a variable as global even
* when declared within a sub-block. This makes the value of the variable
* available to all the other blocks.
*
* Note that the use of the !global keyword is not recommended.
*
* There is our corresponding YACC-like rule:
*
* \code
* !global: '!' WHITESPACE IDENTIFIER(=="global") WHITESPACE
* \endcode
*
* \section default !default "!default" (CSS Preprocessor Extension)
*
* \htmlonly
*
*
*
* \endhtmlonly
*
* The !default keyword can be used to mark a variable declaration as
* the default declaration. This means the existing value of the variable,
* if such exists, does not get modified.
*
* Note that when the !default keyword is used, it does not set the
* variable if it is defined in any block or globally.
*
* There is our corresponding YACC-like rule:
*
* \code
* !default: '!' WHITESPACE IDENTIFIER(=="default") WHITESPACE
* \endcode
*
* \section component_value Component Value "component-value" and "component-value-list" (CSS 3)
*
* \htmlonly
*
*
*
* \endhtmlonly
*
* A component value is a preserved token
* or a block. Blocks are viewed as "non-preserved tokens" and everything
* else is viewed as a preserved token.
*
* Note that CSS defines preserved tokens because the parsing of various
* parts of your CSS rules may end up being done by various compilers and
* thus one compiler may fail where another succeeds and for that reason
* the preserved tokens is a rather loose definition. For the CSS
* Preprocessor, all tokens must be understood 100%. Anything that we
* do not know about, we cannot verify and thus we want to reject.
*
* There is our corresponding YACC-like rule:
*
* \code
* component-value:
* | {}-block
* | component-value-list
* | component-value-list {}-block
*
* component-value-list: component-value-item
* | component-value-list component-value-item
*
* component-value-item: preserved-token
* | ()-block
* | []-block
* | function-block
* \endcode
*
* \warning
* Notice that our Yacc rule does not follow the declaration of
* component-value to the letter. All the other grammar rules expect
* a list of component-value which may also be empty. However, the
* main difference not conveyed in the graphs is the fact that a
* {}-block can only be used at the end
* of a list of 'component-value' entries.
* (see http://www.w3.org/TR/css-syntax-3/#consume-a-qualified-rule0).
* In other words, the following are three 'component-value' entries
* and not just one:
*
* \code
* a { b: c } { d: e } { f: g } ...
* \endcode
*
* \section preserved_token Preserved Token "preserved-token" (CSS 3)
*
* \htmlonly
*
*
*
* \endhtmlonly
*
* The CSS 3 definition of a preserved token is:
*
* \par
* Any token except the '{', '(', '[', and
* FUNCTION.
*
* The importance of this is the fact that all preserved tokens are
* expected to be kept in the parser output. Since we are a preprocessor
* which compacts CSS, we do tend to ignore this definition because we
* want to (1) remove any comment that is not marked as \@preserve,
* (2) compress anything we can, (3) verify the syntax and only allow
* what is permissible (functional on at least one browser.)
*
* This being said, we still attempt to keep as many tokens as we can
* in our tree of nodes.
*
* Note that "any token" does not include ';' which marks the end of
* the a declaration, an @-keyword, a variable set... Also, the
* closing '}', ')', ']' should match open '{', '(', and '[' and
* that's why they do not appear here either. Again, although this
* is \em correct the fact is that we save the opening in our list
* of preserved tokens.
*
* There is our corresponding YACC-like rule:
*
* \code
* preserved-token: ANY-TOKEN except '{', '(', '[', and FUNCTION
* \endcode
*
* \section curlybracket_block {}-block "{}-block" (CSS 3)
*
* \htmlonly
*
*
*
* \endhtmlonly
*
* Define a sub-block of values.
*
* \warning
* The rules as presented here do not specify how things are
* really work: a {}-block is also a terminator rule when it is
* found in a component-value.
* See http://www.w3.org/TR/css-syntax-3/#consume-a-qualified-rule0
* as a reference to that rule.
*
* Specifically, curly bracket blocks are used to add any level of
* declarations within a qualified declaration (a declaration that
* starts with a list of identifiers and other tokens representing
* selectors.)
*
* There is our corresponding YACC-like rule:
*
* \code
* {}-block: '{' component-value-list '}'
* \endcode
*
* \section parenthesis_block ()-block "()-block" (CSS 3)
*
* \htmlonly
*
*
*
* \endhtmlonly
*
* Define a sub-block of values.
*
* In general, parenthesis are used to group expressions together.
*
* There is our corresponding YACC-like rule:
*
* \code
* ()-block: '(' component-value-list ')'
* \endcode
*
* \section squarebracket_block []-block "[]-block" (CSS 3)
*
* \htmlonly
*
*
*
* \endhtmlonly
*
* Define a sub-block of values.
*
* Specifically, the square bracket blocks are used to test the
* attributes of an element in a list of selectors.
*
* There is our corresponding YACC-like rule:
*
* \code
* []-block: '[' component-value-list ']'
* \endcode
*
* \section function_block Function Block "function-block" (CSS 3)
*
* \htmlonly
*
*
*
* \endhtmlonly
*
* Functions are identifiers immediately followed by an open parenthesis,
* variable functions are variables immediately followed by an open
* parenthesis, either is then followed by a list of space or comma
* separated parameters, and a closing parenthesis.
* Note that the parsing is very similar to a
* ()-block.
*
* There is our corresponding YACC-like rule:
*
* \code
* function-block: FUNCTION component-value-list ')'
* | VARIABLE_FUNCTION component-value-list ')'
* \endcode
*/
// Local Variables:
// mode: cpp
// indent-tabs-mode: nil
// c-basic-offset: 4
// tab-width: 4
// End:
// vim: ts=4 sw=4 et syntax=doxygen