2014-11-06 21 views
1

我繼續在JavaCC grammar上工作ECMAScript 5.1。它實際上相當不錯,我想我已經覆蓋了大部分表達式。如何在JavaCC中實現JavaScript/ECMAScript「no LineTerminator here」規則?

我現在有兩個問題,它們都與自動分號插入有關(第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 */ 
} 

我看了一下lexical states,但我不知道這是否是一個正確的方向。我檢查了我發現的其他一些JavaScript語法,但沒有在那裏找到類似的規則。 (當我嘗試從這些語法中超過某些東西時,我確實感到自己是total cargo culter)。

我很感激指針,提示或只是關鍵字的正確搜索方向。

回答

3

我認爲「限制生產」就可以做到這一點

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

嗯,一個非常有趣的想法。我會嘗試一下。 – lexicore 2014-11-07 08:19:56

+0

或者'getToken(0).endLine == getToken(1).beginLine'。 – 2014-11-08 00:05:04

1

更新作爲岡瑟指出,我原來的解決方案是不正確的,由於該段在規範的7.4:

註釋的行爲與白色空間相似,只是如果MultiLineComment包含行結束符字符,則整個註釋將被視爲LineTerminator,以便通過語法語法進行分析。

我發佈了更正,但在問題結束時留下了原始解決方案。

更正解決方案

的核心理念,所提議的西奧多·諾維爾是使用語義向前看。不過我已經決定實施一個更安全的檢查:

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; 
} 

所以++--在此考慮當且僅當他們沒有行結束之前。

+0

它是否也處理行終止符被埋入MultiLineComment中的情況? ECMA-262規定在這種情況下也不允許。 – Gunther 2015-03-18 10:45:38

+0

@Gunther好問題。不,它可能不會。我會檢查。 – lexicore 2015-03-18 12:02:16

+0

我想原來的提案會涵蓋這種情況,不是嗎?前一段時間,我在添加對[REx解析器生成器](http://bottlecaps.de/rex)的自動分號插入支持時構建了類似的東西。你可以通過在[EcmaScript.ebnf](http://bottlecaps.de/rex/EcmaScript.ebnf)生成的解析器中查找方法followingLineTerminator()並打開'-asi'來找到它 – Gunther 2015-03-18 17:24:40

相關問題