# Parser
> **职责**:把某个 dialect 的字节流解析成保真的 raw 模型,一次性固化后层恢复会依赖的所有协议事实。
>
> **不负责**:lowering 语义、CFG 切块、任何推断。
>
> **例子**:`bytes(lua54)` → `parse_lua54_chunk` → `RawChunk{ header, protos: [RawProto{...}] }`
## 入口
```
src/parser/mod.rs
parse_chunk(bytes, options) -- 自动探测版本,按版本字节分派
parse_lua51_chunk / ...lua55 / luajit / luau -- 强制 dialect 入口
```
## 模块布局
```
src/parser/
mod.rs 入口 + 版本分派
raw.rs 统一 raw 模型 + accessor(后层消费这里,不直接碰 dialect 内部)
reader.rs BinaryReader:varint / endian / 字节级读取
options.rs ParseOptions(ParseMode / StringEncoding / StringDecodeMode)
error.rs ParseError
dialect/
opcodes.rs define_opcode_enum! / define_opcode_kind_table! 宏
puc_lua/
header.rs PUC-Lua chunk header 解析
layout.rs 字段顺序布局
instruction.rs 指令编解码
proto.rs proto 读取骨架
sections.rs debug section 驱动
strings.rs 字符串读取
macros.rs define_puc_lua_opcodes! / define_puc_lua_instruction_codec!
lua51/ ... lua55/ 各版本:mod.rs / parser.rs / raw.rs / debug.rs
luajit/ 同上
luau/ 同上
debug.rs dump_parser(委托到各 dialect debug.rs)
```
## 数据流
```
bytes
└─ parse_chunk(或 parse_lua54_chunk 等)
└─ Lua54Parser::parse(bytes) -- dialect/lua54/parser.rs
├─ BinaryReader -- reader.rs
├─ puc_lua::read_header -- puc_lua/header.rs
├─ puc_lua::read_proto -- puc_lua/proto.rs
└─ RawChunk { header, main proto tree }
└─ RawProto { instrs, consts, upvalues, children, debug_info, extra }
```
## 应优先复用的共享设施
| `BinaryReader` | 所有字节级读取,含 `read_varint_u32_lua54` / `read_u32_le` 等 |
| `define_puc_lua_opcodes!` | 声明 opcode enum + label table,避免手写大段 match |
| `define_puc_lua_instruction_codec!` | operand 编解码共享骨架 |
| `puc_lua/proto.rs` | PUC-Lua 家族 proto 读取骨架,lua52~55 不应各自复制 |
| `raw.rs` accessor | 后层消费协议事实的正式入口 |
## 维护规范
1. **协议事实必须在 parser/raw 收口**:来源于字节编码(而非运行语义)的事实必须在此固化。
- 典型:`EXTRAARG` 与前一条指令的绑定、Luau closure const 到 child proto slot 映射、Lua 5.5 字符串复用展开。
- 边界:`local <const>` 不是 parser 能从 chunk 读出的——只有 `local <close>` 依赖运行时语义线索。
2. **parser.rs 只负责按协议顺序读取**:opcode label 大表、operand decode 大表应放到 opcode 宏或共享设施。
3. **raw.rs 只保存稳定事实**:只有后层实际消费的 typed extra 和 accessor,不保存单次读取的临时中间态。
4. **dialect debug.rs 只展示本 dialect 产物**:不做跨 dialect 判断,不重新校验 parser 已保证的版本约束。
5. **错误在 parser 边界暴露**:协议不合法优先报 `ParseError`,不拖到 transformer 再暴露。
## 向后提供的事实
`RawChunk` / `ChunkHeader` / `RawProto` / `RawInstr` / `RawConstPool` / `RawUpvalueInfo` / `RawDebugInfo` / `RawString` / 各 dialect raw extra。
## 排错指引
| 指令数量 / 常量数量解析错误 | `puc_lua/sections.rs` 长度字段读取 |
| opcode 识别失败 | `dialect/opcodes.rs` 宏展开是否漏了某个 opcode |
| extra-word 绑定错位 | `parser.rs` EXTRAARG 绑定逻辑 |
| raw accessor 返回 None | `raw.rs` extra 类型是否与 dialect 版本匹配 |
| 想看 raw 结构 | `unluac --dialect lua54 --debug --target-stage parse <file>` |