#3927·prism

[v2] 语言组合 / 扩展 / 嵌入 / …

作者: LeaVerou创建于 2025年5月5日更新于 2026年9月13日

我一直在思考如何最好地处理依赖或利用其他语言的语言定义。早期的想法包括:

[!NOTE] 这是一个正在进行中的工作,我会根据对这个问题的更多思考来更新它。 但在进入细节之前,有一个图示(来自 VS Code 的我们代码的真实截图): Image 这是 4 种语言相互嵌套!

  1. 外部语言是 JS(好吧, TS)
  2. JSDoc 在 JS 文档注释中
  3. Markdown 在 JSDoc 中
  4. JS 在 Markdown 代码块中 目前有两种类型的依赖:
  5. 必要(实际 ESM 导入)
  6. 可选(如果其他东西导入了它们,否则不使用) 还有几种使用案例如下所述。 _注意: 任何提及"现在"的内容都指的是 simplify 分支(草案 PR),而不是当前的 v2 分支。

1. 语言使用另一种语言作为基础(例如 JavaScript 使用 C-like)

这是最直观的情况:只是简单的继承。

  • 基础语言现在通过 base 键而不是强制性的 extend() 调用来声明(我想 parentextends 可能是更好的名称),并且被视为必需的依赖。
  • 它被作为普通的 ESM 导入导入
  • 其语法通过 base 键同步解析传递给语言的 grammar() 函数。默认情况下,子语言定义中的任何标记会覆盖基础语言中的标记。如果需要不同的行为,则有以下逃逸途径:
    • $merge 进行某些标记的深度合并
    • $insertBefore 在另一个之前插入某些标记
    • $insertAfter 在另一个之后插入某些标记
    • $insert$insertBefore/$insertAfter 的简写版本,更适合一次性插入,因为位置通过 $before/$after 在其值内指定
    • 上述所有操作都合并为一个单一补丁,并在尽可能晚的时间应用
    • 我仍在争论这是否是一个好主意。 通常情况下,基础语言本身是有用的。例如,clike 并不是仅仅为了使其子语言更加 DRY 而创建的,而是为了在需要突出 C-like 语言时作为一种退路,而这种语言没有专门的语言定义(尽管在 Prism 首次推出时只有 5 种语言时,这种情况更为重要)。 如今,也存在一些语言定义仅仅是为了使其他语言定义更加 DRY 的原因而存在(例如 javadoclike)。