Подтвердить что ты не робот

Действительно ли грамматики в спецификации Java7 эквивалентны?

Грамматика в главе 18 JLS v7, похоже, отличается от конструкций в другом месте документации, но для меня, похоже, существуют различия. В частности, в главе 15 правила:

RelationalExpression:
  ShiftExpression
  RelationalExpression < ShiftExpression
  RelationalExpression > ShiftExpression
  RelationalExpression <= ShiftExpression
  RelationalExpression >= ShiftExpression
  RelationalExpression instanceof ReferenceType

что делает foo instanceof Bar выражение RelationalExpression (и, следовательно, EqualityExpresson), которое, в свою очередь, может использоваться как LHS в правиле EqualityExpression, которое делает foo instanceof Bar == false выражение EqualityExpression.

Но если смотреть на грамматику в главе 18, они немного упростили ее:

Expression2:
  Expression3 [Expression2Rest]

Expression2Rest:
  { InfixOp Expression3 }
  instanceof Type

Что выглядит странно, что означает, что мы можем объединить Expression3 с бинарными операторами ИЛИ мы можем проверить тип одного Expression3. В частности, теперь foo instanceof Bar является Expression2, но я не вижу, что было бы справедливо использовать Expression2 как LHS сопоставления равенства.

Я что-то пропустил в грамматике главы 18, которая делает foo instanceof Bar == false допустимым выражение? Обратите внимание, что это допустимое выражение в соответствии с правилами в главе 15 и в соответствии с моим компилятором.

4b9b3361

Ответ 1

Этот вопрос заслуживает хорошего ответа, поэтому давайте внимательно посмотрим.

Основываясь исключительно на грамматике в главе 18:

Все, что связано с InfixOp (например, ==), либо подходит для Expression2Rest, либо ничего не подходит. Expression2Rest принадлежит только Expression2. Итак, если foo instanceof Bar == false является законным Java, это означает, что foo instanceof Bar должен быть выражением3.

Выражение2:
Выражение3 [Expression2Rest]

Expression2Rest:
{InfixOp Expression3}
экземпляр Тип

Но foo instanceof Bar не является выражением3. Там нет PrefixOp и никакого актера, поэтому, чтобы быть Expression3, он должен был быть Первичным. Но это просто не подходит.

expression3:
ПрефиксOp Expression3
( (Expression | Type) ) Expression3
Первичный {Селектор} {PostfixOp}

Primary:
Буквальное
ParExpression
this [Аргументы]
супер SuperSuffix
новый Создатель
NonWildcardTypeArguments (ExplicitGenericInvocationSuffix | thisАргументы)
Идентификатор {. Идентификатор} [ИдентификаторSuffix]
BasicType { []} * .class
void.class

Вывод: основанный исключительно на грамматике, представленной в главе 18, foo instanceof Bar == false не является юридическим выражением Java.!?!?!

Конечно, это вздор. foo instanceof Bar дает логический результат, и этот результат, безусловно, можно сравнить с false. Выражение компилируется и выполняется.

Лучшее заключение: глава 18 не является авторитетной, но остальная часть книги.

В разделе 2.3 указано, что

Синтаксическая грамматика для языка программирования Java приведена в главах 4, 6-10, 14 и 15.... В главе 18 также дается синтаксическая грамматика для языка программирования Java, более подходящая для реализации, чем изложение.

По правилам грамматики, представленным в главе 15, foo instanceof Bar == false есть юридическое выражение Java. Но проверьте последнее предложение перед разделом 15.20.1: "Тип реляционного выражения всегда boolean." Это напрямую противоречит правилам RelationalExpression в 15.20. (В частности, это означает, что значение LHS instanceof должно оцениваться как boolean.) Это не может быть правдой.

Самый лучший вывод: у этой книги есть проблемы. Если вы хотите узнать, является ли что-то законным Java, вы должны его компилировать и запускать, предпочтительно по реализации Oracle reference. И даже тогда могут быть ошибки. Это, в конце концов, просто программное обеспечение.

И я думаю, что если они немного изменили правило Expression2, то глава 18 может быть права. Например:

* Выражение2:
Выражение3 [ экземпляр Тип]
Выражение2 {выражение InfixOp3}

Но кто знает, это может вызвать другие проблемы. В любом случае он исправлен в Java 8.