簡體   English   中英

如何在JavaCC中實現JavaScript / ECMAScript“此處沒有LineTerminator”規則?

[英]How to implement JavaScript/ECMAScript “no LineTerminator here” rule in JavaCC?

我將繼續為ECMAScript 5.1編寫JavaCC語法 它實際上運行得很好,我想我現在已經涵蓋了大多數表達式。

我現在有兩個問題,它們都與自動分號插入有關(第7.9.1節)。 這就是其中之一。

該規范定義了以下產品:

PostfixExpression :
    LeftHandSideExpression
    LeftHandSideExpression [no LineTerminator here] ++
    LeftHandSideExpression [no LineTerminator here] --

如何實現可靠的“此處沒有LineTerminator”檢查?

為了記錄,我的LINE_TERMINATOR目前類似:

SPECIAL_TOKEN :
{
    <LINE_TERMINATOR: <LF> | <CR> | <LS> | <PS> >
|   < #LF: "\n" > /* Line Feed */
|   < #CR: "\r" > /* Carriage Return */
|   < #LS: "\u2028" > /* Line separator */
|   < #PS: "\u2029" > /* Paragraph separator */
}

我已經閱讀了有關詞法狀態的信息 ,但是我不確定這是否是正確的方向。 我檢查了我發現的其他一些JavaScript語法,但沒有在其中找到任何類似的規則。 (當我嘗試從這些語法中超越某些東西時,我實際上感覺自己是一個全面的貨神 。)

我會為正確的搜索方向提供一個指針,一個提示或只是一個關鍵字。

我認為對於“限產”,您可以這樣做

void PostfixExpression() : 
{} {
     LeftHandSideExpression() 
     (
         LOOKAHEAD( "++", {getToken(0).beginLine == getToken(1).beginLine})
         "++"
     |
         LOOKAHEAD( "--", {getToken(0).beginLine == getToken(1).beginLine})
         "--"
     |
         {}
     )
}

更新正如Gunther指出的,由於規范7.4中的這一段,我的原始解決方案是不正確的:

注釋的行為類似於空格,並且被丟棄,除了注釋之外,如果MultiLineComment包含行終止符,則出於語法語法分析的目的,整個注釋都被視為LineTerminator。

我正在發布更正,但問題的末尾保留了原始解決方案。

更正的解決方案

Theodore Norvell提出的核心思想是使用語義超前。 但是我決定實施更安全的檢查:

public static boolean precededByLineTerminator(Token token) {
    for (Token specialToken = token.specialToken; specialToken != null; specialToken = specialToken.specialToken) {
        if (specialToken.kind == EcmaScriptParserConstants.LINE_TERMINATOR) {
            return true;
        } else if (specialToken.kind == EcmaScriptParserConstants.MULTI_LINE_COMMENT) {
            final String image = specialToken.image;
            if (StringUtils.containsAny(image, (char)0x000A, (char)0x000D, (char)0x2028,
                    (char)0x2029)) {
                return true;
            }
        }
    }
    return false;
}

語法是:

expression = LeftHandSideExpression()
(
    LOOKAHEAD ( <INCR>, { !TokenUtils.precededByLineTerminator(getToken(1))} )
    <INCR>
    {
        return expression.postIncr();
    }
|   LOOKAHEAD ( <DECR>, { !TokenUtils.precededByLineTerminator(getToken(1))} )
    <DECR>
    {
        return expression.postDecr();
    }
) ?
{
    return expression;
}

因此,此處考慮++--前提是它們前面沒有行終止符。


原始解決方案

不是我最終解決它的方式。

Theodore Norvell提出的核心思想是使用語義超前。 但是我決定實施更安全的檢查:

public static boolean precededBySpecialTokenOfKind(Token token, int kind) {
    for (Token specialToken = token.specialToken; specialToken != null; specialToken = specialToken.specialToken) {
        if (specialToken.kind == kind) {
            return true;
        }
    }
    return false;
}

語法是:

expression = LeftHandSideExpression()
(
    LOOKAHEAD ( <INCR>, { !TokenUtils.precededBySpecialTokenOfKind(getToken(1), LINE_TERMINATOR)} )
    <INCR>
    {
        return expression.postIncr();
    }
|   LOOKAHEAD ( <DECR>, { !TokenUtils.precededBySpecialTokenOfKind(getToken(1), LINE_TERMINATOR)} )
    <DECR>
    {
        return expression.postDecr();
    }
) ?
{
    return expression;
}

因此,此處考慮++--前提是它們前面沒有行終止符。

暫無
暫無

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

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