3
votes

According to this, JavaScript will insert a semicolon if:

When the program contains a token that is not allowed by the formal grammar, then a semicolon is inserted if (a) there is a line break at that point, or (b) the unexpected token was a closing brace. (emphasis mine)

The classic example is

return  //  <--- semicolon inserted there
{
   id: 12
};

Which leads me to believe that a free standing { is not valid. Yet the following (pointless) code alerts 2, without error

function foo() {
    var x = 1;
    {
        var y = 2; //yes, I know y has the same scope as x 
    }              //and that this is therefore pointless
    alert(y);
}

Why is the opening brace treated as an invalid token in the first code, which leads JavaScript to insert a semicolon, but the opening brace is not treated as invalid in the second—as evidenced by the fact that there is no error.

Clearly one of my assumptions is wrong, and I was hoping someone could help me understand which.

3

3 Answers

5
votes

The return statement problem you mention is not affected by that particular aspect of the semicolon insertion rule. Rather, it's this one:

When, as the program is parsed from left to right, a token is encountered that is allowed by some production of the grammar, but the production is a restricted production and the token would be the first token for a terminal or nonterminal immediately following the annotation ―[no LineTerminator here]‖ within the restricted production (and therefore such a token is called a restricted token), and the restricted token is separated from the previous token by at least one LineTerminator, then a semicolon is automatically inserted before the restricted token.

It so happens that the return statement syntax has one of those "[no LineTerminator here]" quirks.

See section 7.9.1 of the ES 5 spec.

2
votes

The rule is like this: if there is a new line, and we have a valid statement so far, then insert a semicolon.

In your first example this is valid:

return;  //  <--- semicolon inserted there
{
   id: 12
};

In the second example, this is invalid:

function foo() {
    var x = 1;
    {;             // *not a valid insertion*
        var y = 2; // yes, I know y has the same scope as x 
    }              // and that this is therefore pointless
    alert(y);
}

EDIT: This answer is not entirely correct! For example:

num = 4 + 5
  + 1;

// returns 10

See comments below:

0
votes

You're talking about keywords that are expecting blocks and keywords expecting expressions - return isn't like function or if, that are expecting a block ({ }) - so the parser is going to insert the semi-colon like other keywords not expecting braces.