使用 Lezer 语法树
由 @lezer/generator 生成的 JavaScript 文件,其中导出的变量(默认名称)parse 绑定的是一个 LRParser 实例,调用其方法 parse 对给定内容(符合 Input 类型的对象或纯字符串)进行解析,获得语法树
import { parser } from './parser'
// 调用 `parser.parse()` 方法对传入的字符串进行解析,获取语法树
// 再调用 `toString()` 方法将语法树转换为字符串形式,以便打印出来
console.log(parser.parse('one 2 "three"').toString());
为了高效存储语法树,它采用的数据格式并不易读,所以并不推荐直接与语法树进行交互,推荐使用 Lezer 所提供的两种对语法树的更高级、更抽象的封装 SyntaxNode 或 TreeCursor,适用于不同的应用场景
SyntaxNode
Syntax Node 对象表示语法树中的一个节点,符合 interface SyntaxNode
Syntax Node 对象是 immutable 不可变的,它作为一个指针,用于表示节点树里特定的一个节点
它具有一些属性以描述该节点的相关信息,它还具有一些方法可以访问该节点的邻近节点
提示
Syntax Node 适合查看特定某个位置的节点
遍历节点更推荐使用 Tree Cursor,特别是需要遍历大量节点时
因为 SyntaxNode 对象是 immutable,遍历时要为每个节点创建一个新的 JavaScript 对象,会消耗很多内存
TreeCursor
Tree Cursor 对象用于遍历整棵树的所有节点,它是一个 class TreeCursor 实例
区别
Tree Cursor 与 JavaScript 原生的迭代器 iterator 不同
JavaScript 迭代器需要调用方法 next 来获取它们的第一个值,而 Tree Cursor 从一开始就指向第一个值(它们始终指向一个节点,没有特殊的初始状态)
因此将 Tree Cursor 放入 for 循环会稍微有些不便,而更适合使用 do/while 循环或带有 if (!cur.next()) break 的循环