Правила производства объявления переменных грамматики Java
Если я попытаюсь инициализировать переменную, которая не является массивом, используя фигурные скобки, я получу ошибку компиляции.
Например:
public class test1 {
public static void main(String[] args) {
double a = {1.5,6.3};
}
}
Используя "javac", я получаю эту ошибку компиляции:
test1.java:13: error: illegal initializer for double
double a = {1.5,6.3};
^
1 error
Однако, я изучаю грамматику Java и нашел следующие произведения (из спецификации языка Java):
VariableDeclarators:
VariableDeclarator
VariableDeclarators , VariableDeclarator
VariableDeclarator:
VariableDeclaratorId
VariableDeclaratorId = VariableInitializer
VariableDeclaratorId:
Identifier
VariableDeclaratorId [ ]
VariableInitializer:
Expression
ArrayInitializer
ArrayInitializer:
{ VariableInitializersopt ,opt }
С помощью этих правил я могу успешно скомпилировать приведенный выше код (я попробовал это с помощью компилятора, который использует jflex и a .файл спецификации чашки, в котором грамматика уточняется). Почему это возможно? Есть ли что-то, что я игнорирую?
Спасибо.
3 ответа:
Дело в том, что да, грамматика правильна, но она не имеет смысла.
"свиньи летают в небе."это грамматическое английское предложение, но оно не имеет смысла.
Вы написали грамматический оператор Java, но компиляция не удалась, потому что компиляция-это не только соответствие грамматике, типы также должны соответствовать (среди множества других вещей). Здесь левая часть
=
является переменной двойного типа, а правая-выражением типаdouble[]
. 2 типа не являются неявно конвертируемыми, поэтому код не компилируется.Для успешной компиляции попробуйте изменить
double
наdouble[]
.
С помощью грамматики вы можете успешно разобрать ваш код и так же можете
javac
(обратите внимание, что сообщение об ошибкеjavac
не говорит "[что-то] ожидалось", что было бы сообщением, которое он производит для ошибок разбора). Но компиляция включает в себя больше, чем синтаксический анализ - она также включает в себя проверку типов, и когда код не проверяет тип, он не будет компилироваться.В качестве другого примера грамматика также допускает
Правила для хорошо типизированной программы также являются частью спецификации, но отдельно от грамматики. Эти правила запрещают такие вещи, какint x = "lala";
. Как и в вашем примере, это разбирает правильно, но будет отклонено типом контролер.double a = {1.5,6.3};
илиint x = "lala";
.
Компилятор обычно проходит три этапа, прежде чем принять программу как допустимую: лексический, синтаксический и семантический. Фрагмент кода, соответствующий спецификации формальной грамматики, является допустимым только с лексической и синтаксической точек зрения, но не обязательно с семантической. В этом случае нет семантического смысла присваивать вектор значений скалярной переменной, следовательно, он не является семантически корректным.