@danielx/hera

中文文档
0.9.9发布于 2026/10/14MITTypeScriptCommonJS零依赖构建来源已验证近 30 天下载 2381

小而快的表达式语法

中文使用文档
文档目录19 节
  1. 快速启动
  2. 概览
  3. 定义
  4. 代码块
  5. 演示文稿
  6. 实验
  7. 词汇表
  8. V2 构想
  9. CJS/ESM装载机
  10. --import/--require @danielx/hera/register
  11. --import/--require @danielx/hera/register/tsc
  12. --import/--require @danielx/hera/register/civet
  13. 指定 Hera 编译器选项
  14. 设置类型脚本或 Civet 编译器选项
  15. 新建插件
  16. 编辑器工具
  17. API 密码
  18. compile(grammar, options?)
  19. 选项

贺拉

我唱的是Rhea赤裸的金色的Hera. 永生之后是她,在美丽中超越了一切:她是大声的宙斯的姐妹和妻子,是整个奥林波斯高地所祝福的光荣之人,即使像在雷霆中喜悦的宙斯一样荣耀.

——霍梅克·海姆12到赫拉 (转写:Evelyn-White)(希腊史诗C7到公元前4期)

Build codecov

诸释迦之母.

快速启动

npm install @danielx/hera

将“ a” 数与“ b” 数相接的示例语法 然后返回差数.

# parser.hera
Program
  A:a B:b ->
    return a.length - b.length
A
  "a"*
B
  "b"*

将解析器导入您的 JS/ TS 文件 :

// index.mjs
import { parse } from "./parser.hera"

console.log(parse("aaaa"), parse("bbb"), parse("aabb")) // 4 -3 0

parse("c") // throws error

在命令行上运行 :

node --import '@danielx/hera/register' index.mjs

您语法中的处理器块也可以被写入 类型脚本 或者说 密码 语法. 在这种情况下,使用适当的装载器:

node --import '@danielx/hera/register/tsc' index.mjs
# or
node --import '@danielx/hera/register/civet' index.mjs

使用 Hera 构建插件来捆绑 :

import esbuild from "esbuild"
import heraPlugin from "@danielx/hera/esbuild"

await esbuild.build({
  entryPoints: ['index.mjs'],
  bundle: true,
  outfile: 'out.js',
  plugins: [heraPlugin()],
})

如果您的处理器块使用 TypeScript 或 Civet 语法, 通过 language: "typescript" 或者说 language: "civet" 输入 heraPlugin(...)。 。 。 .

概览

Hera 使用解析表达式语法为程序创建解析器 语言.

赫拉语法以缩入为主,每个规则由一个名字组成, 缩进的选择,名称可以扩展至,以及 用于每个选项的可选再缩进代码块( handler):

RuleName
  Choice1
  Choice2 ->
    ...code...

解析大量使用内置正则表达式能力 Java脚本. 终端要么是字面字符串,要么是正则表达式. 规则由其他规则和终端的选择或顺序组成.

文法中列出的第一条规则是起步点. 每一个选项 规则按顺序检查,然后返回第一次匹配.

定义

规则:一种取名出品. 名称由自己用一行未缩入的行来书写,选择(可能的扩展)则用相通的缩入来书写. 例如:

RuleName
  Choice1
  Choice2

选择按顺序进行尝试,第一个成功者获胜. 注意此属性具有递归性,因此可能涉及回溯. 每种选择都可以是下文定义的任何表达式,同时包括: 可选处理器.

表达式:一个表达式可以是一个序列,选择表达式,或者重复终端,规则名称,或者表达式(重复序列,选择表达式,或者重复). 在混合序列,选择表达式,和重复时,用括号将其分出. 譬如说, Part ( "," Part )* 是一个规则名称的序列和一个终端和一个规则名称的重复,代表一个或多个 Part以逗号分隔.

选择表达式 (单位:千美元)/:一个简短的内置方式来指定两个或多个子选择之间的选择. 譬如说, This / That / Other 匹配 This 或者说 That 或者说 Other,以先成功为准。 这相当于 AnonymousRule 地点

AnonymousRule
  This
  That
  Other

选择表达式返回匹配的( 第1)表达式 .

顺序 (单位:千美元) :一个接一个,由空格分隔. 譬如说, "(" Expr ")" 匹配字符 "(" 接下来是 匹配数 Expr 接下来是字符 ")"。 。 。 . 多个部分的序列返回多个部分的数组. 譬如说, "(" Expr ")" 返回由三个项目组成的数组: 字符串 "(",返回值为 Expr字符串 ")"。 。 。 . 值得注意的是,如果一个表达是仅一个项目的"序列", 它不会被长到1个阵列包裹.

终端字符串 (单位:千美元)"...": 字符串正文(以双引号相绕). 整个字符串必须在准确的位置匹配. 终端字符串匹配时返回匹配的字符串 .

终端正则表达式 (单位:千美元)/.../: 正则表达式,通常被前向鞭打所包围. 由 Just . 或字符类 喜欢 [A-Z][a-z]* 不需要周围的鞭打. 整个正则表达式必须在准确位置匹配 (好像正则表达式开始于 ^ 它被应用到弦的其余部分. 终端正则表达式返回 match 数组: 索引上的匹配字符串 [0],然后是任何匹配的组合 指数 [1], (中文(简体) ), [2],, , , , , , , , . (字符串或 undefined 用于未匹配的可选组. 例如,以下规则通过 $1 然后通过 $1[0]数字 :

Name
  /[A-Za-z][A-Za-z0-9]*/ "=" /\d+/ -> $1[0]

作为一种特殊的情况,如果整个表达式是一个正则表达式, 然后返回值是匹配的字符串而不是匹配数组, 和处理器变量取自匹配数组 : $0 是匹配的字符串(默认返回值), 财务报告和审定财务报表 $1, (中文(简体) ), $2被俘虏的团体 例如:

Name
  # Returns matched string:
  /([A-Za-z])[A-Za-z0-9]*/
  # Returns matched string:
  /([A-Za-z])[A-Za-z0-9]*/ -> $0
  # Returns matched first letter:
  /([A-Za-z])[A-Za-z0-9]*/ -> $1

三斜正则表达式 (单位:千美元)///...///: 白空间不敏感正则表达式,类似于 Civet 格氏语法。 。 。 . 空白空间和 // 身体内部的评论被忽略,如此之大 表达式可以分行:

Identifier
  ///
    [A-Za-z_]  // first character
    [A-Za-z0-9_]*
  ///

三斜正则表达式也支持插入. ${expr} 实值 动态: 生成的剖析器重新评价 expr 当规则运行时,重建 页:1 RegExp 当生成源字符串时,并重用缓存 解析器,直到源代码更改.

Close
  /// ${closingPattern} ///

使用 ${const expr} 用于插值应被捕获一次的插值. 如果每个插入部分都是 const,生成解析器计算 正则表达式一次再使用和普通正则相同的解析器 表达式。 在混合静态/动力表达式中,复杂 const 表达式 被缓存一次,而仅使用标识符 const 表达式是直接发射的.

Open
  /// ${const openingPattern} /// ->
    closingPattern = $0 === "(" ? "\\)" : "\\]"
    return $0

Close
  # Returns matched string:
  /// ${closingPattern} ///

取决于分析状态的动态内插需要与 处理器的突变解析器状态。 如果启用结果缓存, 该状态 必须是缓存密钥/状态的一部分,而规则更改它不应是 已缓存 .

重复 (单位:千美元)*, (中文(简体) ), +: ...* 表示零或以上 ..." ,和 ...+ 表示一次或多次重复 Choice。 。 。 . 重复返回匹配的数组 . 特别是,数组的长度正是匹配的数量.

可选 (单位:千美元)?: ...? 表示零或一次扩张 ..." . 如果 ... 匹配时, ...? 直接返回该值。 否则它成功而不消耗输入和返回 undefined不同 * 财务报告和审定财务报表 +, (中文(简体) ), ? 不将其结果包成数组.

寻找上游 (单位:千美元)&, (中文(简体) ), !: &... 财务报告和审定财务报表 !... 分别声称存在或不存在与 ...,不推进位置或消耗任何投入。 譬如说, &/\s/ 就像正则表情 /(?=\s)/。 。 。 . 两者 & 财务报告和审定财务报表 ! 上游回归 true,这样匹配 vs 在标记为可选时无法区分 ? (例如:. (&Pattern)?) (中文(简体) ).

字符串 (单位:千美元)$: $... 匹配 ... 但返回的只是匹配的输入的字符串,而不是匹配过程中的计算返回值(来自处理器和序列和重复的数组). 譬如说, $/\d+/ 返回比对数字的字符串,而不是匹配数组,当表达式不仅仅是一个正则表达式时,该数组是有用的.

返回类型: 选择的返回类型(或更确切地说,其处理者) 可明确使用 ::type 选择之后和之前 处理器( 如果有—— 否则它返回默认值) . 此返回类型在生成 TypeScript 或 Civet 输出时会被释放 . 您也可以写 RuleName ::type 在规则标题上使用该类型作为 默认规则中的每个选项.

处理器:从匹配的选择到语言原始的映射. 处理器附加到规则选择上 -> 选择之后. 最普通的处理器是 JavaScript, TypeScript, 或者 Civet 代码缩进 在选择之下 returns 匹配选择的理想值. 或者,单一表达式可以在与 ->并会隐含 return编. 处理器代码可以指代默认值 (终端字符串的字符串,序列或重复的数组)通过 $0, (中文(简体) ), 如果不提供处理器,选择会得到回报. 这个 n最顶端序列中的 sth 匹配项目可以通过 $n· ; 最高序列中的每个项目也可以通过一个 :name 后缀 (例如, Block:name),然后代码也可以称为 name。 。 。 . 作为一种特殊的情况,如果扩张是单一的正则表达, $0 指匹配的字符串(而不是匹配数组)和 $n 提及 n(原始内容存档于2018-03-21). th group in the regex. 处理器代码可以返回特殊值 $skip 以显示失败的匹配.

注释 (单位:千美元)#...: 处理器之外,线路从 # (在可能缩进之后)作为评论处理. 内部处理器,使用处理器语言的评论,例如,, // 或者说 /*...*/。 。 。 .

代码块

您可以使用三个回击创建直接插入的代码块 输入编译文件,使用与处理器相同的语言. 这对于创建公用功能或增加出口都是有益的.

```
function toInt(n) {
  return parseInt(n)
}
```

Number
  [0-9]+ ->
    return toInt($0)

演示文稿

如果这些演示不能交互, 请查看此页面 https://danielx.net/hera/docs/README.html (中文(简体) )


URL 解析器 https://tools.itf.org/html/rfc3986 (中文(简体) )

#! hera url

数学实例.

#! hera math

赫拉是自我生成的:

#! hera hera

脚本位置示例

#! hera
Grammar
  Punctuation? A+ Punctuation? ->
    return [$1, ...$2, $3].filter((token) => token !== undefined)

A
  ("a" / "A") ->
    return {type: "A", loc: $loc, value: $1}

Punctuation
  "!" / "." / "?" ->
    return {type: "Punctuation", loc: $loc, value: $1}

Regex 组

#! hera
Phone
  /1-(\d{3})-(\d{3})-(\d{4})/ -> [$1, $2, $3]

#! hera
Grammar
  NamedMapping NamedMapping

NamedMapping
  Punctuation -> ["P", $0]

Punctuation
  "."

实验

编译解析器到 TypeScript .

词汇表

EOS - 发言结束

EOF - 文件/输入结束

V2 构想

从匹配序列的一部分输出字符串的简单方式 。 也许添加 护理/选择前缀操作员.

优化选项、顺序和regexes(合并)的重复 减少调用.

平面图和其他平面图.

为处理者命名参数 .

减少常见子序列的回溯:

RuleBody
  Indent Sequence EOS (Indent ^Sequence EOS)+ -> ["/", [2, 4...]]
  Indent Sequence EOS -> 2

上述规则应该能够高效(不需要回溯) 因为它有一个共同的子序列 它应该 能够重新使用已经完成的工作.

一种选择是把它变成一条带可选部分的规则,并添加 逻辑进入处理器, 但似乎粗糙.


#! setup
require("./interactive")(register)

CJS/ESM装载机

实现直接 import 或者说 require 联 合 国 .hera 文档, 在操作语言中使用适当的加载器:

--import/--require @danielx/hera/register

装入编译到 JavaScript 的.hera 文件 .

--import/--require @danielx/hera/register/tsc

装入编译到 TypeScript 的.hera 文件.

试图装入 typescript npm 模块将生成的 TypeScript 转换为 JavaScript .

--import/--require @danielx/hera/register/civet

装入编译到 Civet 的.hera 文件 .

试图装入 @danielx/civet npm 模块将生成的 Civet 转换为 JavaScript .

指定 Hera 编译器选项

见 loader-examples/hera-custom 用于将选项传递到赫拉编译器的示例.

支持的 Hera 编译器选项在 选项。 。 。 .

无害环境管理

而不是使用 --import @danielx/hera/register,登记 @danielx/hera/register/esm 钩并传递编译器选项.

举个例子.

// loader.js
const heraOptions = { ... }
register("@danielx/hera/register/esm", pathToFileURL(__filename), { data: heraOptions })
node --import ./loader.js my-script.mjs

司法理事会

而不是使用 --require @danielx/hera/register,要求和设置选项 @danielx/hera/register/cjs 模块.

举个例子.

require("@danielx/hera/register/cjs").options.hera = { inlineMap: false }

const { parse } = require("./my-typed-grammar.hera")

见 loader-examples/hera-custom/register.js 例如,同时登记无害环境管理和CJS两种选择.

设置类型脚本或 Civet 编译器选项

见 loader-examples/tsc-custom 或者说 loader-examples/civet-custom 用于将选项传递到 TypeScript 或 Civet 编译器.

无害环境管理

而不是使用 --import @danielx/hera/register/tsc 或者说 --import @danielx/hera/register/civet,登记 register/esm 财务报告和审定财务报表 register/tsc/esm 或者说 register/civet/esm 模块并传递您想要的选项. (注意您还需要注册基地) register/esm 模块,因为无害环境管理装载器连锁在一起。 )

举个例子.

// custom-loader.js
const { register } = require("node:module")
const { pathToFileURL } = require("node:url")

register("@danielx/hera/register/esm", pathToFileURL(__filename), {
  data: heraOptions
})

register("@danielx/hera/register/tsc/esm", pathToFileURL(__filename), {
  data: tscCompilerOptions,
})
// OR
register("@danielx/hera/register/civet/esm", pathToFileURL(__filename), {
  data: civetCompilerOptions,
})
node --import ./custom-loader.js ./my-script.mjs

司法理事会

而不是使用 --require @danielx/hera/register/tsc 或者说 --require @danielx/hera/register/civet,要求和设置选项 @danielx/hera/register/tsc/cjs 或者说 @danielx/hera/register/civet/cjs 模块.

举个例子.

const loader = require("@danielx/hera/register/tsc/cjs")
loader.options.hera = heraOptions
loader.options.tsc = tscCompilerOptions

const { parse } = require("./typed-grammar.hera")
const loader = require("@danielx/hera/register/civet/cjs")
loader.options.hera = heraOptions
loader.options.civet = civetCompilerOptions

const { parse } = require("./civet-grammar.hera")

见 loader-examples/tsc-custom/register.js 财务报告和审定财务报表 loader-examples/civet-custom/register.js 以实例说明同时登记无害环境管理和CJS的选项.

新建插件

使用 heraPlugin() 要导入 .hera 正在构建的文件.

如果处理器机构或代码块使用 TypeScript 或 Civet, 请设置插件 明确语言:

heraPlugin({ language: "typescript" })
heraPlugin({ language: "civet" })

插件自动选择合适的 esbuild 加载器, 虽然你可以用 loader 选项.

编辑器工具

VS 代码扩展和语言服务器支持 hera.language 用于控制 如何解释处理者的尸体.

在 VS 代码设置中 :

{
  "hera.language": "civet"
}

在你的工作空间 package.json数字 :

{
  "hera": {
    "language": "civet"
  }
}

见 lsp/README.md。 。 。 .

API 密码

无害环境管理:

import { compile } from "@danielx/hera"

CJS: 贾克:

const { compile } = require("@danielx/hera")

compile(grammar, options?)

将一个赫拉语法编译为解析源代码.

  • 以原始语法源为字符串通过.
  • 默认返回代码字符串 .
  • 回返 { code, sourceMap } 何时 options.sourceMap 实值 true。 。 。 .

选项

compile() 接受这些选项:

  • language?: "javascript" | "typescript" | "civet": 处理器体和代码块所使用的语言. 默认 : "javascript"。 。 。 .
  • types?: boolean: 生成 TypeScript-flavored 剖析器输出. 默认 : false 何时 language 未说明或 "javascript",以及 true 何时 language 实值 "typescript" 或者说 "civet"。 。 。 .
  • module?: boolean: 消除无害环境管理,而不是CJS产出。 默认 : false。 。 。 .
  • filename?: string: 生成源地图中使用的文件名. 默认 : "anonymous"。 。 。 .
  • source?: string:原始语法源文本. 需要时间 inlineMap 或者说 sourceMap 已启用.
  • inlineMap?: boolean: 在生成的输出中添加内置源代码注释。 默认 : false。 。 。 .
  • sourceMap?: boolean编号: 返回 { code, sourceMap } 而不是代码串。 默认 : false。 。 。 .
  • libPath?: string: 导入生成解析器所使用的 Hera 运行时库的路径 。 默认 : "@danielx/hera/lib"。 。 。 .

版本与发布记录

@danielx/hera 共发布 48 个版本,首次发布于 2022/03/09;过去 12 个月发布了 14 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.9.9latest2026/10/1428 天前
0.9.82026/05/275 个月前
0.9.72026/05/225 个月前
0.9.62026/05/016 个月前
0.9.52026/04/296 个月前
0.9.42026/04/276 个月前

其他发布通道:pre → 0.8.19-pre.1。

关于 @danielx/hera 的常见问题

@danielx/hera 是什么?

小而快的表达式语法

如何安装 @danielx/hera?

在项目目录运行 npm install @danielx/hera,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 hera,可以用 npx hera 直接运行。

@danielx/hera 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@danielx/hera 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@danielx/hera 可以商用吗?

@danielx/hera 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@danielx/hera 的下载量有多少?

根据 npm 官方下载统计,@danielx/hera 在 2026/10/12 – 2026/11/10 这 30 天内被下载 2,381 次,日均约 79 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@danielx/hera 还在维护吗?

最新版本 0.9.9 发布于 2026/10/14(28 天前);至今共发布 48 个版本,其中过去 12 个月发布了 14 个;首次发布于 2022/03/09。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。