简体   繁体   English

为什么“抛出”限制生产自动分号插入?

[英]Why is “throw” a restricted production for automatic semicolon insertion?

Part of JavaScript's automatic semicolon insertion algorithm is so-called "restricted productions". JavaScript的自动分号插入算法的一部分是所谓的“限制性制作”。 These are syntactical forms which forbid a newline character from occurring at a certain point. 这些是句法形式,禁止在某一点发生换行符。 To quote the ECMAScript 2015 specification: 引用ECMAScript 2015规范:

If the phrase “[no LineTerminator here]” appears in the right-hand side of a production of the syntactic grammar, it indicates that the production is a restricted production : it may not be used if a LineTerminator occurs in the input stream at the indicated position. 如果短语“[此处没有LineTerminator ]”出现在句法语法生成的右侧,则表示生产是限制生产 :如果LineTerminator出现在输入流中,则可能无法使用它。指示的位置。

There are 10 restricted productions in the ECMAScript 2015 specification: ECMAScript 2015规范中有10个限制产品:

  • PostfixExpression [Yield] : LeftHandSideExpression [?Yield] [no LineTerminator here] ++ PostfixExpression [Yield] LeftHandSideExpression [?Yield] [此处没有LineTerminator ] ++
  • PostfixExpression [Yield] : LeftHandSideExpression [?Yield] [no LineTerminator here] -- PostfixExpression [Yield] LeftHandSideExpression [?Yield] [此处没有LineTerminator ] --
  • ContinueStatement [Yield] : continue [no LineTerminator here] LabelIdentifier [?Yield] ; ContinueStatement [Yield] continue [此处没有LineTerminator ] LabelIdentifier [?Yield] ;
  • BreakStatement [Yield] : break [no LineTerminator here] LabelIdentifier [?Yield] ; BreakStatement [Yield] break [此处没有LineTerminator ] LabelIdentifier [?Yield] ;
  • ReturnStatement [Yield] : return [no LineTerminator here] Expression ; ReturnStatement [Yield] return [此处没有LineTerminator ] 表达式 ;
  • ReturnStatement [Yield] : return [no LineTerminator here] Expression [In, ?Yield] ; ReturnStatement [Yield] return [此处没有LineTerminator ] 表达式 [In,?Yield] ;
  • ThrowStatement [Yield] : throw [no LineTerminator here] Expression [In, ?Yield] ; ThrowStatement [Yield] throw [此处没有LineTerminator ] 表达式 [In,?Yield] ;
  • ArrowFunction [In, Yield] : ArrowParameters [?Yield] [no LineTerminator here] => ConciseBody [?In] ArrowFunction [In,Yield] ArrowParameters [?Yield] [此处没有LineTerminator ] => ConciseBody [?In]
  • YieldExpression [In] : yield [no LineTerminator here] * AssignmentExpression [?In, Yield] YieldExpression [In] yield [此处没有LineTerminator ] * AssignmentExpression [?In,Yield]
  • YieldExpression [In] : yield [no LineTerminator here] AssignmentExpression [?In, Yield] YieldExpression [In] yield [此处没有LineTerminator ] AssignmentExpression [?In,Yield]

Of these productions, I understand the choice to make most of them restricted. 在这些作品中,我理解选择使大部分作品受到限制。 The production for PostfixExpression is restricted to prevent parsing ambiguity with PrefixExpression . 限制PostfixExpression的生成以防止使用PrefixExpression解析歧义。 ContinueStatement , BreakStatement , and ReturnStatement have restricted productions because there are corresponding productions where break and continue do not take labels and return does not take an expression. ContinueStatementBreakStatementReturnStatement具有受限制的产品,因为有相应的产品,其中breakcontinue不带标签, return不带表达式。 I can't say that I know enough about arrow functions or yield expressions to know why they are restricted, but I assume it is to prevent some sort of similar parsing ambiguity. 我不能说我对箭头函数或屈服表达式了解得足以知道为什么它们受到限制,但我认为这是为了防止某种类似的解析模糊。

The production which I don't understand is ThrowExpression . 我不理解的制作是ThrowExpression As far as I can tell, there is no parsing ambiguity involved in using throw like there is when using break , return , and continue : after all, throw; 据我所知,使用throw时没有解析歧义,就像使用breakreturncontinue :毕竟, throw; is not valid JavaScript. 是无效的JavaScript。 I thought that it might be for historical reasons, but as far as I can tell throw; 我认为这可能是出于历史原因,但据我所知, throw; has never been allowed in any JavaScript specification. 从未在任何JavaScript规范中被允许。

The practical consequence of this is that much like with return , you can't put the expression being thrown on the next line, eg this is wrong: 这样做的实际结果就像return ,你不能把表达式抛到下一行,例如这是错误的:

throw
new Error("some error");

However, unlike return , this doesn't have different behavior than putting the new Error() on the same line. 但是,与return不同,这与将new Error()放在同一行上没有不同的行为。 It's just a syntax error: Chrome reports it as 这只是一个语法错误:Chrome将其报告为

Uncaught SyntaxError: Illegal newline after throw 未捕获的SyntaxError:抛出后非法换行

Is the production for ThrowExpression restricted just to maintain consistency with similar contstructs? ThrowExpression的生产是否仅限于保持与类似结构的一致性? Or is there some ambiguity I'm not seeing? 或者是否有一些我没有看到的歧义?

When throw was added to the language in 1998 or so, there was a discussion about whether the throw statement required an expression or not. 当在1998年左右将throw添加到语言中时,讨论了throw语句是否需要表达式。 (The alternative would be that a throw without an expression rethrows the current exception object, as in certain other languages .) (另一种方法是没有表达式的throw会重新抛出当前的异常对象,就像某些其他语言一样 。)

I can't find any record of this discussion, or of the final resolution -- although we know what the resolution was -- but it is mentioned in the TC39 meeting notes for the meeting of February 19, 1998. I suppose that the intent of the restriction was to leave the syntactic space open in case someday the decision were changed. 我找不到任何关于这次讨论或最终解决方案的记录 - 尽管我们知道该决议是什么 - 但是在1998年2月19日的会议的TC39会议记录中提到了这一点。我认为这意味着限制是让句法空间保持开放,以防有一天决定改变。

We can only guess here why the language authors decided to make it so, but I'd say it's for consistency with return . 我们只能猜测为什么语言作者决定这样做,但我会说这是为了与return保持一致。 Both return ¶ value and throw ¶ value are forbidden if you want to complete with the value . 如果要完成throw ¶ value则禁止return ¶ valuethrow ¶ value value That there would be no ambiguity for throw anyway doesn't matter. 无论如何throw都没有歧义并不重要。

I think adeneo's comment is on the right track: like return , the operand to throw is typically a valid expression on its own. 我认为adeneo的评论是在正确的轨道上:像return一样, throw的操作数通常是一个有效的表达式。 The problem with return \\n "valid on its own"; return \\n "valid on its own";的问题return \\n "valid on its own"; is one of the most common examples of ASI problems, so restricting return and any other statements taking a value like that is a reasonable safeguard. 是ASI问题最常见的例子之一,所以限制return和任何其他采用这样的价值的陈述是一个合理的保障。

Looking at the list, most of those are unary operators (or look just like one). 查看列表,其中大多数是一元运算符(或看起来像一个)。 They all follow the same general form, except for arrow functions. 它们都遵循相同的一般形式,箭头函数除外。 That form is a cause of ASI errors, so restricting the whole category is more predictable than just return . 该形式是ASI错误的原因,因此限制整个类别比仅return更可预测。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM