Is the grammars in Java7 spec really equivalent?

439 views Asked by At

The grammar in chapter 18 of JLS v7 seem to differ from the constructs elsewhere in the documentation, but to me there seem to be differences. Specifically in chapter 15 the rules are:

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

which makes foo instanceof Bar a RelationalExpression (and therefore an EqualityExpresson) which in turn can be used as LHS in the EqualityExpression rule which makes foo instanceof Bar == false an EqualityExpression.

But when looking at the grammar in chapter 18 they've simplified it a bit:

Expression2:
  Expression3 [Expression2Rest]

Expression2Rest:
  { InfixOp Expression3 }
  instanceof Type

Which looks odd, which means that we can chain together Expression3s with binary operators OR we can check the type of one Expression3. Specifically now foo instanceof Bar is an Expression2, but I don't see that it would be valid to use an Expression2 as LHS of an equality comparision.

Have I missed something in the grammar of chapter 18 that makes foo instanceof Bar == false a valid expression? Note that it is a valid expression according to the rules in chapter 15 and according to my compiler.

1

There are 1 answers

0
Erick G. Hagstrom On BEST ANSWER

This question deserves a good answer, so let's take a good close look.

Based solely on the grammar in Chapter 18:

Anything with an InfixOp (e.g. ==) either fits Expression2Rest or fits nothing. And Expression2Rest only belongs inside Expression2. So, if foo instanceof Bar == false is legal Java, that means that foo instanceof Bar has to be an Expression3.

Expression2 :
Expression3 [Expression2Rest]

Expression2Rest:
{InfixOp Expression3}
instanceof Type

But foo instanceof Bar is not an Expression3. There's no PrefixOp and no cast, so to be an Expression3 it would have to be a Primary. But it just doesn't fit.

Expression3:
PrefixOp Expression3
( (Expression | Type) ) Expression3
Primary { Selector } { PostfixOp }

Primary:
Literal
ParExpression
this [Arguments]
super SuperSuffix
new Creator
NonWildcardTypeArguments (ExplicitGenericInvocationSuffix | this Arguments)
Identifier { . Identifier } [IdentifierSuffix]
BasicType { [] }* .class
void.class

Conclusion: based solely on the grammar presented in Chapter 18, foo instanceof Bar == false is not a legal Java expression. !?!?!

Of course that's nonsense. foo instanceof Bar yields a boolean result, and that result can certainly be compared to false. The expression compiles and runs.

Better conclusion: Chapter 18 isn't authoritative, but the rest of the book is.

Section 2.3 states that

A syntactic grammar for the Java programming language is given in Chapters 4, 6-10, 14, and 15. ... Chapter 18 also gives a syntactic grammar for the Java programming language, better suited to implementation than exposition.

By the grammar rules presented in Chapter 15, foo instanceof Bar == false is a legal Java expression. But check out the last sentence before section 15.20.1: "The type of a relational expression is always boolean." That directly conflicts with the RelationalExpression rules themselves in 15.20. (In particular, it implies that the LHS of instanceof must evaluate to boolean.) It can't possibly be true.

Bestest conclusion: This book has issues. If you want to know whether something is legal Java, you have to compile and run it, preferably on Oracle's reference implementation. And even then there might be bugs. It is, after all, just software.

And I think that if they changed the Expression2 rule just a little bit, Chapter 18 could be right. Like so:

*Expression2 :
Expression3 [ instanceof Type ]
Expression2 {InfixOp Expression3}

But who knows, that might cause other problems. In any case, it's fixed in Java 8.