Apéndice D: La gramática de CSS2

Contenidos

Este apéndice es normativo.

Nota de la traducción:
Este apéndice es normativo, por lo que recuerdo a los programadores que la única versión aceptada está en http://www.w3.org/TR/1998/REC-CSS2-19980512 por lo que deberán recurrir a ella si desean asegurarse el cumplimiento de las condiciones de conformidad.

La gramática de abajo define la sintaxis de CSS2. Sin embargo, es en cierto sentido un superconjunto de CSS2 puesto que impone restricciones semánticas adicionales no expresadas en esta gramática. Una aplicación del usuario conformada debe también adherir a las reglas de análisis con compatibilidad futura, la notación de propiedades y valores y la unidad de notación. Además, el lenguaje del documento puede imponer restricciones, por ej., HTML impone restricciones a los posibles valores del atributo "class".

D.1 Gramática

La gramática de abajo es LL(1) (pero observe que la mayoría de la AU no debe utilizarla directamente, debido a que no expresa las convenciones de análisis, sólo la sintaxis de CSS2). El formato de las producciones está optimizado para el uso humano y se usa alguna notación abreviadas más allá de Yacc (ver [YACC]):

Las producciones son:

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* | /* vacío */
  ;
combinator
  : '+' S* | '>' S* | /* vacío */
  ;
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?
  | /* vacío */
  ;
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*
  ;
/*
 * Hay una restricción en el color que debe tener
 * 3 o 6 dígitos hexadecimales (es decir, [0-9a-fA-F])
 * después de "#"; ej., "#000" está bien, pero "#abcd" no.
 */
hexcolor
  : HASH S*
  ;

D.2 Scanner de léxico

La siguiente es la definición de los comandos (tokenizer) escrito en notación Flex (ver [FLEX]). Es sensible a la diferencia entre mayúsculas y minúsculas.

Las dos apariciones de "\377" representan el número de carácter más alto que la versión actual de Flex puede manejar (decimal 255). Debe leerse como "\4177777" (decimal 1114111), que es el punto de código más alto posible en 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-zA-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;}

\/\*[^*]*\*+([^/][^*]*\*+)*\/	/* ignore comments */

"<!--"			{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 Comparación de los comandos en CSS2 y CSS1

Hay algunas diferencias en la sintaxis especificada en la recomendación CSS1 ([CSS1]) y la de más arriba. La mayoría de éstas se deben a los nuevos comandos en CSS2 que no existían en CSS1. Otras son debido a que la gramática ha si reescrita para que sea más legible. Sin embargo, hay algunos cambios incompatibles, en lo que se consideró eran errores en la sintaxis de CSS1. Están explicados abajo.

Copyright  ©  1998 W3C (MIT, INRIA, Keio ), All Rights Reserved.

Traducción: Carlos Benavidez