12.10 Automatic Semicolon Insertion
Most ECMAScript statements and declarations must be terminated with a semicolon. Such semicolons may always appear explicitly in the source text. For convenience, however, such semicolons may be omitted from the source text in certain situations. These situations are described by saying that semicolons are automatically inserted into the source code token stream in those situations.
12.10.1 Rules of Automatic Semicolon Insertion
In the following rules, “token” means the actual recognized lexical token determined using the current lexical
There are three basic rules of semicolon insertion:
-
When, as the source text is parsed from left to right, a token (called the offending token) is encountered that is not allowed by any production of the grammar, then a semicolon is automatically inserted before the offending token if one or more of the following conditions is true:
-
The offending token is separated from the previous token by at least one
LineTerminator . -
The offending token is
}
. -
The previous token is
)
and the inserted semicolon would then be parsed as the terminating semicolon of a do-while statement (14.7.2 ).
-
The offending token is separated from the previous token by at least one
- When, as the source text is parsed from left to right, the end of the input stream of tokens is encountered and the parser is unable to parse the input token stream as a single instance of the goal nonterminal, then a semicolon is automatically inserted at the end of the input stream.
-
When, as the source text 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 oneLineTerminator , then a semicolon is automatically inserted before the restricted token.
However, there is an additional overriding condition on the preceding rules: a semicolon is never inserted automatically if the semicolon would then be parsed as an empty statement or if that semicolon would become one of the two semicolons in the header of a for
statement (see
The following are the only restricted productions in the grammar:
The practical effect of these restricted productions is as follows:
-
When a
++
or--
token is encountered where the parser would treat it as a postfix operator, and at least oneLineTerminator occurred between the preceding token and the++
or--
token, then a semicolon is automatically inserted before the++
or--
token. -
When a
continue
,break
,return
,throw
, oryield
token is encountered and aLineTerminator is encountered before the next token, a semicolon is automatically inserted after thecontinue
,break
,return
,throw
, oryield
token. -
When arrow function parameter(s) are followed by a
LineTerminator before a=>
token, a semicolon is automatically inserted and the punctuator causes a syntax error. -
When an
async
token is followed by aLineTerminator before afunction
orIdentifierName or(
token, a semicolon is automatically inserted and theasync
token is not treated as part of the same expression or class element as the following tokens. -
When an
async
token is followed by aLineTerminator before a*
token, a semicolon is automatically inserted and the punctuator causes a syntax error.
The resulting practical advice to ECMAScript programmers is:
-
A postfix
++
or--
operator should be on the same line as its operand. -
An
Expression in areturn
orthrow
statement or anAssignmentExpression in ayield
expression should start on the same line as thereturn
,throw
, oryield
token. -
A
LabelIdentifier in abreak
orcontinue
statement should be on the same line as thebreak
orcontinue
token. -
The end of an arrow function's parameter(s) and its
=>
should be on the same line. -
The
async
token preceding an asynchronous function or method should be on the same line as the immediately following token.
12.10.2 Examples of Automatic Semicolon Insertion
This section is non-normative.The source
{ 1 2 } 3
is not a valid sentence in the ECMAScript grammar, even with the automatic semicolon insertion rules. In contrast, the source
{ 1
2 } 3
is also not a valid ECMAScript sentence, but is transformed by automatic semicolon insertion into the following:
{ 1
;2 ;} 3;
which is a valid ECMAScript sentence.
The source
for (a; b
)
is not a valid ECMAScript sentence and is not altered by automatic semicolon insertion because the semicolon is needed for the header of a for
statement. Automatic semicolon insertion never inserts one of the two semicolons in the header of a for
statement.
The source
return
a + b
is transformed by automatic semicolon insertion into the following:
return;
a + b;
The expression a + b
is not treated as a value to be returned by the return
statement, because a return
.
The source
a = b
++c
is transformed by automatic semicolon insertion into the following:
a = b;
++c;
The token ++
is not treated as a postfix operator applying to the variable b
, because a b
and ++
.
The source
if (a > b)
else c = d
is not a valid ECMAScript sentence and is not altered by automatic semicolon insertion before the else
token, even though no production of the grammar applies at that point, because an automatically inserted semicolon would then be parsed as an empty statement.
The source
a = b + c
(d + e).print()
is not transformed by automatic semicolon insertion, because the parenthesized expression that begins the second line can be interpreted as an argument list for a function call:
a = b + c(d + e).print()
In the circumstance that an assignment statement must begin with a left parenthesis, it is a good idea for the programmer to provide an explicit semicolon at the end of the preceding statement rather than to rely on automatic semicolon insertion.
12.10.3 Interesting Cases of Automatic Semicolon Insertion
This section is non-normative.ECMAScript programs can be written in a style with very few semicolons by relying on automatic semicolon insertion. As described above, semicolons are not inserted at every newline, and automatic semicolon insertion can depend on multiple tokens across line terminators.
As new syntactic features are added to ECMAScript, additional grammar productions could be added that cause lines relying on automatic semicolon insertion preceding them to change grammar productions when parsed.
For the purposes of this section, a case of automatic semicolon insertion is considered interesting if it is a place where a semicolon may or may not be inserted, depending on the source text which precedes it. The rest of this section describes a number of interesting cases of automatic semicolon insertion in this version of ECMAScript.
12.10.3.1 Interesting Cases of Automatic Semicolon Insertion in Statement Lists
In a
- An opening parenthesis (
(
). Without a semicolon, the two lines together are treated as aCallExpression . - An opening square bracket (
[
). Without a semicolon, the two lines together are treated as property access, rather than anArrayLiteral orArrayAssignmentPattern . - A template literal (
`
). Without a semicolon, the two lines together are interpreted as a tagged Template (13.3.11 ), with the previous expression as theMemberExpression . - Unary
+
or-
. Without a semicolon, the two lines together are interpreted as a usage of the corresponding binary operator. - A RegExp literal. Without a semicolon, the two lines together may be parsed instead as the
/
MultiplicativeOperator , for example if the RegExp has flags.
12.10.3.2 Cases of Automatic Semicolon Insertion and “[no LineTerminator here]”
This section is non-normative.
ECMAScript contains grammar productions which include “[no
The rest of this section describes a number of productions using “[no
12.10.3.2.1 List of Grammar Productions with Optional Operands and “[no LineTerminator here]”
UpdateExpression .ContinueStatement .BreakStatement .ReturnStatement .YieldExpression .- Async Function Definitions (
15.8 ) with relation to Function Definitions (15.2 )