Mini YAML Parser¶
从 0 行(CC 实际用第三方库
yaml)提炼到 ~150 行的 缩进敏感 递归下降 parser。 支持 mapping / sequence / scalar(string / number / bool / null)+ 注释 + 引号。
文件¶
mini-yaml-parser/
├── src/
│ ├── types.ts 解析器(~110 行,单文件含 preprocess + parseBlock + parseMapping + parseSequence + parseScalar)
│ └── cli.ts CLI(~30 行,支持 stdin / file / --example)
└── README.md
跑¶
npm install && npm start -- --example
# 或
echo "key: value" | npm start
# 或
npm start -- examples/config.yaml
支持的语法¶
# 注释
name: cc-claude-code # string
version: 1.0.0 # number
enabled: true # bool
maxRetries: 3 # integer
ratio: 1.5 # float
missing: null # null / ~ / ""
# 引号字符串
title: "Hello, World"
single: 'no escape needed'
# 嵌套 mapping
server:
host: localhost
port: 8080
tls: true
# sequence
features:
- streaming
- tool-use
- mcp
# 复杂嵌套
env:
PATH: /usr/local/bin
DEBUG: null
不支持(vs 真实 YAML 1.2 规范)¶
- ❌ 多行 block scalar(
|>) - ❌ flow style(
{a: 1, b: 2}/[1, 2, 3]) - ❌ 锚点 & 引用(
&anchor/*ref) - ❌ 标签(
!!str/!!int) - ❌ Tab 缩进(只支持空格)
- ❌ 混合 key 类型(
{a: 1, 2: b}) - ❌ 日期 / 时间类型
- ❌ 多文档(
---分隔)
核心 4 件套¶
1️⃣ preprocess:source → Line[]¶
- 按
\n切行 - 算 indent(开头的空格数)
- 去掉注释(注意引号内
#不算) - 过滤空行
2️⃣ parseBlock = dispatch by first char¶
-开头 → parseSequencekey:开头 → parseMapping
3️⃣ 缩进 = 递归边界¶
parseBlock(lines, i, baseIndent) 解析 indent ≥ baseIndent 的所有行。indent 减小就 return。这天然支持任意深度嵌套。
4️⃣ parseScalar 6 路¶
"abc" | 'abc' → string (剥引号)
null | ~ | "" → null
true | True → boolean
123 → integer
1.5 → float
其他 → string
真实代码对照¶
CC 实际用 yaml 库(外部依赖)。本 demo 是教学用自实现,理解原理后可换回官方库。
| Demo | 真实 yaml 库 | 简化 |
|---|---|---|
| preprocess | yaml/lib/lexer (~500 行) |
30 行 |
| parseBlock | yaml/lib/parser (~2000 行) |
80 行 |
| parseScalar | yaml/lib/schema (~500 行) |
10 行 |
进阶练习¶
- 加 flow style:
{a: 1, b: 2}/[1, 2, 3] - 加 block scalar:
\|保留换行 />折叠换行 - 加锚点引用:
&anchor/*ref实现递归数据 - 加错误恢复:解析失败给 line:col 定位
- 加 JSON 兼容输出:自动把 key 转为 JSON 兼容(不加引号)
- 加 type tag:
!!int "42"强制转换
相关阅读¶
- topics/structured-diff-perf-archaeology.md —— YAML/JSON 性能对比
- docs/ENV_VARS.md —— CC 实际用 YAML 配 env
- YAML 1.2 规范
- mini-bash-parser/ —— 另一个递归下降 parser 范例