Al mirar la gramática BNF de C, pensé que era extraño que la regla de producción para una declaración se viera así (de acuerdo con https://cs.wmich.edu/~gupta/teaching/cs4850/sumII06/The%20syntax%20of% 20C% 20in% 20Backus-Naur% 20form.htm ):
<declaration> ::= {<declaration-specifier>}+ {<init-declarator>}* ;
¿Por qué usar un *
cuantificador (que significa cero o más ocurrencias) para el init-declarator
? Esto permite que declaraciones como int;
o void;
sean sintácticamente válidas, aunque sean semánticamente inválidas. ¿No podrían haber usado un +
cuantificador (una o más ocurrencias) en lugar de *
en la regla de producción?
Intenté compilar un programa simple para ver qué genera el compilador y todo lo que hace es emitir una advertencia.
Entrada:
int main(void) {
int;
}
Salida:
test.c: In function ‘main’:
test.c:2:5: warning: useless type name in empty declaration
int;
^~~
c
language-lawyer
context-free-grammar
rafaelfp
fuente
fuente
int
como un tipo de retorno paramain
y no utilice()
como una lista de tipos de parámetros en funciones, sino en su(void)
lugar.Respuestas:
declaration-specifier
incluyetype-specifier
, que incluyeenum-specifier
. Una construcción comoes válido
declaration
con noinit-declarator
.Las construcciones como
int;
se descartan por restricciones más allá de la gramática :Supongo que hay razones de compatibilidad con versiones anteriores detrás de su compilador que solo emite una advertencia.
fuente
Una declaración sin un declarador init:
es inofensivo para las listas de especificadores de declaración que no son un solo
enum
/struct
/union
especificador y coincide útilmente con las que sí lo son.En cualquier caso, la gramática presentada también coincidirá erróneamente con declaraciones como
int struct foo x;
odouble _Bool y;
(permite múltiples especificadores para hacer coincidir cosas comolong long int
), pero todo esto se puede detectar más tarde, en una comprobación semántica.La gramática BNF en sí misma no eliminará todas las construcciones ilegales.
fuente