本页目录
.prime DSL 文法
一套小而手写的语法。28 个关键字(每种 kind 一个),14 个 verb 名当字段标识符,
6 类标点。注释用 //。
词法结构
- 关键字 —— 28 种原子 kind,全是保留字。
- 标识符 —— 原子名走
PascalCase,字段名走kebab-case。 - 原子 ID ——
@scope/kind-kebab-name,允许跨 Prime 引用。 - 字符串 —— 双引号,
\\转义"、n、t。 - 数字 —— 整数和小数。
- 布尔 ——
true、false。 - 标点 ——
{}[]:, - 注释 ——
//一直到行尾。
BNF(草图)
prime-file ::= atom-decl*
atom-decl ::= kind-keyword name "{" field* "}"
kind-keyword ::= "fact" | "term" | "rule" | "method" | ... (28 kinds)
name ::= [A-Z][A-Za-z0-9]*
field ::= field-name ":" value
field-name ::= [a-z][a-z0-9-]* // kebab-case
value ::= string | number | bool
| atom-id
| list
| object
string ::= '"' (escaped-char | non-quote)* '"'
number ::= integer | decimal
bool ::= "true" | "false"
atom-id ::= "@" scope "/" name-kebab
scope ::= [a-z][a-z0-9-]*
name-kebab ::= [a-z][a-z0-9-]*
list ::= "[" (value ("," value)* ","?)? "]"
object ::= "{" (field ("," field)* ","?)? "}" 结尾逗号
list 和 object 都允许。parser 会接受 [a, b, c,],
所以调换边列表的顺序时不会污染 diff。
各种值的字段写法
| 字段形态 | 例子 |
|---|---|
| string | statement: "..." |
| number | confidence: 0.99 |
| bool | verified: true |
| atom id | requires: [@my/term-x] |
| 字符串列表 | tags: ["fintech", "button"] |
| 对象列表 | steps: [{ action: "..." }] |
| 嵌套对象 | contract: { must-include: [...] } |
边字段
14 个 verb 都能直接当字段名。值永远是一组 atom ID。
requires: [@my/term-x, @my/term-y]
validates-with: [@my/source-rfc-1234]
contradicts: [@my/anti-pattern-y]
see-also: [@my/pattern-z]
边界情况
- 重复字段 —— 后写的覆盖前面,L1 给一个 warning。
- 空列表 —— 等同不写这个字段。
- 空对象 —— 对 kind 必填字段来说不合法。
- 自引用 —— 一个原子在
requires 里写自己,L3 当成环。
为什么用 DSL
YAML 或 JSON 也能行。最后选了一个薄 DSL,原因有三:
- YAML 空白敏感,加上 9 种写字符串的方式,解析报错很脆。
- 原子 ID(
@scope/name)能独占一类 token —— 拼错时报错更清楚。 - 保留 kind 关键字比 YAML 里
kind: rule 加一堆任意字段读起来清晰得多。