假设我正在创建一个仅与解析函数有关的简单JavaScript语言解析器。
我需要区分function "declarations"/"statements"和function expressions。因为它们看起来几乎相同,我想我需要知道使用function
的上下文。
我想我可以通过前面的标记来确定函数表达式。我认为以下算法可能有效:
我能指望此算法正确判断function
是声明还是表达式?如果它有缺陷,应该修复什么?或者,如果仅仅通过查看前一个标记就无法区分表单,那么我怎样才能以最少的努力来区分表单呢?
(我知道Esprima和co。存在。我想用不同的语言实现 native 解析器。)
答案 0 :(得分:2)
我也在用JavaCC编写一个JavaScript parser - 用于Java。它是“时尚”吗? :)
我不是专家,所以我的术语可能有点家庭,请原谅。
如果我理解你的想法,似乎你想在词汇层面上区分函数声明和表达式。我认为这是一种错误的方式。 JavaScript有一个非常棘手的语法,这可能与函数声明一起使用,但是你将会遇到各种各样的问题。其中两个最复杂的是自动分号插入和正则表达式与分割。
现在回答你的问题。
语法:
FunctionDeclaration :
function Identifier ( FormalParameterList_opt ) { FunctionBody }
FunctionExpression :
function Identifier_opt ( FormalParameterList_opt ) { FunctionBody }
一个案例function (
很容易。没有标识符 - 不能是FunctionDeclaration
。但是,这并不能保证此 可以FunctionExpression
:顶层的function () {}
在语法上不正确。
FunctionExpression
可能会出现在表达式可能显示的位置except for ExpressionStatement
。
所以问题是,你能否可靠地找出你是否可以在某个地方词汇表达一个表达式(即只看上一个令牌)。
我认为这可能相当困难。看一下my analysis的类似问题(从词汇上检测正则表达式)。
对于你的算法:
如果上一个令牌是/
怎么办?接下来是function
?你会认为这是一个函数表达式,但这可能是一个正则表达式文字。
同样:
并不意味着这是一个函数表达式,这可能是无效:
label: function() {}
我还认为ASI可能会出现进一步的并发症。考虑:
i++
function a() {}
++
是function
之前的后缀运算符,但function a() {}
是函数声明,在它之前会自动插入分号。
所以我认为你的算法不正确。而且我不确定你是否可以通过简单地查看几个以前的令牌来逃脱。