Zum Inhaltsverzeichnis

Inhaltsverzeichnis

D Die Grammatik von CSS2
D.1 Grammatik
D.2 Lexikalischer Scanner
D.3 Vergleich der Tokenbildung zwischen CSS1 und CSS2

Die Grammatik von CSS2

Dieser Anhang ist normativ.

Die nachfolgende Grammatik definiert die Syntax von CSS1. Es handelt sich dabei jedoch in gewisser Hinsicht um eine Obermenge von CSS2, weil diese Spezifikation zusätzliche semantische Beschränkungen einführt, die nicht in dieser Grammatik ausgedrückt sind. Ein konformes Benutzerprogramm muss außerdem die Regeln zum vorwärtskompatiblen Parsing, die Eigenschaft/Wert-Notation und die Einheitennotation berücksichtigen. Darüber hinaus kann die Dokumentsprache Beschränkungen einführen, z.B. legt HTML Beschränkungen zu den möglichen Werten des „class“-Attributs fest.

D.1 Grammatik

Die nachfolgende Grammatik ist LL(1) (beachten Sie jedoch, dass die meisten Benutzerprogramme sie nicht direkt verwenden sollten, weil sie die Parsing-Konventionen nicht ausdrückt, sondern nur die CSS2-Syntax). Das Format der Produktionen ist für die menschliche Wahrnehmung optimiert, und es wird eine Art abkürzende Notation jenseits von Yacc (siehe [YACC]) verwendet:

Die Produktionen sind:

stylesheet
: [ CHARSET_SYM S* STRING S* ';' ]?
[S|CDO|CDC]* [ import [S|CDO|CDC]* ]*
[ [ ruleset | media | page | font_face ] [S|CDO|CDC]* ]*
;
import
: IMPORT_SYM S*
[STRING|URI] S* [ medium [ ',' S* medium]* ]? ';' S*
;
media
: MEDIA_SYM S* medium [ ',' S* medium ]* '{' S* ruleset* '}' S*
;
medium
: IDENT S*
;
page
: PAGE_SYM S* IDENT? pseudo_page? S*
'{' S* declaration [ ';' S* declaration ]* '}' S*
;
pseudo_page
: ':' IDENT
;
font_face
: FONT_FACE_SYM S*
'{' S* declaration [ ';' S* declaration ]* '}' S*
;
operator
: '/' S* | ',' S* | /* leer */
;
combinator
: '+' S* | '>' S* | /* leer */
;
unary_operator
: '-' | '+'
;
property
: IDENT S*
;
ruleset
: selector [ ',' S* selector ]*
'{' S* declaration [ ';' S* declaration ]* '}' S*
;
selector

: simple_selector [ combinator simple_selector ]*
;
simple_selector
: element_name? [ HASH | class | attrib | pseudo ]* S*
;
class
: '.' IDENT
;
element_name
: IDENT | '*'
;
attrib
: '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S*
[ IDENT | STRING ] S* ]? ']'
;
pseudo
: ':' [ IDENT | FUNCTION S* IDENT S* ')' ]
;
declaration
: property ':' S* expr prio?
| /* leer */
;
prio
: IMPORTANT_SYM S*
;
expr
: term [ operator term ]*
;
term
: unary_operator?
[ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* |
TIME S* | FREQ S* | function ]
| STRING S* | IDENT S* | URI S* | RGB S* | UNICODERANGE S* | hexcolor
;
function
: FUNCTION S* expr ')' S*
;
/*
* Es gibt eine Beschränkung bezüglich der
* Farbe, nämlich, dass sie 3 oder
* 6 Hex-Ziffern (i.e., [0-9a-fA-F]) hinter
* dem "#" haben muss; e.g., "#000" ist OK,
* "#abcd" nicht
*/
hexcolor
: HASH S*
;

D.2 Lexikalischer Scanner

Nachfolgend sehen Sie den Tokenizer, geschrieben in Flex-Notation (siehe [FLEX]). Der Tokenizer berücksichtigt keine Groß-/Kleinschreibung.

Die beiden Vorkommen von „\377“ stellen die höchste Zeichennummer dar, mit der aktuelle Versionen von Flex zurechtkommen (dezimal 255). Sie sollten als „\4177777“ (dezimal 1114111) gelesen werden, der höchstmögliche Codepunkt in Unicode/ISO-10646.

%option case-insensitive

h  [0-9a-f]
nonascii [\200-\377]
unicode  \\{h}{1,6}[ \t\r\n\f]?
escape  {unicode}|\\[ -~\200-\377]
nmstart  [a-z]|{nonascii}|{escape}
nmchar  [a-z0-9-]|{nonascii}|{escape}
string1  \"([\t !#$%&(-~]|\\{nl}|\'|{nonascii}|{escape})*\"
string2  \'([\t !#$%&(-~]|\\{nl}|\"|{nonascii}|{escape})*\'

ident  {nmstart}{nmchar}*
name  {nmchar}+
num  [0-9]+|[0-9]*"."[0-9]+
string  {string1}|{string2}
url  ([!#$%&*-~]|{nonascii}|{escape})*
w  [ \t\r\n\f]*
nl  \n|\r\n|\r|\f
range  \?{1,6}|{h}(\?{0,5}|{h}(\?{0,4}|{h}(\?{0,3}|{h}(\?{0,2}|{h}(\??|{h})))))

%%

[ \t\r\n\f]+  {return S;}

\/\*[^*]*\*+([^/][^*]*\*+)*\/ /* Kommentare ignorieren */

"<!--"   {return CDO;}
"-->"   {return CDC;}
"~="   {return INCLUDES;}
"|="   {return DASHMATCH;}

{string}  {return STRING;}

{ident}   {return IDENT;}

"#"{name}  {return HASH;}

"@import"  {return IMPORT_SYM;}
"@page"   {return PAGE_SYM;}
"@media"  {return MEDIA_SYM;}
"@font-face"  {return FONT_FACE_SYM;}
"@charset"  {return CHARSET_SYM;}
"@"{ident}  {return ATKEYWORD;}

"!{w}important"  {return IMPORTANT_SYM;}

{num}em   {return EMS;}
{num}ex   {return EXS;}
{num}px   {return LENGTH;}
{num}cm   {return LENGTH;}
{num}mm   {return LENGTH;}
{num}in   {return LENGTH;}
{num}pt   {return LENGTH;}
{num}pc   {return LENGTH;}
{num}deg  {return ANGLE;}
{num}rad  {return ANGLE;}
{num}grad  {return ANGLE;}
{num}ms   {return TIME;}
{num}s   {return TIME;}
{num}Hz   {return FREQ;}
{num}kHz  {return FREQ;}
{num}{ident}  {return DIMEN;}
{num}%   {return PERCENTAGE;}
{num}   {return NUMBER;}

"url("{w}{string}{w}")" {return URI;}
"url("{w}{url}{w}")" {return URI;}
{ident}"("  {return FUNCTION;}
U\+{range}  {return UNICODERANGE;}
U\+{h}{1,6}-{h}{1,6} {return UNICODERANGE;}

.   {return *yytext;}

D.3 Vergleich der Tokenbildung zwischen CSS1 und CSS2

Es gibt einige Unterschiede zwischen der Syntax, wie sie in der CSS1-Empfehlung ([CSS1]) angegeben ist, und der oben gezeigten. Diese Unterschiede sind größtenteils durch neue Token in CSS2 bedingt, die es in CSS1 nicht gab. Andere Unterschiede sind entstanden, weil die Grammatik der besseren Lesbarkeit umformuliert wurde. Es gibt jedoch einige inkompatible Änderungen, die in der CSS1-Syntax als Fehler erkannt wurden. Sie sind nachfolgend beschrieben.