如何在这里实现JavaScript / ECMAScript"没有LineTerminator" JavaCC中的规则?

时间:2014-11-06 15:09:12

标签: javascript ecmascript-5 javacc

我继续为JavaCC grammar ECMAScript 5.1工作。它实际上非常顺利,我想我现在已经涵盖了大多数表达式。

我现在有两个问题,它们都与自动分号插入有关(§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。)

我很感激指针,提示或只是正确搜索方向的关键字。

2 个答案:

答案 0 :(得分:3)

我认为对于限制性制作&#34;你可以这样做

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

答案 1 :(得分:1)

更新正如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;
}

因此,如果++--之前没有行终止符,则会考虑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; }


原始解决方案

是我最终解决的问题。

Theodore Norvell提出的核心思想是使用语义预测。但是我决定实施更安全的检查:

++

语法是:

--

因此,如果{{1}}或{{1}}之前没有行终止符,则会考虑{{1}}或{{1}}。