The parser is composed of the following rules:
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:
The stylesheet is an entry point used to parse rules found in a <style> tag. This includes rules such as the CDO and CDC which allow the user to write the style data in what looks like a comment:
Other documents do not accept the CDO and CDC tokens.
There are our corresponding YACC-like rules:
The Rule List includes qualified rules, @ rules, and whitespace tokens.
There are our corresponding YACC-like rules:
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:
Qualified rules are selectors followed by a block. The selector list can be empty.
Note that a component value is just whatever preserved token so you can create a field with the qualified-rule grammar:
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:
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:
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:
A declaration is a component value with the particularity of starting with an IDENTIFIER which is followed by a colon (:).
To support variables, we also accept a VARIABLE followed by a colon (:).
And to support declarations of functions, we support VARIABLE_FUNCTION followed by a colon (:).
We also support two special extensions:
There is our corresponding YACC-like rule:
However, we do not enforce the exclamation flag name until later when we know exactly how it is getting used.
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:
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:
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:
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:
The CSS 3 definition of a preserved token is:
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 correct the fact is that we save the opening in our list of preserved tokens.
There is our corresponding YACC-like rule:
Define a sub-block of values.
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:
Define a sub-block of values.
In general, parenthesis are used to group expressions together.
There is our corresponding YACC-like rule:
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:
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:
Documentation of CSS Preprocessor.
This document is part of the Snap! Websites Project.
Copyright by Made to Order Software Corp.