Почему грамматика BNF C допускает объявления с пустой последовательностью init-деклараторов? - PullRequest
28 голосов
/ 04 апреля 2020

Просматривая грамматику C BNF, я подумал, что странно, что производственное правило для объявления выглядит так (согласно https://cs.wmich.edu/~gupta/teaching/cs4850/sumII06/The%20syntax%20of%20C%20in%20Backus-Naur%20form.htm):

<declaration> ::=  {<declaration-specifier>}+ {<init-declarator>}* ;

Зачем использовать квантификатор * (что означает ноль или более вхождений) для init-declarator? Это позволяет синтаксически допустимым операторам, таким как int; или void;, даже если они семантически недействительны. Разве они не могли просто использовать + квантификатор (одно или несколько вхождений) вместо * в производственном правиле?

Я попытался скомпилировать простую программу, чтобы увидеть, что выводит компилятор, и все, что он делает выдается предупреждение.

Ввод:

int main(void) {
    int;
}

Выход:

test.c: In function ‘main’:
test.c:2:5: warning: useless type name in empty declaration
     int;
     ^~~

Ответы [ 2 ]

29 голосов
/ 04 апреля 2020

declaration-specifier включает type-specifier, что включает enum-specifier. Конструкция, подобная

enum stuff {x, y};

, является действительной declaration без init-declarator.

Конструкции, подобные int;, исключаются из ограничений за пределами грамматики :

Объявление, отличное от объявления static_assert, должно объявлять, по крайней мере, декларатора (кроме параметров функции или членов структуры или объединения), тега или членов перечисления.

Я полагаю, что существуют причины обратной совместимости вашего компилятора, выдающего только предупреждение.

14 голосов
/ 04 апреля 2020

Объявление без объявления init:

<declaration> ::=  {<declaration-specifier>}+ {<init-declarator>}* ;

безвредно для списков спецификаторов объявлений, которые не являются единичным спецификатором enum / struct / union, и полезно соответствует тем, которые .

В любом случае, представленная грамматика также будет ошибочно соответствовать объявлениям, таким как int struct foo x; или double _Bool y; (она позволяет использовать несколько спецификаторов для сопоставления с такими вещами, как long long int), но все это может быть обнаружено позже. в проверке семанти c.

Сама грамматика BNF не отсеет все недопустимые конструкции.

...