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