javascript - JavaCC中如何实现JavaScript自动插入分号?

标签 javascript parsing dojo grammar javacc

我正在完成我的 ECMAScript 5.1/JavaScript grammar for JavaCC 。我已经按照规范完成了所有代币和制作。

现在我面临一个大问题,我不知道如何解决。

JavaScript 具有自动分号插入的这个很好功能:

What are the rules for JavaScript's automatic semicolon insertion (ASI)?

quote the specifications ,规则为:

There are three basic rules of semicolon insertion:

  1. When, as the program 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 }.
  2. When, as the program 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 complete ECMAScript Program, then a semicolon is automatically inserted at the end of the input stream.

  3. When, as the program 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 one LineTerminator, 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 12.6.3).

如何使用 JavaCC 实现此功能?

到目前为止我找到的答案最接近的是 this grammar来自 Dojo 工具包,该工具包有一个名为 insertSemiColonJAVACODE 部分,专门用于该任务。但我没有看到这个方法在任何地方被调用(无论是在语法中还是在整个 jslinker 代码中)。

如何使用 JavaCC 解决这个问题?

另请参阅这个问题:

javascript grammar and automatic semocolon insertion

(没有答案。)

评论中的一个问题:

Is it correct to say that semicolons need only be inserted where semicolons are syntactically allowed?

我认为正确的说法是,仅在语法上需要的地方才需要插入分号。

这里的相关部分是§7.9:

7.9 Automatic Semicolon Insertion

Certain ECMAScript statements (empty statement, variable statement, expression statement, do-while statement, continue statement, break statement, return statement, and throw statement) must be terminated with semicolons. 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.

让我们以return语句为例:

ReturnStatement :
    return ;
    return [no LineTerminator here] Expression ;

因此(根据我的理解)语法上分号是必需的,而不仅仅是允许(如您的问题中所示)。

最佳答案

分号插入的3条规则可以在section 7.9.1 of the ECMAScript 5.1 standard中找到

我认为标准中的规则 1 和 2 可以通过语义前瞻来处理。

void PossiblyInsertedSemicolon() 
{}
{
    LOOKAHEAD( {semicolonNeedsInserting()} ) {}
|
    ";"
}

那么什么时候需要插入分号呢?当其中之一为真时

  • 当下一个标记不是分号且位于另一行时 ( getToken(1).kind != SEMICOLON && getToken(0).endLine < getToken(1).beginLine )
  • 当下一个标记是右大括号时。
  • 当下一个标记是 EOF 时

所以我们需要

boolean semicolonNeedsInserting() {
    return (`getToken(1).kind != SEMICOLON && getToken(0).endLine < getToken(1).beginLine`) 
    || getToken(1).kind == RBRACE
    || getToken(1).kind == EOF ;
}

这符合标准的规则 1 和 2。

对于规则 3(限制制作),如我对 this question 的回答中所述,你可以执行以下操作

void returnStatement()
{}
{
    "return"
    [   // Parse an expression unless either the next token is a ";", "}" or EOF, or the next token is on another line.
        LOOKAHEAD( {   getToken(1).kind != SEMICOLON
                    && getToken(1).kind != RBRACE
                    && getToken(1).kind != EOF
                    && getToken(0).endLine == getToken(1).beginLine} )
        Expression()
    ]
    PossiblyInsertedSemicolon() 
}

关于javascript - JavaCC中如何实现JavaScript自动插入分号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27069755/

相关文章:

javascript - 多次重复一组方法的设计模式

Javascript:从字符串(包括查询字符串)中提取 URL 并返回数组

php - 使用php从xml中提取信息

javascript - 如何在nodejs中重复执行

javascript - 在 ASP.NET Web API 2 项目中为 Angular 设置路由

html - 防止其他 div 内的 2 div 换行

dojo - 支离 splinter 的 Dojo 构建文档

javascript - Dojo 访问外部文件中的 javascript 对象

javascript - node.js 返回未定义的问题

parsing - F# 中针对列表开头进行模式匹配的更简单方法