Ao examinar a gramática BNF de C, achei estranho que a regra de produção de uma declaração tivesse essa aparência (de acordo com https://cs.wmich.edu/~gupta/teaching/cs4850/sumII06/The%20syntax%20of% 20C% 20in% 20Backus-Naur% 20form.htm ):
<declaration> ::= {<declaration-specifier>}+ {<init-declarator>}* ;
Por que usar um *
quantificador (significando zero ou mais ocorrências) para o init-declarator
? Isso permite que instruções como int;
ou void;
sejam sintaticamente válidas, mesmo que sejam semanticamente inválidas. Eles não poderiam ter usado apenas um +
quantificador (uma ou mais ocorrências) em vez de *
na regra de produção?
Tentei compilar um programa simples para ver o que o compilador gera e tudo o que ele faz é emitir um aviso.
Entrada:
int main(void) {
int;
}
Resultado:
test.c: In function ‘main’:
test.c:2:5: warning: useless type name in empty declaration
int;
^~~
c
language-lawyer
context-free-grammar
rafaelfp
fonte
fonte
int
como um tipo de retorno paramain
e não use()
como uma lista de tipos de parâmetros em funções, mas(void)
sim.Respostas:
declaration-specifier
incluitype-specifier
, o que incluienum-specifier
. Uma construção comoé um válido
declaration
seminit-declarator
.Construções como
int;
são descartadas por restrições além da gramática :Eu acho que existem razões de compatibilidade com versões anteriores por trás do seu compilador apenas emitir um aviso.
fonte
Uma declaração sem um declarador init:
é inofensivo para as listas de especificadores de declaração que não são um único especificador
enum
/struct
/union
e combina de maneira útil com as que são.De qualquer forma, a gramática apresentada também corresponderá erroneamente a declarações como
int struct foo x;
ordouble _Bool y;
(permite vários especificadores para corresponder a coisas comolong long int
), mas todos esses podem ser detectados posteriormente, em uma verificação semântica.A própria gramática da BNF não eliminará todas as construções ilegais.
fonte