JavaScript中无需解析即可进行自动分号插入。

4
我正在编写一个JavaScript预处理器,它会自动在必要的地方插入分号。不要问为什么。
现在我知道解决这个问题的一般方法是编写一个JavaScript解析器,并根据规范中的规则在必要时添加分号。但是出于以下原因,我不想这样做:
1. 我不想编写一个完整的解析器。 2. 我想保留注释和空格。
我已经使用一个简单的扫描器实现了第二条和第三条自动插入分号的规则(正确)。
然而,第一条规则证明更具挑战性。所以我有三个问题:
1. 是否可能使用带有前瞻和后顾的简单扫描器来实现第一条规则? 2. 如果可能,那么是否已经有人这样做了? 3. 如果不行,那么我应该如何解决这个问题?
为了完整起见,这里是三个规则:
当程序从左到右解析时,如果遇到一个令牌(称为“有问题的令牌”),该令牌不被语法规则中的任何产生式所允许,则在以下一个或多个条件为真时,在有问题的令牌之前自动插入分号: 1. 有问题的令牌与前一个令牌至少相隔一个LineTerminator。 2. 有问题的令牌是"}"。 当程序从左到右解析时,如果遇到输入令牌流的末尾并且解析器无法将输入令牌流解析为单个完整的ECMAScript程序,则在输入流的末尾自动插入分号。 当程序从左到右解析时,如果遇到允许由语法规则的某些产生式的令牌,但产生式是受限制的产生式,并且该令牌将成为紧接着受限制产生式中的注释“[no LineTerminator here]”之后的终端或非终端的第一个令牌(因此这样的令牌称为受限制的令牌),并且受限制的令牌与前一个令牌至少隔开一个LineTerminator,则在受限制的令牌之前自动插入分号。 但是,上述规则还有一个额外的优先条件:如果自动插入分号会被解析为空语句或该分号将成为for语句头中的两个分号之一(参见12.6.3),则永远不会自动插入分号。

2
是的,我要问...为什么要实现一个预处理器来做JS引擎已经为您完成的工作呢? - the system
3
请使用当前版本的规范,参见 http://ecma-international.org/ecma-262/5.1/ 或 http://es5.github.com/ - Bergi
1
@thesystem - 为了好玩。 - Aadit M Shah
1
@AaditMShah:说实话,我想不出比这更好的答案了。其他任何目的都似乎是徒劳的。 - the system
@Bergi - 看起来自动分号插入的规则没有改变。 - Aadit M Shah
@AaditMShah:是的,我也不知道。我只是被可怕的布局所疏远 :-) - Bergi
1个回答

4
使用扫描仪(标记化程序)无法达到您想要的目的。这是因为要回答“我们需要在这里使用分号吗?”您需要回答“下一个令牌是否是一个违规的令牌?”而要回答这个问题,您需要一种JavaScript语法,因为违规令牌的定义是语法不允许在此处出现的东西。
我曾经尝试过创建所有令牌的列表,然后在第二步处理该列表(以便获得一些上下文)。使用这种方法,您可以通过编写以下代码来修复一些位置:
- 反向迭代令牌(从最后一个开始,向文件的开头前进) - 如果当前令牌是IF, FOR, WHILE, VAR等: - 跳过令牌之前的空格和注释 - 如果当前令牌不是 ; ,则插入一个;
这种方法之所以有效,是因为错误不是随机发生的。人们总是犯同样的错误。大多数情况下,人们忘记在行末添加 ; ,查找关键字前缺少的 ; 是定位它们的好方法。
但是,这种方法只能让您走得这么远。如果您必须可靠地找到所有缺少的分号,那么您必须编写JavaScript解析器(或重用现有的解析器)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接