Как выглядит синтаксический анализ компилятора Java?

Простое выражение типа

(x) - y

интерпретируется по-разному в зависимости от того, является ли x именем типа или нет. Если x не является именем типа, (x) - y просто вычитает y из x. Но если x - это имя типа, (x) - y вычисляет отрицание y и выводит результирующее значение на тип x.

В типичном компиляторе C или С++ вопрос о том, является ли тип x типом или нет, отвечает, потому что парсер передает эту информацию в лексер, как только он обрабатывает объявление typedef или struct. (Я думаю, что такое требуемое нарушение уровней было самой противной частью дизайна C.)

Но в Java x не может быть определен до конца в исходном коде. Как компилятор Java рассогласовывает такое выражение?

Ясно, что компилятору Java требуется несколько проходов, поскольку Java не требует объявления перед использованием. Но это, по-видимому, означает, что первый проход должен выполнять очень неряшливое задание при разборе выражений, а затем в более позднем прохождении делать другой, более точный разбор выражений. Это кажется расточительным.

Есть ли лучший способ?

Ответ 1

Я думаю, что нашел решение, которое меня удовлетворяет. Благодаря mmyers я понял, что мне нужно проверить формальную спецификацию синтаксиса для тиков.

Неоднозначность вызвана тем, что + и - являются как унарными, так и двоичными операторами. Java решает проблему этой грамматикой:

CastExpression:
        ( PrimitiveType Dimsopt ) UnaryExpression
        ( ReferenceType ) UnaryExpressionNotPlusMinus

(см. http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#238146)

Итак, '+' и '-' явно запрещены сразу после ')' приведения, если только cast не использует примитивный тип - который известен априорно компилятору.

Ответ 2

Я только что проверил это, и этот код:

Double y = new Double(0.1);
System.out.println((Double)-y);

дает ошибку компиляции:

operator - cannot be applied to Double, java.lang.Double.

Помещение круглых скобок вокруг -y делает его компилируемым. Таким образом, очевидно, что Java решает эту проблему, просто не допуская ее в грамматике (если это правильная терминология, я не эксперт по компиляторам).