我正在使用Patrick Hulsmeijer EcmaScript 3 语法构建一个带有 ANTLR 的 JavaScript 工具。
我在解析这行代码时遇到问题:
function(){}();
那是函数表达式的直接调用。解析器将该语句识别为函数声明,然后在找到函数体后面的括号时失败。原因是函数声明被优先识别以避免函数表达式的歧义。
这是语法识别函数声明的方式:
sourceElement
options
{
k = 1 ;
}
: { input.LA(1) == FUNCTION }? functionDeclaration
| statement
;
我什至不确定它是否是有效的 EcmaScript 语句。是吗?
我认为应该更正确的写法:
(function(){})();
这实际上由解析器很好地处理。
顺便说一句,这不是问题的核心,因为我无法控制要检测的代码。
我试图functionDeclaration
从sourceElement
生产中消除并将其投入生产:statement
statementTail
statementTail
: variableStatement
| emptyStatement
| expressionStatement
| functionDeclaration
| ifStatement
| ...
;
但是会出现构建错误:
[致命] 规则
statementTail
具有非 LL(*) 决策,因为可以从 alts 3,4 访问递归规则调用。通过左分解或使用语法谓词或使用backtrack=true
选项来解决。
|---> : 变量声明
因为variableStatement
产生式包含functionExpression
作为后代,这会导致歧义。解析器不能在和之间进行选择functionDeclaration
,functionExpression
因为它们几乎相等:
functionDeclaration
: FUNCTION name=Identifier formalParameterList functionBody
-> ^( FUNCTIONDECL $name formalParameterList functionBody )
;
functionExpression
: FUNCTION name=Identifier? formalParameterList functionBody
-> ^( FUNCTIONEXPR $name? formalParameterList functionBody )
;
注意:我使用不同的树节点(FUNCTIONDECL 和 FUNCTIONEXPR)修改了原始的重写规则,因为我在遍历 AST 时需要它。
我该如何解决这种歧义?