Что люди имеют в виду, когда говорят, что С++ имеет "неразрешимую грамматику"?

Что люди говорят, когда говорят об этом? Каковы последствия для программистов и компиляторов?

Ответы

Ответ 1

Это связано с тем, что система шаблонов С++ Turing завершена. Это означает (теоретически), что вы можете вычислить что-либо во время компиляции с шаблонами, которые вы могли бы использовать с любым другим языком или системой Turing.

Это имеет побочный эффект, что некоторые, по-видимому, действительные С++-программы не могут быть скомпилированы; компилятор никогда не сможет решить, действительна ли программа или нет. Если компилятор может решить вопрос о действительности всех программ, он сможет решить проблему Halting.

Обратите внимание, что это не имеет ничего общего с двусмысленностью грамматики С++.


Редактировать: Джош Хаберман указал в комментариях ниже и в сообщении с отличным примером того, что построение дерева синтаксиса для С++ фактически не поддается обсуждению. Из-за двусмысленности грамматики невозможно отделить синтаксический анализ от семантического анализа, и поскольку семантический анализ не определен, так же как и синтаксический анализ.

См. также (ссылки из сообщения Джоша):

Ответ 2

То, что это, вероятно, означает, что грамматика С++ синтаксически неоднозначна, вы можете записать код, который может означать разные вещи, в зависимости от контекста. (Грамматика - это описание синтаксиса языка, что определяет, что a + b является операцией сложения, включающей переменные a и b.)

Например, foo bar(int(x));, как написано, может быть объявлением переменной bar, типа foo, причем int (x) является инициализатором. Это также может быть объявление функции bar, взятие int и возврат foo. Это определяется внутри языка, но не как часть грамматики.

Важна грамматика языка программирования. Во-первых, это способ понять язык, и, во-вторых, это часть компиляции, которая может быть выполнена быстро. Поэтому компиляторы С++ сложнее писать и использовать медленнее, чем если бы С++ имела однозначную грамматику. Кроме того, проще сделать определенные классы ошибок, хотя хороший компилятор предоставит достаточное количество подсказок.

Ответ 3

Если "некоторые люди" включают Йосси Крейнина, то на основании того, что он пишет здесь...

Рассмотрим следующий пример:

x * y(z);

в двух разных контекстах:

int main() {
    int x, y(int), z;
    x * y(z);
}

и

int main() {
    struct x { x(int) {} } *z;
    x * y(z);
}

... он означает "Вы не можете решить, глядя на x * y (z), является ли это выражением или декларацией". В первом случае это означает "вызов функции y с аргументом z, затем вызовите оператор * (int, int) с x и возвращаемое значение вызова функции и, наконец, отбросьте результат". Во втором случае это означает, что "y - это указатель на структуру x, инициализированный для указания того же (мусора и бомбы замедленного действия), что и z".

Скажите, что у вас есть подгонка COBOLmania и добавлен DECLARE на этот язык. Тогда вторая станет

int main() {
    DECLARE struct x { x(int) {} } *z;
    DECLARE x * y(z);
}

и появится разрешимость. Обратите внимание, что разрешимость не устраняет проблему с указателем на мусор.

Ответ 4

"Неразрешимая грамматика" - очень плохой выбор слов. Поистине неразрешимая грамматика такова, что не существует синтаксического анализа грамматики, которая прекратится на всех возможных входах. То, что они, вероятно, означают, что грамматика С++ не является контекстно-зависимой, но даже это немного зависит от вкуса: где рисовать линию между синтаксисом и семантикой? Любой компилятор будет допускать только соответствующее подмножество тех программ, которые проходят этап анализатора без синтаксических ошибок, и только соответствующее подмножество этих программ фактически выполняется без ошибок, поэтому ни один язык не является контекстно-свободным или даже разрешимым (за исключением, возможно, некоторых эзотерических языков).

Ответ 5

Примером для тех из нас, кто использует этот язык, является то, что сообщения об ошибках могут быть очень странными, очень быстрыми (на практике это не так уж и сложно. Ошибки библиотеки STL обычно хуже, чем те вещи, к языковой грамматике).

Импликация для тех, кто пишет компиляторы, заключается в том, что они должны тратить много дополнительного времени и усилий на компиляцию языка.