Syntactic parameters

# Michael Dyck (11 years ago)

When I take the ECMAScript grammar and expand its abbreviations as outlined in section 5.1.5, I get a grammar with lots of unreachable nonterminals (i.e., symbols that can't appear in any sentential form derived from Script or Module).

For instance, consider StrictFormalParameters. With its parameters Yield and GeneratorParameter, it expands to 4 nonterminals:

     StrictFormalParameters
     StrictFormalParameters_Yield
     StrictFormalParameters_GeneratorParameter
     StrictFormalParameters_Yield_GeneratorParameter

(I use underscores to make the resulting names easier to read.)

In the unexpanded grammar, it's used in only 3 productions:

14.2:
     ArrowFormalParameters :
         ( StrictFormalParameters )

14.3:
     MethodDefinition[Yield] :
         PropertyName[?Yield] ( StrictFormalParameters ) { FunctionBody }

14.4:
     GeneratorMethod[Yield] :
         * PropertyName[?Yield]
         ( StrictFormalParameters[Yield,GeneratorParameter] )
         { FunctionBody[Yield] }

The first two of these expand to productions that reference

      StrictFormalParameters

and the last one expands to productions that reference

      StrictFormalParameters_Yield_GeneratorParameter.

So

      StrictFormalParameters_Yield and
      StrictFormalParameters_GeneratorParameter

are never referenced, and are thus unreachable.

Is this intentional? Or should StrictFormalParameters have a "?Yield" subscript in the 14.3 and 14.4 productions? (And while we're in the neighborhood, should FunctionBody also have a "?Yield" subscript in those productions?) If not, why not?

Similarly, I'm also wondering about the unreachability of

     Statement_Yield
     Declaration_Yield_Default
     BindingIdentifier_Default_Yield
# Allen Wirfs-Brock (11 years ago)

On Feb 5, 2014, at 9:30 PM, Michael Dyck wrote:

(I use underscores to make the resulting names easier to read.)

I think I'll make the "_" part of the expansion defined in chapter 5.

Is this intentional? Or should StrictFormalParameters have a "?Yield" subscript in the 14.3 and 14.4 productions?

Yes, it's intentional.

The Yield parameter selects whether or not "yield" is treated as an identifier or as an operator symbol. "yield" is only treated as an operator if the yield parameter is present. The GeneratorParameter parameter, when present, tags the use of a production in the parameter list. A yield operation doesn't work as part of an initializer or computed property name in a generator function's parameter list because when parameter declarations are evaluated, the associated generator object is not yet in a yield-able state. However, to avoid confusion, we want to disallow the use of "yield" as an identifier throughout a generator function including the parameter list. So, we parameterize StrictFormalParameters for generator functions and methods with [Yield, GeneratorParameter]. That parameter combination can be interpreted as don't allow "yield" as an identifier but also don't allow it to be used as an operator.

We never use StrictFormalParameter_Yield because that would permit the actual use of the yield operator within a formal parameter initializer.

We never use [GeneratorParameter] by itself because that essentially means allow "yield" as an identifier and don't treat it as an operator. That's redundant.

I should probably make a statement in section 5 that not all expansions are necessarily used.

14.3 is particularly interesting. consider:

"don't use strict";
function *() {
   return {
       [yield something] (yield) {yield = 0}
   }
}

Yield is validly treated a yield operator in determining the computed property name but is a regular identifier in parameter list and body of the nest function.

(And while we're in the neighborhood, should FunctionBody also have a "?Yield" subscript in those productions?) If not, why not?

No, generator-ness and use of the yield operator doesn't propagate to nested functions.

Similarly, I'm also wondering about the unreachability of Statement_Yield

there is no statement context where yield is used as an operator but the return statement is not allowed.

Declaration_Yield_Default BindingIdentifier_Default_Yield

There is no context where "default" can be bound as an identifier and "yield" can also be used as an operator.

# Michael Dyck (11 years ago)

On 14-02-07 03:15 PM, Allen Wirfs-Brock wrote:

The Yield parameter selects whether or not "yield" is treated as an identifier or as an operator symbol. "yield" is only treated as an operator if the yield parameter is present.

Yup, got that.

The GeneratorParameter parameter, when present, tags the use of a production in the parameter list. A yield operation doesn't work as part of an initializer or computed property name in a generator function's parameter list because when parameter declarations are evaluated, the associated generator object is not yet in a yield-able state.

Yup, got that from the Note in 14.4. However, I was puzzled, because it implies that you don't want +Yield to propagate to AssignmentExpressions within the parameter list, and yet that's exactly what's being 'passed' to the Strict/FormalParameters symbols. So it would be useful to augment that Note with something like your next paragraph:

However, to avoid confusion, we want to disallow the use of "yield" as an identifier throughout a generator function including the parameter list. So, we parameterize StrictFormalParameters for generator functions and methods with [Yield, GeneratorParameter]. That parameter combination can be interpreted as don't allow "yield" as an identifier but also don't allow it to be used as an operator.

[I'm going to abbreviate "GeneratorParameter" here as "GP".]

Looking at it some more, I think it nearly doesn't matter whether StrictFormalParameters is 'invoked' with or without 'Yield'. Generally, at any point where you stop propagating the GP parameter, there's a [+GP] rhs-annotation that explicitly says whether or not to pass down 'Yield'. I think the only exception is when FormalParameterList invokes FunctionRestParameter -- if you added [+GP] annotations to that production, then the presence/absence of 'Yield' wouldn't matter at all when 'GP' is present.

(Alternatively, you could give FunctionRestParameter a GP parameter, and do simple propagation from FormalParameterList to FunctionRestParameter to BindingRestElement, which already has a [+GP] annotation.)

[[ I noticed that BindingRestElement doesn't really need its GP parameter -- regardless of parameters, it can't derive a YieldExpression, so it only needs to know whether to allow 'yield' as an identifier, which can be done with just the 'Yield' parameter. But I'm guessing you gave it a GP because it's tidier to do the [+/-GP] split there than in ArrayBindingPattern.

Similarly, I don't think PropertyName needs a GP parameter, but it's slightly tidier to do the [+/-GP] split there than in BindingProperty. ]]

One thing I still don't understand: why does GeneratorExpression invoke BindingIdentifier with Yield but GeneratorDeclaration invokes it without?

# Allen Wirfs-Brock (11 years ago)

On Feb 11, 2014, at 5:36 PM, Michael Dyck wrote:

One thing I still don't understand: why does GeneratorExpression invoke BindingIdentifier with Yield but GeneratorDeclaration invokes it without?

Yield doesn't make any sense as the bound name of a GeneratorExpression because that binding is only visible within the scope of the GeneratorExpression but "yield" can not be used as an identifier within that scope. (I suppose a function nested within the generator function could have a up-level reference to a GeneratorExpression named 'yield' , bu that is jsut going to be confusing...)

The name of a generator function is bound in the surrounding scope, which may be a scope where "yield" is a valid identifier. GeneratorDeclaration looks like it needs to have [Yield] parameter telling it whether or not 'yield' is allowed in the surrounding scope and its reference to BindingIdentifier needs a [?Yield] . FunctionDeclaration/ClassDeclaration need to be handled similarly.