簡體   English   中英

如何在JavaCC中實現JavaScript自動分號插入?

[英]How to implement JavaScript automatic semicolon insertion in JavaCC?

我正在完成JavaCC的 ECMAScript 5.1 / JavaScript 語法 我已經按照規范完成了所有標記和制作。

現在,我面臨着一個大問題,我不知道該如何解決。

JavaScript具有自動分號插入的這一出色功能:

JavaScript自動分號(ASI)的規則是什么?

引用規范 ,規則是:

分號插入有三個基本規則:

  1. 當從左到右解析程序時,遇到任何語法產生都不允許的令牌(稱為冒犯令牌)時,如果以下一項或多項操作,則在冒犯令牌之前會自動插入分號條件為真:

    • 至少有一個LineTerminator將有問題的令牌與前一個令牌分開。
    • 令人討厭的令牌是}
  2. 當從左向右解析程序時,遇到令牌輸入流的末尾,並且解析器無法將輸入令牌流作為單個完整的ECMAScript程序進行解析,則分號將自動插入到末尾。輸入流。

  3. 當從左向右解析程序時,遇到某種語法的某種生產所允許的令牌,但是該生產是受限制的生產,並且該令牌將成為緊隨注解之后的終端或非終端的第一個令牌在受限產品中[no LineTerminator here] (因此,此類令牌稱為受限令牌),並且受限令牌與至少一個LineTerminator與前一個令牌分開,然后在受限令牌之前自動插入分號。

但是,上述規則還有一個額外的優先條件:如果分號隨后將被解析為空語句,或者如果該分號成為for語句的標頭中的兩個分號之一,則永遠不會自動插入分號。 12.6.3 )。

如何用JavaCC來實現呢?

到目前為止,我發現的答案JAVACODE是Dojo工具箱中的這種語法工具箱具有專門用於該任務的JAVACODE部分,稱為insertSemiColon 但是我看不到在任何地方都可以調用此方法(無論是在語法上還是在整個jslinker代碼中)。

如何用JavaCC解決這個問題?

另請參閱以下問題:

javascript語法和semocolon自動插入

(那里沒有答案。)

評論中的一個問題:

說分號只需要在語法上允許分號的地方插入是正確的嗎?

我認為說分號僅在語法上需要分號的地方插入是正確的。

這里的相關部分是第7.9節:

7.9自動分號插入

某些ECMAScript語句(空語句,變量語句,表達式語句,do-while語句,continue語句,break語句,return語句和throw語句)必須以分號終止。 這樣的分號可能總是顯式地出現在源文本中。 但是,為方便起見,在某些情況下可以從源文本中省略此類分號。 通過說在這些情況下將分號自動插入到源代碼令牌流中來描述這些情況。

讓我們以return語句為例:

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

因此(從我的理解)從語法上說 ,分號是必需的 ,而不僅僅是被允許的 (如您的問題)。

分號插入的3條規則可以在ECMAScript 5.1標准的7.9.1節中找到

我認為標准中的規則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(限制生產),您可以執行以下操作

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() 
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM