slime-parser
v0.2.87
Published
Slime 的 CST 解析器和 CST→AST 转换器。
Readme
slime-parser
Slime 的 CST 解析器和 CST→AST 转换器。
安装
npm install slime-parser使用
import { SlimeParser, SlimeCstToAstUtil } from 'slime-parser'
// 1. 将代码解析为 CST
const parser = new SlimeParser(code)
const cst = parser.Program()
// 2. 将 CST 转换为 AST
const ast = SlimeCstToAstUtils.toProgram(cst)扩展 CST→AST 转换
slime-parser 提供全局注册模式,允许子项目扩展 CST → AST 转换逻辑。
为什么需要全局注册
slime-parser 内部各转换器通过 SlimeCstToAstUtils.xxx() 调用。直接继承重写方法不会生效,因为内部调用不经过子类。
全局注册后,所有调用都会路由到注册的子类实例。
架构设计:继承链自动注册
核心机制
- Proxy 代理模式:默认导出的
SlimeCstToAstUtils是一个 Proxy,动态代理到全局注册的实例 - 构造函数自动注册:
SlimeCstToAst构造函数自动调用registerSlimeCstToAstUtil(this) - 继承链传递:子类调用
super()时,this是子类实例,自动注册为子类
工作原理
// slime-parser/src/SlimeCstToAstUtils.ts
let _SlimeCstToAstUtils: SlimeCstToAst
export function registerSlimeCstToAstUtil(instance: SlimeCstToAst) {
_SlimeCstToAstUtils = instance
}
export class SlimeCstToAst {
constructor() {
registerSlimeCstToAstUtil(this) // this 是最终的子类实例
}
}
// Proxy: 动态代理到当前注册的实例
export const SlimeCstToAstUtils = new Proxy({} as SlimeCstToAst, {
get(_, prop) {
const val = (_SlimeCstToAstUtils as any)[prop]
return typeof val === 'function' ? val.bind(_SlimeCstToAstUtils) : val
}
})
// 初始化默认实例
new SlimeCstToAst()使用方法
基础用法(单层继承)
import { SlimeCstToAst, registerSlimeCstToAstUtil } from 'slime-parser'
class MyExtendedCstToAst extends SlimeCstToAst {
constructor() {
super() // 父类构造会自动注册 this(MyExtendedCstToAst 实例)
// 可选:注册到自己的全局变量
registerMyExtendedCstToAst(this)
}
// 重写方法,处理自定义语法
createPrimaryExpressionAst(cst) {
const first = cst.children?.[0]
if (first?.name === 'CustomExpression') {
return this.handleCustomExpression(first)
}
return super.createPrimaryExpressionAst(cst)
}
}
// 创建实例时自动注册到所有层
const converter = new MyExtendedCstToAst()
const ast = converter.toProgram(cst)多层继承(继承链)
// 第二层:cssts-compiler
class CssTsCstToAst extends SlimeCstToAst {
constructor() {
super() // SlimeCstToAst 构造已注册 this
registerCssTsCstToAst(this) // 只注册到本层
}
}
// 第三层:ovs-compiler
class OvsCstToSlimeAst extends CssTsCstToAst {
constructor() {
super() // 继承链自动注册到 cssts 和 slime 层
registerOvsCstToSlimeAst(this) // 只注册到本层
}
}
// 实例化时的注册流程:
// new OvsCstToSlimeAst()
// → OvsCstToSlimeAst.constructor()
// → super() → CssTsCstToAst.constructor()
// → super() → SlimeCstToAst.constructor()
// → registerSlimeCstToAstUtil(this) // this = OvsCstToSlimeAst 实例 ✅
// → registerCssTsCstToAst(this) // this = OvsCstToSlimeAst 实例 ✅
// → registerOvsCstToSlimeAst(this) // this = OvsCstToSlimeAst 实例 ✅
// 结果:三层全局变量都指向同一个 OvsCstToSlimeAst 实例注意事项
⚠️ 避免循环引用:全局变量必须先声明再初始化
// ❌ 错误:循环引用
let _util: SlimeCstToAst = new SlimeCstToAst() // 构造函数会访问 _util
// ✅ 正确:分两步
let _util: SlimeCstToAst // 先声明
export function registerSlimeCstToAstUtil(instance: SlimeCstToAst) {
_util = instance
}
// ... Proxy 定义 ...
new SlimeCstToAst() // 再初始化已使用此机制的项目
| 项目 | 扩展类 | 继承自 | 用途 |
|------|--------|--------|------|
| slime-parser | SlimeCstToAst | - | 基础 JavaScript/TypeScript 语法 |
| cssts-compiler | CssTsCstToAst | SlimeCstToAst | 处理 css { } 表达式 |
| ovs-compiler | OvsCstToSlimeAst | CssTsCstToAst | 处理 OVS DSL 语法(继承 CSSTS) |
许可证
MIT License - 详见 LICENSE 文件。
