Skill Wiki v0.1.0

文档 / reference / dsl

本页目录

.prime DSL 文法

一套小而手写的语法。28 个关键字(每种 kind 一个),14 个 verb 名当字段标识符, 6 类标点。注释用 //

词法结构

  • 关键字 —— 28 种原子 kind,全是保留字。
  • 标识符 —— 原子名走 PascalCase,字段名走 kebab-case
  • 原子 ID —— @scope/kind-kebab-name,允许跨 Prime 引用。
  • 字符串 —— 双引号,\\ 转义 "nt
  • 数字 —— 整数和小数。
  • 布尔 —— truefalse
  • 标点 —— { } [ ] : ,
  • 注释 —— // 一直到行尾。

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。

各种值的字段写法

字段形态例子
stringstatement: "..."
numberconfidence: 0.99
boolverified: true
atom idrequires: [@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,原因有三:

  1. YAML 空白敏感,加上 9 种写字符串的方式,解析报错很脆。
  2. 原子 ID(@scope/name)能独占一类 token —— 拼错时报错更清楚。
  3. 保留 kind 关键字比 YAML 里 kind: rule 加一堆任意字段读起来清晰得多。