问题描述
我正在使用 Patrick Hulsmeijer EcmaScript 3语法用ANTLR构建JavaScript工具.
I am building a JavaScript instrumentor with ANTLR, using the Patrick Hulsmeijer EcmaScript 3 grammar.
我在解析此行代码时遇到问题:
I'm having a problem parsing this line of code:
function(){}();
是函数表达式的直接调用.解析器将该语句识别为函数声明,然后在找到函数主体后的括号时失败.原因是函数声明具有最高优先级,以避免函数表达式含糊不清.
that is a direct call of a function expression.The parser recognizes the statement as a function declaration and then fails when it finds the parentheses after the function body. The reason is that function declarations are recognized with most precedence to avoid the ambiguity with function expressions.
这是语法识别函数声明的方式:
This is how the grammar recognizes function declarations:
sourceElement
options
{
k = 1 ;
}
: { input.LA(1) == FUNCTION }? functionDeclaration
| statement
;
我什至不确定它是否是有效的EcmaScript语句.是吗?
我认为这样写应该更正确:
I am not even sure that it is a valid EcmaScript statement. Is it?
I think it should be more correct to write:
(function(){})();
实际上解析器可以很好地处理它.
顺便说一下,这不是问题的核心,因为我无法控制要检测的代码.
which is actually well handled by the parser.
By the way this is not the core of the question, because I have no control over the code to instrument.
我试图从sourceElement
生产中删除functionDeclaration
并将其放入 statementTail
生产中:
I tried to eliminate functionDeclaration
from the sourceElement
production and to put it in the statementTail
production:
statementTail
: variableStatement
| emptyStatement
| expressionStatement
| functionDeclaration
| ifStatement
| ...
;
但是出现构建错误:
因为variableStatement
产生式包含functionExpression
作为后代,这导致了歧义.解析器无法在functionDeclaration
和functionExpression
之间进行选择,因为它们几乎相等:
because the variableStatement
production contains functionExpression
as a descendant, which leads to an ambiguity. The parser cannot choose among functionDeclaration
and functionExpression
because they are almost equal:
functionDeclaration
: FUNCTION name=Identifier formalParameterList functionBody
-> ^( FUNCTIONDECL $name formalParameterList functionBody )
;
functionExpression
: FUNCTION name=Identifier? formalParameterList functionBody
-> ^( FUNCTIONEXPR $name? formalParameterList functionBody )
;
注意:我在使用AST时需要使用不同的树节点(FUNCTIONDECL和FUNCTIONEXPR)来修改原始重写规则.
Note: I modified the original rewrite rules using different tree nodes (FUNCTIONDECL and FUNCTIONEXPR) because I need it while walking the AST.
如何解决这种歧义?
推荐答案
当sourceElement以'function'关键字开头时,解析器期望有functionDeclaration是正确的.实际上,这从 ECMAScript语言规范中实现了以下限制:
The parser is right to expect a functionDeclaration, when a sourceElement begins with the 'function' keyword. This in fact implements the following restriction from the ECMAScript Language Specification:
因此,根据上述限制,所讨论的语句是无效的,尽管实际上它在语法生成上并不是模棱两可的:因为它省略了函数标识符,所以不能是functionDeclaration.暴露句法歧义的声明将是
The statement in question thus is invalid per the above restriction, though in fact it is not ambiguous by productions of the grammar: as it omits the function identifier, it cannot be a functionDeclaration. A statement exposing the syntactic ambiguity would be
function f(){}(42)
根据ECMAScript规范,该函数是functionDeclaration,后跟expressionStatement.
which according to the ECMAScript spec is a functionDeclaration, followed by an expressionStatement.
因此,最好的办法是要求此代码的提供者提供正确的语法.您说的是无论如何都需要解析它,并且可以使用ANTLR的回溯来完成.确保函数标识符在functionDeclaration中是必需的,并在语句前尝试使用functionDeclaration.但是请注意,即使这对原始语句有所帮助,它也会因以下原因而失败
So the best thing to do is ask the provider of this code for correct syntax. You were saying that you need to parse it anyway, and that could possibly be done using ANTLR's backtracking. Make sure the function identifier is mandatory in the functionDeclaration, and have it try a functionDeclaration before a statement. But be aware that, even if this helps for the original statement, it will fail for
function f(){}()
因为在这里functionDeclaration可以成功完成,但是后面没有有效的语句.
because here the functionDeclaration can be completed successfully, but there is no valid statement following it.
这篇关于如何使用ANTLR解析JavaScript函数表达式调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!