JavaScript语言解析: Distinguish function expressions and declarations

标签 javascript parsing expression declaration abstract-syntax-tree

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

我需要区分 function "declarations"/"statements"function expressions 。因为它们看起来几乎相同,所以我想我需要知道使用 function 的上下文。

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

  • 如果 token 是“函数”,那么
    • 如果之前的 token 是 operator ,
      除了“结束”运算符,例如“]”、“}”或“)”,或者
      如果前一个标记是“:”,那么
      • 函数是一个函数表达式。
    • 其他
      • 函数是函数声明。

我可以期望该算法正确确定函数是声明还是表达式吗?如果有缺陷,应该修复什么?或者,如果仅通过查看前一个标记无法区分表单,那么我怎样才能以最少的努力来区分表单?

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

最佳答案

我也在写JavaScript parser - 对于 Java,使用 JavaCC。是“流行”吗? :)

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

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

现在回答你的问题。

语法:

FunctionDeclaration :
    function Identifier ( FormalParameterList_opt ) { FunctionBody }

FunctionExpression :
    function Identifier_opt ( FormalParameterList_opt ) { FunctionBody }

一种情况函数(很简单。没有标识符 - 不能是FunctionDeclaration。但这并不能保证这个可以 FunctionExpression:顶层的 function () {} 在语法上不正确。

FunctionExpression 可能出现在表达式可能出现的位置 except for ExpressionStatement .

所以问题是,你能否可靠地找出是否可以在词法上的某个地方期待一个表达式(即仅查看前一个标记)。

我认为这可能相当困难。看看my analysis对于类似的问题(从词法上检测正则表达式)。

适合您的算法:

  • 如果 token 是“函数”,那么
    • 如果前一个标记是运算符, 除了“结束”运算符,例如“]”、“}”或“)”,或者
      如果前一个标记是“:”,那么
      • 函数是一个函数表达式。
    • 其他
      • 函数是函数声明。

如果前一个标记是 / 怎么办?接下来是function?您会认为这是一个函数表达式,但它可能是一个正则表达式文字。

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

label: function() {}

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

i++
function a() {}

++function 之前的后缀运算符,但 function a() {} 是函数声明,插入了分号自动位于其前面。

所以我认为你的算法不正确。而且我不确定您是否可以仅仅查看之前的几个标记就可以逃脱惩罚。

关于JavaScript语言解析: Distinguish function expressions and declarations,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27217854/

相关文章:

perl - 如何使用 Perl 解析证书签名请求?

c# - 如何将 DateTime.TryParse() 用于非英语语言(如阿拉伯语)?

java - 将简单的表达式语言放入java

javascript - onclick 按钮,参数值来自文本区域

javascript - 使用 jquery 单击更改 div 内容和 url

javascript - React Native useContext Hooks 问题

ios - 如何使用 JASON pod 解析枚举?

java - switch 语句中使用的 char 数组

c - boolean 表达式求值器错误

javascript - 无法使用 IE11 进行转换