JavaScript 语言解析:区分函数表达式和声明

JavaScript Language Parsing: Distinguish function expressions and declarations

本文关键字:函数 表达式 声明 语言 JavaScript      更新时间:2023-09-26

假设我正在创建一个简单的JavaScript语言解析器,它只涉及解析函数。

我需要区分函数"声明"/"语句"和函数表达式。因为它们看起来几乎相同,所以我想我需要知道使用function的上下文。

我想我可以通过前面的标记确定函数表达式。我认为以下算法可能有效:

  • 如果令牌是"函数",则
    • 如果上一个令牌是运算符,
      除了"关闭"运算符,如"]"、"}"或"(",或
      如果上一个标记是 ":",则
        函数
      • 是函数表达式。
      • 函数
      • 是一个函数声明。

我是否可以期望此算法正确确定function是声明还是表达式?如果有缺陷,应该修复什么?或者,如果仅通过查看以前的令牌无法区分表单,那么我如何以最少的努力区分表单?

(我知道Esprima和co.存在。我想用不同的语言实现本机解析器。

我也在写一个JavaScript解析器 - 用于Java,使用JavaCC。是"流行"吗?:)

我不是专家,所以我的术语可能有点家庭水平,请原谅。

如果我理解正确了你的想法,似乎你想在词汇级别区分函数声明和表达式。我认为这是一种错误的方式。JavaScript 有一个非常棘手的语法,这可能适用于函数声明,但你会一路遇到极端情况。最复杂的两个是自动分号插入和正则表达式与除法。

现在回答你的问题。

语法:

FunctionDeclaration :
    function Identifier ( FormalParameterList_opt ) { FunctionBody }
FunctionExpression :
    function Identifier_opt ( FormalParameterList_opt ) { FunctionBody }

一个案例function (很容易。无标识符 - 不能是FunctionDeclaration。然而,这并不能保证这可以FunctionExpression:顶层的function () {}在语法上是不正确的。

ExpressionStatement 之外,表达式可能出现的位置可能会出现FunctionExpression

所以问题是,您能否可靠地找出是否可以在词法上的某个地方期待表达式(即只是查看以前的令牌(。

我认为这可能相当困难。看看我对类似问题的分析(以词法检测正则表达式(。

为您算法:

  • 如果令牌是"函数",则
    • 如果上一个令牌是运算符,除了"关闭"运算符,如"]"、"}"或"(",或
      如果上一个标记是 ":",则
        函数
      • 是函数表达式。
      • 函数
      • 是一个函数声明。

如果以前的令牌是/的怎么办?接下来function呢?你会认为这是一个函数表达式,但这可能是一个正则表达式文字。

另外:这并不意味着这是一个函数表达式,这可能是无效的:

label: function() {}

我还认为ASI可能会带来进一步的并发症。考虑:

i++
function a() {}

++ 是前面的后缀运算符function,但function a() {}是一个函数声明,则在它前面自动插入了一个分号。

所以我认为你的算法不正确。而且我不确定您能否简单地查看以前的几个令牌。