javascript - 如何在 JavaCC 中实现对 token 的负 LOOKAHEAD 检查?

标签 javascript parsing grammar ecmascript-5 javacc

我目前正在实现 JavaScript/ECMAScript 5.1使用 JavaCC 的解析器。我最近learned关于 LOOKAHEAD 在这里很方便,因为语法不完全是 LL(1)。

我在 ECMAScript 语法中看到的一件事是“负向先行检查”,如下所示 ExpressionStatement生产:

ExpressionStatement :
    [lookahead ∉ {{, function}] Expression ;

所以我可能需要类似 LOOKAHEAD(!("{"| "function")) 的东西,但它在这种语法中不起作用。

我的问题是,我如何在 JavaCC 中实现这个“负 LOOKAHEAD”?

阅读 LOOKAHEAD MiniTutorial 后我认为像 getToken(1).kind != FUNCTION 这样的表达式可能就是我需要的,但我不太确定。

最佳答案

对于您提供的示例,我更愿意使用句法前瞻,这在某种意义上必然是“积极的”。

ExpressionStatement 的产生式不是解决问题的地方,因为别无选择。

void ExpressionStatement() : {} { Expression() ";" }

当在表达式语句和 block 之间或表达式语句和函数声明(或两者)之间进行选择时,就会出现问题。

例如在声明中你会发现

void Statement() :{} {
    ...
|
    Block()
|
    ExpressionStatement() 
|   ...
}

给出警告,因为两个选择都可以以“{”开头。你有两个选择。一是忽略警告。只要 Block 优先,就会采取第一个选择,一切都会好起来的。第二种选择是使用前瞻规范来抑制警告。像这样:

void Statement() :{} {
    ...
|
    LOOKAHEAD("{") Block()
|
    ExpressionStatement() 
|   ...
}

从某种意义上来说,句法前瞻是积极的——“如果 X 就采用这个替代方案”。

如果你真的想要一个否定——即“如果不是X,就采用这个替代方案”——向前看,它必须是语义的。

在声明的情况下,你可以写

void Statement() :{} {
    ...
|
    LOOKAHEAD({!(getToken(1)==LBRACE)}) ExpressionStatement() 
|   
    Block()
}

我确保这是最后两个替代方案,否则您需要在阻止 ExpressionStatement() 的标记集中包含更多标记,例如如果下一个标记是“if”、“while”或“for”等,则不应选择它。

总的来说,如果可以的话,最好使用语法前瞻。它通常更直接,更难搞乱。

关于javascript - 如何在 JavaCC 中实现对 token 的负 LOOKAHEAD 检查?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26909200/

相关文章:

javascript - Edge 浏览器中无法导出到 Excel

javascript - 动态改变onclick方法

javascript - Jquery 克隆问题 - 克隆仅显示一次

javascript - 在 Microsoft Edge 上注册服务工作人员时出错

php - 如何使用php解析ipa来收集信息

grammar - 乐语法 : Use named regex without consuming matching string

java - 将字符串解析为 double[]

java - 使用 GSON 将 JSON 字符串转为 Java 对象

c# - 为什么不能在 C# 中没有大括号的 switch 部分中使用 using 变量?

c++ - 解析 C++ 源时的 ANTLR4 相互左递归错误