Правила производства объявления переменных грамматики 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 2

3 ответа:

Дело в том, что да, грамматика правильна, но она не имеет смысла.

"свиньи летают в небе."это грамматическое английское предложение, но оно не имеет смысла.

Вы написали грамматический оператор Java, но компиляция не удалась, потому что компиляция-это не только соответствие грамматике, типы также должны соответствовать (среди множества других вещей). Здесь левая часть = является переменной двойного типа, а правая-выражением типа double[]. 2 типа не являются неявно конвертируемыми, поэтому код не компилируется.

Для успешной компиляции попробуйте изменить double на double[].

С помощью грамматики вы можете успешно разобрать ваш код и так же можете javac (обратите внимание, что сообщение об ошибке javac не говорит "[что-то] ожидалось", что было бы сообщением, которое он производит для ошибок разбора). Но компиляция включает в себя больше, чем синтаксический анализ - она также включает в себя проверку типов, и когда код не проверяет тип, он не будет компилироваться.

В качестве другого примера грамматика также допускает int x = "lala";. Как и в вашем примере, это разбирает правильно, но будет отклонено типом контролер.

Правила для хорошо типизированной программы также являются частью спецификации, но отдельно от грамматики. Эти правила запрещают такие вещи, как double a = {1.5,6.3}; или int x = "lala";.

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