javascript - 用于 JavaScript/ECMAScript 数组文字生成的 LOOKAHEAD

标签 javascript parsing grammar ecmascript-5 javacc

我目前正在执行一个 JavaScript/ECMAScript 5.1解析器与 JavaCC 有问题 ArrayLiteral生产。

ArrayLiteral :
    [ Elision_opt ]
    [ ElementList ]
    [ ElementList , Elision_opt ]

ElementList :
    Elision_opt AssignmentExpression
    ElementList , Elision_opt AssignmentExpression

Elision :
    ,
    Elision ,

我有三个问题,我会一一提问。

这是第二个。


我已将此产生式简化为以下形式:

ArrayLiteral:
    "[" ("," | AssignmentExpression ",") * AssignmentExpression ? "]"

请看第一题是否正确:

How to simplify JavaScript/ECMAScript array literal production?

现在我尝试在 JavaCC 中实现如下:

void ArrayLiteral() :
{
}
{
    "["
    (
        ","
    |   AssignmentExpression()
        ","
    ) *
    (
        AssignmentExpression()
    ) ?
    "]"
}

JavaCC 提示模棱两可 ,AssignmentExpression (其内容)。显然,一个 LOOKAHEAD规范是必需的。我花了很多时间试图计算 LOOKAHEAD出来了,尝试了不同的东西,比如

  • LOOKAHEAD (AssignmentExpression() ",")(...)*
  • LOOKAHEAD (AssignmentExpression() "]")(...)?

和一些其他变体,但我无法摆脱 JavaCC 警告。

我不明白为什么这不起作用:

void ArrayLiteral() :
{
}
{
    "["
    (
        LOOKAHEAD ("," | AssignmentExpression() ",")
        ","
    |   AssignmentExpression()
        ","
    ) *
    (
        LOOKAHEAD (AssignmentExpression() "]")
        AssignmentExpression()
    ) ?
    "]"
}

好的,AssignmentExpression()本身是模棱两可的,但尾随 ",""]"LOOKAHEAD s 应该明确应该采取哪些选择 - 或者我在这里弄错了吗?

什么是正确的 LOOKAHEAD这个产品的规范是什么样的?

更新

不幸的是,这没有用:

void ArrayLiteral() :
{
}
{
    "["
    (
        ","
    |
        LOOKAHEAD (AssignmentExpression() ",")
        AssignmentExpression()
        ","
    ) *
    (
        AssignmentExpression()
    ) ?
    "]"
}

警告:

Warning: Choice conflict in (...)* construct at line 6, column 5.
         Expansion nested within construct and expansion following construct
         have common prefixes, one of which is: "function"
         Consider using a lookahead of 2 or more for nested expansion.

第 6 行是 (在第一个之前 LOOKAHEAD .公共(public)前缀 "function"只是 AssignmentExpression 的可能开始之一.

最佳答案

JavaCC 生成自上而下的解析器。顺便说一句,我不是自上而下的解析器生成器的粉丝,所以我不是 JavaCC 专家,也没有方便的测试。

(编辑:我认为其他方法会起作用,但后来我意识到我不明白 JavaCC 如何将先行附加到实际选择;在 ( A | B ) 的情况下* C,其实有A、B、C三种可能的选择,我以为它会考虑这三个,但有可能一次只考虑两个。所以下面是另一种猜测。 )

话虽如此,我认为以下内容可行,但它涉及对几乎每个 AssignmentExpression() 进行两次解析。

{
    "["
    (
        ","
    |
        AssignmentExpression()
        ","
    ) *
    (
        LOOKAHEAD (AssignmentExpression() "]")
        AssignmentExpression()
    ) ?
    "]"
}

正如我在 the linked question 中指出的那样,更好的解决方案是以不同方式重写产生式:

"[" AssignmentExpression ? ("," AssignmentExpression ?) * "]"

这会导致单标记先行语法,因此您不需要 LOOKAHEAD 声明来处理它。

关于javascript - 用于 JavaScript/ECMAScript 数组文字生成的 LOOKAHEAD,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26908705/

相关文章:

python - Django DB 表名,复数 double s

javascript - 在 html 页面上一次播放一个视频

javascript - 需要帮助选择 JS/jQuery 事件

node.js - Nodejs 中查询字符串的多种类型

c - 每次我从 C 中的输入文件读取 '\n' 时都无法循环函数

reference - Xtext:对属性的 DSL 引用

javascript - 如何在 ES6 类中使用组合和方法?

javascript - 如何根据多个键有条件地对数组进行分组?

C#:如何以编程方式将 SQL 脚本导入数据库?

java - 我想使用 ANTLR4 从 java 源文件中提取所有方法名称和变量名称