To be clear, in the new approach, the lexeme `yield` is always tokenized as an identifier, and never as a keyword.

Gavin has already changed the MethodName production so that it uses UnqualifiedMethodIdentifier rather than Identifier. And since MethodName is used by MethodInvocation (15.12), ALL unqualified method invocations are now constrained by the "can't call `yield`" policy -- whether an invocation is top level (an expression statement) or nested (an expression). If you write `f(g(yield(1)))` then you will get a compile-time error due to g's argument not parsing as an Expression.

Alex

On 5/29/2019 9:15 AM, Peter Levart wrote:
Even in expression context, unqualified yield could be tokenized as
keyword (and hence produce a compile-time error). What do we loose? If
it is a field, it can be qualified. If it is a local variable, it only
presents source incompatibility, which can easily be fixed at next
re-compile.

The treatment would be more regular (not dependent on expression vs.
statement context) this way.

Regards, Peter

On 5/29/19 4:21 PM, Gavin Bierman wrote:
Upon reflection, the simplest way out of this is to not go down the
path of trying to identify tokens so that the lexer knows something
about parsing, but rather follow the suggestion made by Dan earlier in
this thread. To wit, we treat `yield` much like we treat `var`. It’s a
"restricted identifier", which means that it can’t be used as a
*TypeIdentifier* nor as a *MethodName*. Thus any unqualified method
invocation needs to be qualified (or in the extreme corner case
involving an anonymous class spotted by Tagir, may need (local)
renaming). Without qualification, `yield (42);` will be *parsed* as a
`yield` statement and not an expression statement. Our corpus
analysis, as reported by Brian, shows this not to be a problem.
Tagir’s analysis of the Idea Ultimate sources suggests the same.

The revised JLS is available at:
http://cr.openjdk.java.net/~gbierman/jep354-jls-20190528.html

Thanks,
Gavin



On 24 May 2019, at 23:44, Alex Buckley <alex.buck...@oracle.com
<mailto:alex.buck...@oracle.com>> wrote:

On 5/24/2019 1:19 PM, Tagir Valeev wrote:
Hello! Answering myself

The first token in a YieldStatement production is always preceded
by one of these separator tokens: ;, {, }, ), or ->.

Seems I'm missing something. Could you please illustrate in which
case YieldStatement could be preceded by ')'?

Nevermind. if(foo) yield bar; is a good example. Other my points
still apply.

Also what about '->'? In lambda '->' is followed by an expression
or block, but not a statement. In switch '->' is followed by block,
throw or expression plus semicolon. Also could YieldStatement be
preceded by ':' in old switch format? E.g.

System.out.println(switch(0) { default: yield 1; }); // seems
legit

You're right that `->` should not appear in the list. Any `yield`
which follows `->` is necessarily the start of an expression, so
`yield` should be tokenized as an identifier there.

`:` is tricky. On the one hand, the space after `:` is sometimes
desirous of an statement, so tokenize `yield` as a keyword:

- `default : yield (1);` in a switch expression (also `case ... :`)

- `L1 : yield (1);` in a switch expression (labeled statements are
legitimate in a switch-labeled block! If there was no label, we would
quickly say that this `yield` is a YieldStatement not an
ExpressionStatement, and that if you want an ExpressionStatement
which invokes a method, then qualify the invocation.)

On the other hand, the space after `:` is sometimes desirous of an
expression, so tokenize `yield` as a identifier: (and it might be the
name of a local variable, so no way to qualify)

- `for (String s : yield . f) ...`

- `m(a ? yield . f : yield . g)`

Alex


Reply via email to