规范
🌐 Specification
ECMAScript® 2023 语言规范 详细说明了 JavaScript 语言的所有内容,因此任何人都可以实现自己的 JavaScript 引擎。
我们的解析器需要学习以下章节:
🌐 The following chapters need to be studied for our parser:
- 第五章:符号约定
- 第11章:ECMAScript 语言:源文本
- 第12章:ECMAScript语言:词法语法
- 第13-16章:表达式、语句、函数、类、脚本和模块
- 附录 B:Web 浏览器的额外 ECMAScript 特性
- 附件 C:ECMAScript 的严格模式
在规范内导航时:
🌐 For navigation inside the specification:
- 任何可点击的内容都有永久链接,它们会作为锚点显示在URL上,例如“#sec-identifiers”
- 将鼠标悬停在某些内容上可能会显示工具提示,点击
References会显示它的所有引用
符号约定
🌐 Notational Conventions
第5.1.5章 语法符号 是我们需要阅读的部分。
这里需要注意的事项是:
🌐 The things to note here are:
递归
🌐 Recursion
这就是语法中列出内容的方式。
🌐 This is how lists are presented in the grammar.
ArgumentList :
AssignmentExpression
ArgumentList , AssignmentExpression意思
🌐 means
a, b = 1, c = 2
^_____________^ ArgumentList
^__________^ ArgumentList, AssignmentExpression,
^___^ AssignmentExpression可选
🌐 Optional
“opt”后缀用于可选语法。例如,
🌐 The _opt_ suffix for optional syntax. For example,
VariableDeclaration :
BindingIdentifier Initializer_opt意思
🌐 means
var binding_identifier;
var binding_identifier = Initializer;
______________ Initializer_opt参数
🌐 Parameters
[Return] 和 [In] 是语法的参数。
🌐 The [Return] and [In] are parameters of the grammar.
例如
🌐 For example
ScriptBody :
StatementList[~Yield, ~Await, ~Return]意味着在脚本中不允许使用顶层 yield、await 和 return,但
🌐 means top-level yield, await and return are not allowed in scripts, but
ModuleItem :
ImportDeclaration
ExportDeclaration
StatementListItem[~Yield, +Await, ~Return]允许顶层 await。
🌐 allows for top-level await.
源文本
🌐 Source Text
第11.2章 源代码类型 告诉我们,脚本代码和模块代码之间存在巨大的差异。并且有一种 use strict 模式,通过禁止旧的 JavaScript 行为,使语法更加合理。
Script Code is not strict, use strict need to be inserted at the top of the file to make script code strict. In HTML we write <script src="javascript.js"></script>.
Module Code is automatically strict. In HTML we write <script type="module" src="main.mjs"></script>.
ECMAScript语言:词法语法
🌐 ECMAScript Language: Lexical Grammar
想要更深入的解释,请阅读 V8 博客上的《理解 ECMAScript 规范》Understanding the ECMAScript spec。
🌐 For more in-depth explanation, read the V8 blog on Understanding the ECMAScript spec.
自动分号插入
🌐 Automatic Semicolon Insertion
本节描述了在编写 JavaScript 时可以省略分号的所有规则。所有解释归结为
🌐 This section describes all the rules where we can omit a semicolon while writing JavaScript. All the explanation boils down to
pub fn asi(&mut self) -> Result<()> {
if self.eat(Kind::Semicolon) || self.can_insert_semicolon() {
return Ok(());
}
let range = self.prev_node_end..self.cur_token().start;
Err(SyntaxError::AutoSemicolonInsertion(range.into()))
}
pub const fn can_insert_semicolon(&self) -> bool {
self.cur_token().is_on_new_line || matches!(self.cur_kind(), Kind::RCurly | Kind::Eof)
}asi 函数需要在适用的地方手动调用,例如在语句结尾处:
🌐 The asi function need to be manually called where applicable, for example in the end of statement:
fn parse_debugger_statement(&mut self) -> Result<Statement<'a>> {
let node = self.start_node();
self.expect(Kind::Debugger)?;
self.asi()?;
self.ast.debugger_statement(self.finish_node(node))
}INFO
这一部分关于 asi 的内容是针对解析器编写的,它明确说明源文本是从左到右解析的,这几乎使得解析器不可能用其他方式编写。jsparagus 的作者在这里对此发表了长篇抱怨。
🌐 This section on asi is written with a parser in mind, it explicitly states that the source text is parsed from left to right, which makes it almost impossible to write the parser in any other way. The author of jsparagus made a rant about this here.
该功能的规范既是非常高层次的,又奇怪地采用了过程化描述(“当从左到右解析源文本时,遇到一个标记时……”,就好像规范在讲述浏览器的故事一样。据我所知,这是规范中唯一假设或暗示解析内部实现细节的地方)。但以其他方式来规范自动分号插入(ASI)会很困难。
表达式、语句、函数、类、脚本和模块
🌐 Expressions, Statements, Functions, Classes, Scripts and Modules
理解语法语法需要一段时间,然后将其应用于编写解析器。
🌐 It takes a while to understand the syntactic grammar, then apply them to writing a parser.
