【问题标题】:Javascript and automatic semicolon insertionJavascript 和自动分号插入
【发布时间】:2013-01-14 19:15:26
【问题描述】:

test262 测试套件有 test 包含源:

var x=0, y=0;
var z=
x
++
++
y

注释说:

由于后缀递增/递减运算符(I/DO)和操作数之间的LineTerminator(LT)是不允许的,自动分号插入后两个引用之间用[LT]分隔的两个IO(就像两个DO及其组合)导致语法错误

为什么这段代码会导致语法错误?我认为这是一个有效的代码 sn-p。上面的代码等于var z=x; ++ ++ y;。表达式 ++ ++ yallowed 由 javascript 语法。那么有什么问题呢?

【问题讨论】:

  • ++ ++ y根本不允许
  • @Neal 但是这部作品UnaryExpression : ++UnaryExpression 呢?
  • @sergeyz:作品并不是一切。你可以说这是一种运行时错误,但在编译时可以检测到,因为++ 只能将引用作为其操作数,但永远不会产生一个。

标签: javascript parsing


【解决方案1】:

这段代码将变成:

var z = x;
++ ++ y;

++ ++ y 是问题的根源。让我们看看为什么...

++ ++ y 被评估为++(++y)。第一步是评估(++y)++ 运算符增加它旁边的变量引用的值,并返回增加的值。这里重要的部分是它不返回引用,只返回一个值。所以第二步是++(1),(或任何++y 产生的),这是一个错误,因为只能增加引用。

【讨论】:

  • 正如我在 ECMA-262 中找到相同的解释,你发布了这个答案 :) 很难从标准中提取这些规则,但它基本上是 step 1 of PutValue,由 step 5 of the prefix increment operator 调用.
  • @Tinctorius PutValue 规则说If Type(V) is not Reference, throw a ReferenceError exception. 所以法律上的表达式++ ++ y; 导致运行时错误(异常)?不解析错误?
  • 它通常被静态分析捕获。如果编译器在编译时确定类型是安全的(例如,仅当 Type(V)Reference,在这种情况下)在编译时,您可以在运行时跳过大量类型检查。这不是解析错误,可能是运行时错误,但通常是分析期间的编译时错误。
  • 其实我正在尝试实现js解析器。我认为最好从规范中纠正原始语法并报告语法错误:UnaryExpression: ++LeftHandSideExpression
【解决方案2】:

计算结果为:

var x = 0, y = 0;
var z = x ++ ++ y; //MAKES NO SENSE!

【讨论】:

  • 不,它没有。后缀增量不能由行终止符分隔。真的是var z = x; ++ ++ y;
  • @Tinctorius 仍然是非法的。
  • @Neal 为什么++ ++ y; 是非法的?是解析错误还是运行时错误?
【解决方案3】:

语法不允许在++-- 运算符之前有换行符;这样的换行必须转换为;。因此,表达式必须被解析为:

var x = 0 , y = 0 ;
var z = x ;
++ ;
++ y ;

第三行是非法的。

参考资料:

第 7.9.1 节,“自动分号插入规则”,规则 3

第 11.3 节,“11.3 后缀表达式”。

【讨论】:

  • 不是这样解释的。您可以在前缀递增/递减及其操作数之间使用行终止符。
  • 只有 postfix 运算符有“无换行”规则。前缀运算符可以根据需要使用任意数量的换行符。当然,为什么你会想要超出我的范围:)
  • @rici this production 允许表达式 like ++ ++ y;。这意味着您的代码等于var z = x; ++ ++ y;,而不是var z = x; ++; ++ y;。那么根据语法解析器接受输入和错误实际上是运行时异常?
  • @sergeyz:确实,UnaryExpression 产生式允许多个自动增量,尽管 PostfixExpression 不允许。 (真的很奇怪,因为在任何情况下重复前缀运算符都没有意义。)所以,我同意,我错了,测试用例也是。
  • @sergeyz,我检查了两个 mozilla js 实现(SpiderMonkey 和 JägerMonkey),它们都实现了 UnaryExpression,就好像它包含 ++ LeftSideExpression | -- LeftSideExpression,这也显示在这个旧的 Mozilla 语法中:www-archive.mozilla.org/js/language/grammar14.html。 Google V8引擎按照实际标准进行解析,但会检查前缀++/--的参数是否为LeftSideExpression,如果不是,则将其转换为运行时异常;有一条评论说这是为了与 JSC 兼容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-26
  • 1970-01-01
  • 2023-02-17
  • 2013-02-10
  • 1970-01-01
  • 2011-05-15
  • 1970-01-01
相关资源
最近更新 更多