// 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 *
* * * * * * * * * * * * * * * * * WHITESPACE * * * * * * * * CDC * * * * * * * * CDO * * * * * * * * qualified-rule * * * * * * * * at-rule * * * * * * * * * * * * * * * *
* \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 *
* * * * * * * * * * * * * * * * * WHITESPACE * * * * * * * * qualified-rule * * * * * * * * at-rule * * * * * * * * * * * * * * * *
* \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 *
* * * * * * * AT-KEYWORD * * * * * * * * * * * * * * component-value * * * * * * * * * * * * * * * {}-block * * * * * * * * ; * * * * * * *
* \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 *
* * * * * * * * * * * * * * * component-value * * * * * * * * * * * * * * {}-block * * * * * *
* \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 *
* * * * * * * WHITESPACE * * * * * * * * * * * * * * * declaration * * * * * * * * * * * * * * * ; * * * * * * declaration-list * * * * * * * * * * * * * * * at-rule * * * * * * declaration-list * * * * * * * * *
* \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 *
* * * * * * * IDENTIFIER * * * * * * WHITESPACE * * * * * * : * * * * * * * * * * * * * * component-value * * * * * * * * * * * * * * * * * * * * * !important * * * * * * * !global * * * * * * * !default * * * * * * * *
* \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 *
* * * * * * * ! * * * * * * WHITESPACE * * * * * IDENTIFIER "important" * * * * * * WHITESPACE * * * * * *
* \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 *
* * * * * * * ! * * * * * * WHITESPACE * * * * * IDENTIFIER "global" * * * * * * WHITESPACE * * * * * *
* \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 *
* * * * * * * ! * * * * * * WHITESPACE * * * * * IDENTIFIER "default" * * * * * * WHITESPACE * * * * * *
* \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 *
* * * * * * * * preserved-token * * * * * * * * {}-block * * * * * * * * ()-block * * * * * * * * []-block * * * * * * * * function-block * * * * * * *
* \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 *
* * * * * * * any token except '{', '(', '[', * FUNCTION * * * * * *
* \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 *
* * * * * * * { * * * * * * * * * * * * * * component-value * * * * * * * * * * * * * * } * * * * * *
* \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 *
* * * * * * * ( * * * * * * * * * * * * * * component-value * * * * * * * * * * * * * * ) * * * * * *
* \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 *
* * * * * * * [ * * * * * * * * * * * * * * component-value * * * * * * * * * * * * * * ] * * * * * *
* \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 *
* * * * * * * * FUNCTION * * * * * * * * * VARIABLE_FUNCTION * * * * * * * * * * * * * * * * component-value * * * * * * * * * * * * * ) * * * * * *
* \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