Что люди имеют в виду, когда говорят, что С++ имеет "неразрешимую грамматику"?
Что люди говорят, когда говорят об этом? Каковы последствия для программистов и компиляторов?
Ответы
Ответ 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 обычно хуже, чем те вещи, к языковой грамматике).
Импликация для тех, кто пишет компиляторы, заключается в том, что они должны тратить много дополнительного времени и усилий на компиляцию языка.