Add Endor source reader before lexing with provenance and URI provider
Verify databases and deploy Aster VM / verify-and-deploy (push) Successful in 6m53s
Verify databases and deploy Aster VM / verify-and-deploy (push) Successful in 6m53s
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
| --- | --- |
|
||||
| [对象模型](objects.md) | EndorObject/ObjectHeader、代际句柄、操作协议、托管引用与循环回收 |
|
||||
| [基本对象与 Number](builtins.md) | 函数、原生函数、字典、Cell、异常数据、字符串与无损数字 |
|
||||
| [Endor 阅读器](reader.md) | SourceUnit、来源/修订标签、字符串/流/文件和宿主 URI provider |
|
||||
| [源码前端](frontend.md) | 手写 lexer、token PEG parser、AST、基础函数/表达式语法与诊断 |
|
||||
| [字节码 VM](bytecode.md) | 指令编码、代码校验、局部槽、执行帧、函数创建、调用/返回与边界 |
|
||||
| [文本编码](text-encoding.md) | UTF-8、日文、外部 Shift_JIS/CP932 与宿主解码边界 |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 源码词法与 PEG 语法前端
|
||||
|
||||
frontend 包提供手写 Rust lexer 和 rust-peg 生成的 token parser。当前入口为 lex、parse、parse_expression,CLI 提供 parse 文件命令;结果是 AST,还没有 AST 到字节码的编译器、类型检查、名称解析或源码执行。Core 不依赖 frontend 或 peg,仍保持零外部依赖。
|
||||
frontend 包提供 [Endor 阅读器](reader.md)、手写 Rust lexer 和 rust-peg 生成的 token parser。宿主通过 SourceUnit 调用带来源的词法/语法入口,原有 lex、parse、parse_expression 保留;CLI 提供 parse 文件/stdin 命令;结果是 AST,还没有 AST 到字节码的编译器、类型检查、名称解析或源码执行。Core 不依赖 frontend 或 peg,仍保持零外部依赖。
|
||||
|
||||
首版以 Endorphin-Language 设计稿的基础词法、表达式与函数章节为起点,语法可以继续修改;设计稿中的未完成部分不作为阻塞前端实现的前置条件,也不被整体视作已经实现的语言能力。这里维护当前解析契约;源码位置见 [frontend](../../crates/frontend/README.md)。
|
||||
|
||||
@@ -14,6 +14,9 @@ grammar.peg 保留 rust-peg 0.8 的 peg::parser! 外层声明,因此是直接
|
||||
|
||||
| API | 输入与结果 |
|
||||
| --- | --- |
|
||||
| lex_source(&SourceUnit) | 对阅读器输出分词,错误携带来源、修订及行列 |
|
||||
| parse_source(&SourceUnit) | 对阅读器输出解析基础函数 Program,错误携带来源信息 |
|
||||
| parse_source_expression(&SourceUnit) | 对阅读器输出解析一个完整表达式,错误携带来源信息 |
|
||||
| lex(&str) | 产生 Vec<Token>;每个 token 只有种类和原始源码的字节范围,不复制文本 |
|
||||
| parse(&str) | 解析一个或多个完整函数定义,返回 Program;空输入和未消费的尾部内容报错 |
|
||||
| parse_expression(&str) | 解析一个完整表达式,不能忽略尾部 token |
|
||||
@@ -24,7 +27,7 @@ AST 的名称、数字原文和解码后的字符串均由 AST 自己持有,
|
||||
|
||||
## 词法规则
|
||||
|
||||
- 输入是有效 UTF-8 的 &str。CLI 使用严格的 read_to_string 读文件;其他编码由宿主先显式解码,不修改全局 locale。
|
||||
- lexer 输入是有效 UTF-8 的 &str。阅读器将字符串、流、文件或宿主 URI provider 的结果转换为不可变 SourceUnit;CLI 通过阅读器严格解码字节。其他编码由宿主先显式解码,不修改全局 locale。
|
||||
- 名称首字符为下划线或 Rust char::is_alphabetic,后续为下划线或 char::is_alphanumeric。这是当前明确采用的分类,不承诺 XID/NFKC 规则;没有自动规范化。中文、日文可用于名称,emoji 可以用于字符串。
|
||||
- 名称统一产生 Name token。function、let、return 只在相应语法位置按拼写识别,不预先固定全局保留字表;class、agent 等也仍可作为名称。
|
||||
- 数字为 ASCII 十进制数字,可带两边都有数字的小数部分;原文保留,不转换为 f64。负号单独分词;科学计数法、数字后缀、下划线分隔、前导正号、.5 和 1. 形式不在当前表达式语法中。
|
||||
@@ -59,6 +62,6 @@ use、namespace、class、agent、完整类型语法、条件/循环、比较
|
||||
|
||||
词法和语法错误分别标记为 Lexical/Syntax。语法错误将 PEG 的 token 下标转换成原始源码 Span,保留期望项目列表;EOF 错误使用 source.len() 处的空区间。Diagnostic::location 返回一基行列,列按 Unicode 标量计数,CRLF 只算一次换行,不按字节列或字形簇计数。
|
||||
|
||||
`cli parse <file>` 成功时输出 Rust Debug 格式的 AST,失败时在 stderr 输出文件/行/列和诊断并返回非零退出码。AST Debug 文本不是稳定的序列化协议。命令不执行源码、不初始化 VM、不连接数据库;具体运行与本地禁测约定见 [运行](../operations/README.md) 和 [验证](../operations/validation.md)。
|
||||
`cli parse <file>` 与 `cli parse -` 成功时输出 Rust Debug 格式的 AST,失败时在 stderr 输出来源/行/列和诊断并返回非零退出码;`-` 表示从 stdin 读到 EOF,不是 REPL。阅读与来源包装规则见 [阅读器](reader.md)。AST Debug 文本不是稳定的序列化协议。命令不执行源码、不初始化 VM、不连接数据库;具体运行与本地禁测约定见 [运行](../operations/README.md) 和 [验证](../operations/validation.md)。
|
||||
|
||||
后续编译器应将 AST 经名称/闭包分析转换为现有字节码,不另设 AST 求值器;解析成功不表示表达式已有运行语义。VM 虽已支持 MakeFunction,但从源码创建函数仍需要编译器接入。解析器也不是不可信代码沙箱,当前没有通用输入大小或解析递归深度限额。
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# Endor 阅读器与源码来源
|
||||
|
||||
EndorReader 位于 lexer 之前,把宿主输入转换为 SourceUnit,再交给 lex_source、parse_source 或 parse_source_expression。它负责读取、严格 UTF-8 解码和来源记录,不解析 token、不解析 namespace 依赖、不执行代码。源码在 [reader.rs](../../crates/frontend/src/reader.rs),来源与诊断结构在 [source.rs](../../crates/frontend/src/source.rs),词法和语法见 [前端](frontend.md)。
|
||||
|
||||
```text
|
||||
字符串/字节流/文件/宿主 URI provider
|
||||
→ EndorReader → SourceUnit → lexer → PEG parser → AST
|
||||
```
|
||||
|
||||
## 输入适配
|
||||
|
||||
| 入口 | 行为 |
|
||||
| --- | --- |
|
||||
| EndorReader::from_text(name, text) | 接收已经解码的 Unicode 字符串,复制或接管其 String 所有权,记录文本来源名称 |
|
||||
| EndorReader::from_stream(name, reader) | 接收实现 std::io::Read 的流,读到 EOF 后统一严格解码,记录流名称 |
|
||||
| EndorReader::from_file(path) | 按原生 Path 打开文件,读到 EOF 并严格解码,保留 PathBuf 来源 |
|
||||
| EndorReader::from_endor(uri, provider) | 调用宿主 EndorSourceProvider 取得一次解析结果,严格解码并保存请求 URI 与已选修订标签 |
|
||||
|
||||
Reader 不修改 locale,不猜测 Shift_JIS/CP932 或其他编码,不以替换字符修复非法 UTF-8。其他编码由宿主先明确解码后通过字符串或 UTF-8 输入交付。流可以在任意字节处分块,包括拆开一个 Unicode 字符;所有字节收齐后才进行 UTF-8 校验。
|
||||
|
||||
文本原样保留:不转换 CRLF/CR,不移除 BOM,也不规范化 Unicode。Span 继续指向这份原始 UTF-8 文本;Reader 不提前处理注释、转义或缩进。BOM 等字符是否构成合法语法由 lexer 决定,当前 lexer 不接受开头 BOM。
|
||||
|
||||
SourceUnit 拥有源码和 SourceOrigin,只公开只读访问,不依赖仍打开的文件、流或平台连接。一次读取完成后,重新读取同一 URI 或修改源文件不会改写已有单元的内容;这保证输入缓冲区固定,不表示对可变文件读取过程实现了文件系统事务快照。
|
||||
|
||||
## 来源与诊断
|
||||
|
||||
SourceOrigin 区分 Text、Stream、File 和 Endor。文本/流名称由宿主指定,例如 `<editor>`、`<stdin>` 或会话输入编号;文件保留操作系统路径;Endor 来源额外记录 provider 给出的修订标签。
|
||||
|
||||
lex_source、parse_source 和 parse_source_expression 将原有 Diagnostic 包装为 SourceDiagnostic,保存来源、行列和完整诊断(包括 Span 与 expected 列表)。行列根据读取到的原文计算,使用一基 Unicode 标量列,CRLF 算一次换行。包装后的错误可以在源码缓冲区释放后继续报告;错误不会保存整份源码文本。
|
||||
|
||||
Read 阶段的 SourceReadError 与词法/语法 Diagnostic 分开:Io 保留原始 I/O/provider 错误,InvalidUtf8 报告第一个无效字节位置,InvalidEndorUri 表示入口不属于可接受的 Endor URI,MissingRevision 表示宿主没有提供已选修订。读取中途失败不返回部分源码,不继续解析部分内容;URI 失败不会改从本地文件读取。I/O 和 UTF-8 的底层错误可通过 Error::source 取得。
|
||||
|
||||
原有 lex(&str)、parse(&str)、parse_expression(&str) 保留为不带来源的低层便捷接口。需要文件名、URI、修订或会话标签时,宿主应使用 SourceUnit 入口;这些标签不是 VM 的 ObjectRef,也不充当持久资源身份。
|
||||
|
||||
## 平台 URI 边界
|
||||
|
||||
EndorSourceProvider::load(&str) 返回 io::Result<ResolvedEndorSource>。ResolvedEndorSource 包含 bytes 和非空 revision;宿主负责名称解析、权限检查、版本选择与实际存储访问,失败直接返回相应错误。例如权限不足可使用 PermissionDenied,不存在可使用 NotFound。
|
||||
|
||||
Reader 只校验 scheme 为不区分大小写的 endor、冒号后非空,且 URI 不含原始空白/控制字符。它不固定 workspace/namespace 的 URI 路径形式,不解码百分号、不实现相对 URI,也不规定修订选择器或 hash 算法。scheme 以外的协议校验由宿主执行,原 URI 不重写。每次读取只调用一次 provider,之后词法和语法处理不再解析 URI。
|
||||
|
||||
revision 是宿主返回的原样标签;Reader 只拒绝全空白标签,不验证标签是否为内容 hash、不验证内容与 hash 的对应关系,也不实现资源历史、依赖锁、发布快照或签名。当前没有内置平台 provider、网络客户端、数据库存储或 CLI URI 执行入口。具体版本模型仍需另行设计。
|
||||
|
||||
## CLI 与交互输入
|
||||
|
||||
CLI parse 文件通过 from_file → parse_source 输出 AST;`cli parse -` 通过 from_stream 读取 stdin 到 EOF,来源为 `<stdin>`。错误保留文件或流名及行列;文件读取与非法 UTF-8 错误在进入 lexer 前返回。命令仍不执行源码。
|
||||
|
||||
stdin 入口不是 REPL,不打印提示符、不保持求值环境,也不区分“需要继续输入”和“真正语法错误”。未来 REPL 宿主先收集一次提交的输入单元,再使用 from_text 并指定会话来源;reader 不承担交互调度。包与 namespace 的成员查找和依赖解析也不由 reader 自动完成。
|
||||
|
||||
运行方式见 [运行指南](../operations/README.md),编码边界见 [文本编码](text-encoding.md),检查范围见 [验证](../operations/validation.md)。本地不编译、不执行测试;流、文件与 provider 检查由指定远端环境执行。
|
||||
@@ -20,7 +20,7 @@ Value::Text 与 EndorStringObject 使用 Rust String,始终是有效 UTF-8。
|
||||
|
||||
String::from_utf8 验证字节;它不会自动识别 Shift_JIS,也不会自动转换编码。某些错误编码字节可能恰好仍是合法 UTF-8,因此“能通过 UTF-8 校验”也不能代替输入协议。[from_utf8 文档](https://doc.rust-lang.org/std/string/struct.String.html#method.from_utf8)。
|
||||
|
||||
CLI parse 已有严格 UTF-8 文件读取,frontend 接收 &str 进行词法和语法解析。当前仍无通用文件/网络文本加载器或 Shift_JIS 解码器;以上非 UTF-8 转换由宿主显式提供,不是已有内置转码能力。无需修改全局 locale 来处理单个文件。
|
||||
EndorReader 提供严格 UTF-8 文件/流读取和宿主 URI provider 适配,输出带来源的 SourceUnit;frontend 将其文本交给 lexer/parser。CLI parse 文件和 stdin 都经过阅读器,见 [阅读器](reader.md)。当前仍无通用文件/网络文本加载器或 Shift_JIS 解码器;以上非 UTF-8 转换由宿主显式提供,不是已有内置转码能力。无需修改全局 locale 来处理单个文件。
|
||||
|
||||
## 其他日文文本差异
|
||||
|
||||
|
||||
Reference in New Issue
Block a user