style:优化代码格式和注释

This commit is contained in:
Luke 2025-07-16 21:31:07 +08:00
parent f540d7fad5
commit e931d9ec06
147 changed files with 696 additions and 705 deletions

View File

@ -11,7 +11,7 @@ body:
attributes:
label: 任务标题
description: 简要描述维护内容
placeholder: "如升级 JDK 版本"
placeholder: "如: 升级 JDK 版本"
validations:
required: true
@ -20,6 +20,6 @@ body:
attributes:
label: 任务详情
description: 描述执行步骤或相关脚本命令
placeholder: "如修改 pom.xml…"
placeholder: "如: 修改 pom.xml…"
validations:
required: false

View File

@ -20,7 +20,7 @@ body:
attributes:
label: 优化方案
description: 详细描述改进思路与实现方式
placeholder: "如缓存机制、算法优化…"
placeholder: "如: 缓存机制、算法优化…"
validations:
required: true
@ -29,6 +29,6 @@ body:
attributes:
label: 预期收益
description: 描述优化后带来的效益或体验提升
placeholder: "如响应时间缩短 30%…"
placeholder: "如: 响应时间缩短 30%…"
validations:
required: false

View File

@ -32,6 +32,6 @@ body:
attributes:
label: 修复截止日期
description: 填写计划完成的日期 (YYYY-MM-DD)
placeholder: "例如2025-06-20"
placeholder: "例如: 2025-06-20"
validations:
required: false

View File

@ -20,7 +20,7 @@ body:
attributes:
label: 已尝试方法
description: 列出已尝试过的解决方案或思路
placeholder: "如查阅文档、尝试示例代码…"
placeholder: "如: 查阅文档、尝试示例代码…"
validations:
required: false
@ -29,6 +29,6 @@ body:
attributes:
label: 期望答案
description: 描述希望获得的解答或帮助方向
placeholder: "如最佳实践、配置示例…"
placeholder: "如: 最佳实践、配置示例…"
validations:
required: false

View File

@ -20,7 +20,7 @@ body:
attributes:
label: 重构原因
description: 说明当前存在的痛点或待改进之处
placeholder: "如变量命名不规范、函数职责过多…"
placeholder: "如: 变量命名不规范、函数职责过多…"
validations:
required: true
@ -29,6 +29,6 @@ body:
attributes:
label: 预期效果
description: 说明重构后带来的好处或验证方式
placeholder: "如提高性能、增强可读性…"
placeholder: "如: 提高性能、增强可读性…"
validations:
required: false

View File

@ -3,14 +3,14 @@
https://gitee.com/jcnc-org/snow/blob/main/doc/Git-Management/Git-Management.md
提交 PR 后,请根据实际情况删除不适用的项。
1. 请在右侧面板中
1. 请在右侧面板中:
- 关联 Issue
- 选择 PR 类型bug 修复 / 新功能 / 文档 / 优化 等)
- 添加必要的标签和审查人
- 请添加里程碑
- 如必要请设置优先级
2. 在下面的“检查清单”里,用 `- [x]` 标记已完成,用 `- [ ]` 标记未完成。例如
2. 在下面的“检查清单”里,用 `- [x]` 标记已完成,用 `- [ ]` 标记未完成。例如:
- [x] 已阅读并遵守项目规范
- [ ] 本地通过所有测试
- [ ] 文档已更新(如有必要)

122
README.md
View File

@ -86,11 +86,11 @@ Snow 语言受到 LLM 驱动代码生成趋势的启发,强调简单而清晰的
## 开发环境安装
1. **开发环境准备**
1. **开发环境准备**:
1. 安装集成开发环境 [IntelliJ IDEA](https://www.jetbrains.com/idea/download)
2. 安装 Java 开发工具 [Graalvm-jdk-24](https://www.graalvm.org/downloads/)
2. **获取源码**
2. **获取源码**:
将项目源码下载或克隆到本地目录。
```bash
git clone https://gitee.com/jcnc-org/snow.git
@ -285,37 +285,37 @@ Snow 语言受到 LLM 驱动代码生成趋势的启发,强调简单而清晰的
独立编译不依赖 `.cloud` 文件,而是直接使用 `Snow` 编译器进行 `.snow` 文件的编译和执行。
#### 独立编译步骤
#### 独立编译步骤:
1. **运行编译器**
1. **运行编译器: **
你可以通过以下命令来编译单个或多个 `.snow` 文件,或者递归编译一个目录中的所有 `.snow` 源文件为`.water`虚拟机指令。
* **单个文件编译**
* **单个文件编译: **
```bash
Snow complete [SnowCode].snow
```
* **多个文件编译**
* **多个文件编译: **
```bash
Snow complete [SnowCode1].snow [SnowCode2].snow [SnowCode3].snow -o [Name]
```
* **目录递归编译**
* **目录递归编译: **
```bash
Snow -d path/to/source_dir
```
2. **查看编译输出**
编译过程会输出源代码、抽象语法树AST、中间表示IR以及虚拟机指令等内容。你可以看到如下几个分段输出
2. **查看编译输出: **
编译过程会输出源代码、抽象语法树AST、中间表示IR以及虚拟机指令等内容。你可以看到如下几个分段输出:
* **AST**(抽象语法树)部分以 JSON 格式输出。
* **IR**(中间表示)部分会列出逐行的中间代码。
* **VM code**(虚拟机指令)会展示虚拟机的字节码指令。
3. **默认执行模式**
3. **默认执行模式: **
编译器会在 **DEBUG 模式** 下运行,显示详细的执行过程和状态,并且在虚拟机中执行编译后的代码,最后会打印出所有局部变量的值。
---
@ -324,30 +324,30 @@ Snow 语言受到 LLM 驱动代码生成趋势的启发,强调简单而清晰的
集成编译需要使用 `.cloud` 文件来指定项目的配置和结构,适用于项目标准化、依赖管理、构建管理和项目分发等场景。
#### 集成编译命令
#### 集成编译命令:
1. **基本用法**
1. **基本用法: **
```bash
snow [OPTIONS] <command>
```
2. **命令选项**
2. **命令选项: **
* `-h, --help`显示帮助信息并退出。
* `-v, --version`打印 Snow 编程语言的版本并退出。
* `-h, --help`: 显示帮助信息并退出。
* `-v, --version`: 打印 Snow 编程语言的版本并退出。
3. **可用命令**
3. **可用命令: **
* `compile``.snow` 源文件编译成虚拟机字节码文件(`.water`)。此命令会使用 `.cloud` 文件来指导编译过程。
* `clean`清理构建输出和本地缓存,移除中间产物,释放磁盘空间。
* `version`打印 Snow 的版本。
* `run`运行已编译的虚拟机字节码文件(`.water`)。
* `init`初始化一个新项目,生成 `project.cloud` 文件。
* `generate`根据 `project.cloud` 生成项目目录结构。
* `build`构建当前项目,按顺序解析依赖、编译和打包。
* `compile`: `.snow` 源文件编译成虚拟机字节码文件(`.water`)。此命令会使用 `.cloud` 文件来指导编译过程。
* `clean`: 清理构建输出和本地缓存,移除中间产物,释放磁盘空间。
* `version`: 打印 Snow 的版本。
* `run`: 运行已编译的虚拟机字节码文件(`.water`)。
* `init`: 初始化一个新项目,生成 `project.cloud` 文件。
* `generate`: 根据 `project.cloud` 生成项目目录结构。
* `build`: 构建当前项目,按顺序解析依赖、编译和打包。
4. **例如,执行集成编译命令**
4. **例如,执行集成编译命令: **
```bash
snow compile [SnowCode].snow
@ -355,14 +355,14 @@ Snow 语言受到 LLM 驱动代码生成趋势的启发,强调简单而清晰的
* 此命令会使用 `.cloud` 文件中的配置信息来指导编译过程,并生成 `.water`
5. **使用帮助**
如果你需要了解某个命令的详细选项,可以使用
5. **使用帮助: **
如果你需要了解某个命令的详细选项,可以使用:
```bash
snow <command> --help
```
例如,查看 `compile` 命令的具体选项
例如,查看 `compile` 命令的具体选项:
```bash
snow compile --help
@ -372,7 +372,7 @@ Snow 语言受到 LLM 驱动代码生成趋势的启发,强调简单而清晰的
## 示例代码片段
以下是一个简单的 Snow 代码示例,演示模块定义,导入和函数声明的基本语法
以下是一个简单的 Snow 代码示例,演示模块定义,导入和函数声明的基本语法:
```snow
module: Math
@ -407,10 +407,10 @@ module: Math
end module
```
上述代码定义了一个名为 `Math` 的模块,其中包含两个函数
上述代码定义了一个名为 `Math` 的模块,其中包含两个函数:
* `main`不接收任何参数,返回类型为 `int`。在函数体内调用了 `Math.factorial(6)`,然后返回 `0`
* `factorial`接收一个 `int` 类型的参数 `n`,返回类型为 `int`。函数体内先声明并初始化局部变量 `num1``1`,然后通过一个
* `main`: 不接收任何参数,返回类型为 `int`。在函数体内调用了 `Math.factorial(6)`,然后返回 `0`
* `factorial`: 接收一个 `int` 类型的参数 `n`,返回类型为 `int`。函数体内先声明并初始化局部变量 `num1``1`,然后通过一个
`loop` 循环(从 `counter = 1``counter <= n`)依次将 `num1` 乘以 `counter`,循环结束后返回 `num1`,即 `n` 的阶乘值。
@ -418,45 +418,45 @@ end module
## 项目结构说明
* `compiler/`Snow 编译器源代码目录
* `compiler/`: Snow 编译器源代码目录
* `lexer/`词法分析模块,负责将源码切分为 Token
* `parser/`语法分析模块,将 Token 流解析为 AST含模块/函数/语句解析)
* `semantic/`语义分析模块,负责符号表管理、类型检查等
* `ir/`中间表示IR模块生成并管理三地址码形式的中间代码
* `backend/`编译器后端模块,将 IR 翻译为虚拟机指令,包含寄存器分配和指令生成器
* `lexer/`: 词法分析模块,负责将源码切分为 Token
* `parser/`: 语法分析模块,将 Token 流解析为 AST含模块/函数/语句解析)
* `semantic/`: 语义分析模块,负责符号表管理、类型检查等
* `ir/`: 中间表示IR模块生成并管理三地址码形式的中间代码
* `backend/`: 编译器后端模块,将 IR 翻译为虚拟机指令,包含寄存器分配和指令生成器
* `vm/`虚拟机相关源代码目录
* `vm/`: 虚拟机相关源代码目录
* `commands/`定义 SnowVM 指令集的具体实现
* `engine/`核心执行引擎,提供指令执行和寄存器/栈管理
* `execution/`执行流程控制(按指令顺序执行、分支跳转等)
* `io/`输入输出辅助类(加载指令、文件解析等)
* `gui/`Swing 可视化调试面板,实时展示局部变量表
* `factories/``utils/`指令创建、日志调试等公共工具
* `commands/`: 定义 SnowVM 指令集的具体实现
* `engine/`: 核心执行引擎,提供指令执行和寄存器/栈管理
* `execution/`: 执行流程控制(按指令顺序执行、分支跳转等)
* `io/`: 输入输出辅助类(加载指令、文件解析等)
* `gui/`: Swing 可视化调试面板,实时展示局部变量表
* `factories/``utils/`: 指令创建、日志调试等公共工具
* `pkg/`内置构建与包管理器 **snow pkg**
* `pkg/`: 内置构建与包管理器 **snow pkg**
* `dsl/``.cloud` 描述文件解析器
* `tasks/`预设任务实现(`clean · compile · run · package · publish` 等)
* `resolver/`本地/远程仓库解析与缓存
* `lifecycle/`任务生命周期钩子pre/post 脚本等)
* `model/`项目、依赖、版本等模型
* `utils/`文件、日志、校验和等通用工具
* `doc/`开发者文档与示例 `.cloud` 配置
* `dsl/`: `.cloud` 描述文件解析器
* `tasks/`: 预设任务实现(`clean · compile · run · package · publish` 等)
* `resolver/`: 本地/远程仓库解析与缓存
* `lifecycle/`: 任务生命周期钩子pre/post 脚本等)
* `model/`: 项目、依赖、版本等模型
* `utils/`: 文件、日志、校验和等通用工具
* `doc/`: 开发者文档与示例 `.cloud` 配置
* `cli/`独立的命令行前端
* `cli/`: 独立的命令行前端
* `commands/``compile` / `run` / `pkg` 等子命令实现
* `api/`公共选项解析、终端交互抽象
* `utils/`终端颜色、进度条、异常格式化等
* `SnowCLI.java`CLI 主入口
* `commands/`: `compile` / `run` / `pkg` 等子命令实现
* `api/`: 公共选项解析、终端交互抽象
* `utils/`: 终端颜色、进度条、异常格式化等
* `SnowCLI.java`: CLI 主入口
## 版权声明
版权所有 © 2025 许轲Luke代表 SnowLang 项目。
仓库地址<https://gitee.com/jcnc-org/snow>
仓库地址: <https://gitee.com/jcnc-org/snow>
本项目依据 [Apache 2.0 许可证](LICENSE) 进行许可和发布。
“SnowLang 项目”为由许轲Luke发起的独立开源项目。
@ -464,7 +464,7 @@ end module
## 加入我们
- 微信`xuxiaolankaka`
- QQ`1399528359`
- 邮箱`luke.k.xu [at] hotmail.com`
- 微信: `xuxiaolankaka`
- QQ: `1399528359`
- 邮箱: `luke.k.xu [at] hotmail.com`

View File

@ -2,27 +2,27 @@
在执行 `build-project2tar.ps1` 脚本之前,您需要确保 PowerShell 的执行策略允许运行脚本。默认情况下PowerShell 可能阻止未签名的脚本执行。因此,您需要设置适当的执行策略。
#### 步骤 1以管理员身份打开 PowerShell
#### 步骤 1: 以管理员身份打开 PowerShell
* 在 Windows 系统中,搜索 **PowerShell**,右键点击 **Windows PowerShell**,并选择 **以管理员身份运行**
#### 步骤 2设置 PowerShell 执行策略
#### 步骤 2: 设置 PowerShell 执行策略
为了允许执行 PowerShell 脚本,您需要调整当前用户的执行策略。输入以下命令并按 Enter
为了允许执行 PowerShell 脚本,您需要调整当前用户的执行策略。输入以下命令并按 Enter:
```powershell
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
```
#### 解释
#### 解释:
* `-Scope CurrentUser`此参数指定该执行策略仅对当前用户有效,而不会影响系统范围内的其他用户。
* `-ExecutionPolicy RemoteSigned`:此策略表示:
* `-Scope CurrentUser`: 此参数指定该执行策略仅对当前用户有效,而不会影响系统范围内的其他用户。
* `-ExecutionPolicy RemoteSigned`: 此策略表示:
* 本地创建的脚本可以直接运行。
* 从互联网下载的脚本必须具备有效的数字签名才能运行。没有签名的脚本将无法执行,除非您先解除阻止该脚本。
#### 步骤 3运行 `build-project2tar.ps1` 脚本
#### 步骤 3: 运行 `build-project2tar.ps1` 脚本
设置完成后,您可以在 PowerShell 中运行 `build-project2tar.ps1` 脚本。确保您已经切换到包含该脚本的目录,或提供完整的文件路径来执行它。

View File

@ -11,7 +11,7 @@ $parentDir = Split-Path -Parent $scriptDir
$tarPath = Join-Path $parentDir $tarName
# 输出开始创建 tar 包的消息
Write-Output "开始创建 tar 包$tarName$parentDir ..."
Write-Output "开始创建 tar 包: $tarName$parentDir ..."
# 如果存在旧 tar 包,先删除它
if (Test-Path $tarPath) {
@ -26,7 +26,7 @@ if (-not (Get-Command $tarCommand -ErrorAction SilentlyContinue)) {
exit 1
}
# 执行打包操作切换到 org\jcnc 目录下再压缩 snow 文件夹
# 执行打包操作: 切换到 org\jcnc 目录下再压缩 snow 文件夹
try {
# 构建命令并执行
$tarCommandArgs = "-cf", $tarPath, "-C", "$scriptDir\..\src\main\java\org\jcnc", "snow"
@ -34,7 +34,7 @@ try {
& $tarCommand @tarCommandArgs
} catch {
Write-Error "❌ 创建 tar 包失败。错误信息$_"
Write-Error "❌ 创建 tar 包失败。错误信息: $_"
exit 1
}

View File

@ -2,7 +2,7 @@
## 1. 版本控制基础
本项目使用 Git 进行版本控制,并遵循以下基本原则
本项目使用 Git 进行版本控制,并遵循以下基本原则:
* 所有代码更改必须通过 Git 提交,并推送至远程仓库。
* 每次提交必须包括清晰、简洁且具描述性的提交信息,确保团队成员能够轻松理解变更的目的和内容。
@ -10,23 +10,23 @@
## 2. 分支管理
本项目采用以下分支策略进行代码管理
本项目采用以下分支策略进行代码管理:
### 2.1 主分支 (`main`)
* **用途**`main` 分支始终保持项目的稳定版本,且此分支的代码随时可以部署到生产环境。
* **更新规则**仅允许经过充分测试并审查的代码合并到 `main` 分支。每次从 `dev``release` 分支合并到 `main` 时,必须打上版本标签。
* **用途**: `main` 分支始终保持项目的稳定版本,且此分支的代码随时可以部署到生产环境。
* **更新规则**: 仅允许经过充分测试并审查的代码合并到 `main` 分支。每次从 `dev``release` 分支合并到 `main` 时,必须打上版本标签。
### 2.2 开发分支 (`dev`)
* **用途**`dev` 分支是所有开发工作的集成分支。所有的新功能开发应首先合并至 `dev` 分支,并经过集成测试后再合并到 `main`
* **更新规则**所有功能开发完成后,应合并至 `dev` 分支进行集成测试,确认没有问题后再合并到 `main`
* **用途**: `dev` 分支是所有开发工作的集成分支。所有的新功能开发应首先合并至 `dev` 分支,并经过集成测试后再合并到 `main`
* **更新规则**: 所有功能开发完成后,应合并至 `dev` 分支进行集成测试,确认没有问题后再合并到 `main`
### 2.3 功能分支 (`feature/*`)
* **用途**每个新功能的开发都应从 `dev` 分支创建一个独立的功能分支。
* **命名规范**`feature/功能描述`,例如:`feature/ast-folding``feature/user-cli`。所有分支名称应使用小写字母,并且使用破折号(`-`)分隔单词。
* **开发流程**
* **用途**: 每个新功能的开发都应从 `dev` 分支创建一个独立的功能分支。
* **命名规范**: `feature/功能描述`,例如: `feature/ast-folding``feature/user-cli`。所有分支名称应使用小写字母,并且使用破折号(`-`)分隔单词。
* **开发流程**:
1. 从 `dev` 分支拉取最新代码。
2. 完成功能开发后,在本地提交代码并推送至远程仓库。
@ -34,9 +34,9 @@
### 2.4 修复分支 (`bugfix/*`)
* **用途**用于修复 Bug修复分支可以从 `dev``main` 分支创建。
* **命名规范**`bugfix/bug描述`,例如:`bugfix/fix-ast-error`
* **开发流程**
* **用途**: 用于修复 Bug修复分支可以从 `dev``main` 分支创建。
* **命名规范**: `bugfix/bug描述`,例如: `bugfix/fix-ast-error`
* **开发流程**:
1. 从 `dev``main` 分支拉取最新代码。
2. 完成修复后,提交修改并推送至远程仓库。
@ -44,9 +44,9 @@
### 2.5 发布分支 (`release/*`)
* **用途**`dev` 分支的功能开发完成且准备发布时,应创建一个 `release` 分支进行发布准备。
* **命名规范**`release/vX.X.X`,例如:`release/v1.0.0`
* **开发流程**
* **用途**: `dev` 分支的功能开发完成且准备发布时,应创建一个 `release` 分支进行发布准备。
* **命名规范**: `release/vX.X.X`,例如: `release/v1.0.0`
* **开发流程**:
1. 从 `dev` 分支创建 `release` 分支。
2. 在 `release` 分支上进行版本发布的最终准备工作,如文档更新、版本号调整等。
@ -54,24 +54,24 @@
### 2.6 热修复分支 (`hotfix/*`)
* **用途**当生产环境中发现紧急问题(如 Bug 或系统崩溃等),需在 `main` 分支上进行快速修复时,应创建一个 `hotfix` 分支进行修复。
* **命名规范**`hotfix/bug描述`,例如:`hotfix/fix-production-crash`
* **开发流程**
* **用途**: 当生产环境中发现紧急问题(如 Bug 或系统崩溃等),需在 `main` 分支上进行快速修复时,应创建一个 `hotfix` 分支进行修复。
* **命名规范**: `hotfix/bug描述`,例如: `hotfix/fix-production-crash`
* **开发流程**:
1. 从 `main` 分支创建 `hotfix` 分支,确保该分支包含生产环境中最新的稳定版本。
2. 在 `hotfix` 分支上进行问题修复和相关调整。
3. 完成修复后,提交修改并推送至远程仓库。
4. 创建拉取请求PR`hotfix` 分支合并至 `main` 分支并打上版本标签,确保生产环境修复生效。
5. 将修复后的变更合并回 `dev` 分支,确保所有的修复和调整同步到开发分支,防止后续开发中出现同样的问题。
6. **回滚策略**如果热修复未能解决问题,立即回滚合并,删除 `hotfix` 分支并通知团队,确保不影响生产环境。
6. **回滚策略**: 如果热修复未能解决问题,立即回滚合并,删除 `hotfix` 分支并通知团队,确保不影响生产环境。
## 3. 提交规范
为确保提交信息清晰且易于理解,遵循以下提交规范
为确保提交信息清晰且易于理解,遵循以下提交规范:
### 3.1 提交信息格式
提交信息应简洁且具有描述性,格式如下
提交信息应简洁且具有描述性,格式如下:
```
[类型] 描述
@ -81,20 +81,20 @@
#### 提交类型
* `feat`新增功能
* `fix`修复 Bug
* `docs`文档更新
* `style`代码格式调整(不影响功能)
* `refactor`代码重构
* `test`增加/修改测试
* `chore`工具配置等其他杂项任务
* `ci`持续集成相关改动
* `perf`性能优化
* `feat`: 新增功能
* `fix`: 修复 Bug
* `docs`: 文档更新
* `style`: 代码格式调整(不影响功能)
* `refactor`: 代码重构
* `test`: 增加/修改测试
* `chore`: 工具配置等其他杂项任务
* `ci`: 持续集成相关改动
* `perf`: 性能优化
#### 示例
* `feat: 添加 IR 折叠功能`
* `fix: 修复问题 Y原因X bug解决方案Z`
* `fix: 修复问题 Y原因: X bug解决方案: Z`
* `docs: 更新 API 文档`
* `refactor: 优化 AST 逻辑`
@ -114,7 +114,7 @@
### 4.2 代码审查
* 所有 PR 必须经过至少一名开发者的代码审查。
* 审查时应关注以下方面
* 审查时应关注以下方面:
* 代码是否符合项目的编码规范。
* 是否提供了足够的单元测试覆盖。
@ -124,14 +124,14 @@
## 5. 版本发布
版本发布基于 Git 标签,发布流程如下
版本发布基于 Git 标签,发布流程如下:
### 5.1 打标签
每当版本准备发布时,应在 `main` 分支上打上版本标签
每当版本准备发布时,应在 `main` 分支上打上版本标签:
* **版本号规则**采用语义化版本控制SemVer格式版本号由三部分组成`主版本号.次版本号.修订号`(例如:`v1.0.0`)。
* **标签命令**
* **版本号规则**: 采用语义化版本控制SemVer格式版本号由三部分组成: `主版本号.次版本号.修订号`(例如: `v1.0.0`)。
* **标签命令**:
```bash
git tag v1.0.0

View File

@ -6,7 +6,7 @@
## 2. 前置条件
1. 操作系统Linux/macOS/Windows
1. 操作系统: Linux/macOS/Windows
2. Java 项目Maven
3. GraalVM建议 24+ 版本)
@ -14,10 +14,10 @@
### 3.1 安装 GraalVM
1. 下载对应平台的 GraalVM Community 版本[https://www.graalvm.org/downloads/](https://www.graalvm.org/downloads/)
2. 解压并配置环境变量
1. 下载对应平台的 GraalVM Community 版本: [https://www.graalvm.org/downloads/](https://www.graalvm.org/downloads/)
2. 解压并配置环境变量:
3. 验证安装
3. 验证安装:
```bash
java -version
@ -44,12 +44,12 @@ Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 24.0.1+9.1 (build 24.0.1+9-jvmc
## 4. Maven 项目配置文件
通过将以下配置文件添加到 `pom.xml` 中,为 Native Image 启用 Maven 插件
通过将以下配置文件添加到 `pom.xml` 中,为 Native Image 启用 Maven 插件:
```xml
<profiles>
<!--
原生镜像构建Linux 平台
原生镜像构建: Linux 平台
- 使用 GraalVM 的 native-image 工具,生成静态链接的可执行文件
- 依赖 musl libc需提前安装并配置 musl-gcc 工具链
-->
@ -111,7 +111,7 @@ Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 24.0.1+9.1 (build 24.0.1+9-jvmc
</profile>
<!--
原生镜像构建Windows 平台
原生镜像构建: Windows 平台
- 使用 GraalVM 的 native-image 工具,生成 Windows 可执行文件
- Windows 上不使用 musl因此不配置静态链接
-->
@ -169,6 +169,6 @@ Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 24.0.1+9.1 (build 24.0.1+9-jvmc
![IMG_Maven_Package_1.png](img/IMG_Maven_Package_1.png)
3. 等待 Native Image 构建完成这个过程可能较慢(数分钟)。
3. 等待 Native Image 构建完成: 这个过程可能较慢(数分钟)。
4. 可执行文件即可直接运行,无需 JVM。
> 生成的可执行文件位于 target/ 目录。

View File

@ -7,22 +7,22 @@
## 1.2 背景与目标读者
自 ChatGPT 3.5 诞生以来,越来越多的个人和企业将 LLM 生成的代码融入日常开发与自动化。然而,实践证明LLM 生成的代码虽然“看起来没问题”,却常因对底层语言细节把握不准导致微妙 Bug——比如运算符优先级混淆、作用域处理错误、甚至基础库调用都无法编译通过。
自 ChatGPT 3.5 诞生以来,越来越多的个人和企业将 LLM 生成的代码融入日常开发与自动化。然而,实践证明: LLM 生成的代码虽然“看起来没问题”,却常因对底层语言细节把握不准导致微妙 Bug——比如运算符优先级混淆、作用域处理错误、甚至基础库调用都无法编译通过。
于是,我萌生了这样一个想法**能否设计一门编程语言,让 LLM 在“语法层面”能够更精准、高效地理解和生成代码?**
于是,我萌生了这样一个想法: **能否设计一门编程语言,让 LLM 在“语法层面”能够更精准、高效地理解和生成代码?**
传统编程语言的设计多偏重“计算机”的执行效率程序员往往在抽象表达和底层性能之间不断权衡。Ruby 之父松本行弘提出“为人而不是为机器编程”的理念。而在 LLM 日益普及的今天,我们应当承认大型模型正成为“超级程序员”,它们不仅是助手,更是“代码生产的中介”。如果一门语言的语法和设计能最大化发挥 LLM 的推理与生成能力,人机协作的效率将被极大提升。
传统编程语言的设计多偏重“计算机”的执行效率程序员往往在抽象表达和底层性能之间不断权衡。Ruby 之父松本行弘提出“为人而不是为机器编程”的理念。而在 LLM 日益普及的今天,我们应当承认: 大型模型正成为“超级程序员”,它们不仅是助手,更是“代码生产的中介”。如果一门语言的语法和设计能最大化发挥 LLM 的推理与生成能力,人机协作的效率将被极大提升。
因此,**Snow** 的使命是让编程语言不再“让人头疼”,而是“让 LLM 更加从容地书写”。目标受众涵盖 LLM 爱好者、开发者、对编译原理感兴趣的学生,以及对性能有追求的工程师甚至是初学者——每个人都能在 Snow 中找到乐趣与成长。
因此,**Snow** 的使命是: 让编程语言不再“让人头疼”,而是“让 LLM 更加从容地书写”。目标受众涵盖 LLM 爱好者、开发者、对编译原理感兴趣的学生,以及对性能有追求的工程师甚至是初学者——每个人都能在 Snow 中找到乐趣与成长。
## 1.3 文章目的
本文将带你完整体验 Snow 从零到 v0.1 的诞生历程,围绕四个核心目标
本文将带你完整体验 Snow 从零到 v0.1 的诞生历程,围绕四个核心目标:
* **兴趣驱动的坚持**用真实经历激励更多人相信“兴趣是最好的动力”,哪怕工作再忙,也能靠热爱坚持探索。
* **从规划到实践的拆解**详解在有限资源下如何一步步拆解出词法分析、语法解析、AST 构建、解释执行等关键模块,以“先可用后完备”为原则,稳步推进。
* **经验与反思**不仅有“成功输出 1+1=2”的成就感也有调试死循环、运算符冲突等踩坑经历全方位展示编程语言设计的挑战与思考。
* **激励与号召**希望 Snow 成为开源社区的新起点,邀请更多伙伴参与,见证从 v0.2、v1.0 甚至到未来并发、标准库、包管理等更大梦想的实现。
* **兴趣驱动的坚持**: 用真实经历激励更多人相信“兴趣是最好的动力”,哪怕工作再忙,也能靠热爱坚持探索。
* **从规划到实践的拆解**: 详解在有限资源下如何一步步拆解出词法分析、语法解析、AST 构建、解释执行等关键模块,以“先可用后完备”为原则,稳步推进。
* **经验与反思**: 不仅有“成功输出 1+1=2”的成就感也有调试死循环、运算符冲突等踩坑经历全方位展示编程语言设计的挑战与思考。
* **激励与号召**: 希望 Snow 成为开源社区的新起点,邀请更多伙伴参与,见证从 v0.2、v1.0 甚至到未来并发、标准库、包管理等更大梦想的实现。
---
@ -31,18 +31,18 @@
## 2.1 现有工具的痛点
* **编程语言过于灵活,缺乏规范**
常见的编程语言如 Python、PHP、Ruby虽然语法简洁、上手快但“灵活性”本身也带来了不少隐患变量类型可以随意变化,作用域和命名规则宽松,团队协作时代码风格极易失控,隐蔽 Bug 难以及时发现。自动化运维和日常数据处理脚本往往随手一写,维护与交接时却漏洞百出、沟通成本高。许多开发者都在思考如果有一门语法严谨、行为可预测,并天然适合团队协作与 LLM 生成的编程语言,是不是能让代码质量和工程效率都上一个台阶?
常见的编程语言如 Python、PHP、Ruby虽然语法简洁、上手快但“灵活性”本身也带来了不少隐患: 变量类型可以随意变化,作用域和命名规则宽松,团队协作时代码风格极易失控,隐蔽 Bug 难以及时发现。自动化运维和日常数据处理脚本往往随手一写,维护与交接时却漏洞百出、沟通成本高。许多开发者都在思考: 如果有一门语法严谨、行为可预测,并天然适合团队协作与 LLM 生成的编程语言,是不是能让代码质量和工程效率都上一个台阶?
* **缺乏专为 LLM 设计的编程语言**
当下主流编程语言,基本都是“为人类程序员”而设计,很少考虑 LLM 的生成和推理习惯。比如部分语法容易混淆作用域和可见性规则不直观LLM 在生成时不仅需要大量提示,结果还常常不理想。缺少一门语法清晰、特征单一、对 LLM 友好的编程语言,导致自动化和智能生成代码场景下,仍然存在很多不可控和效率瓶颈。
当下主流编程语言,基本都是“为人类程序员”而设计,很少考虑 LLM 的生成和推理习惯。比如: 部分语法容易混淆作用域和可见性规则不直观LLM 在生成时不仅需要大量提示,结果还常常不理想。缺少一门语法清晰、特征单一、对 LLM 友好的编程语言,导致自动化和智能生成代码场景下,仍然存在很多不可控和效率瓶颈。
## 2.2 触发想法的场景
* **对高效与规范的需求日益突出**
在实际开发和运维工作中,我们经常要写各种自动化脚本。由于编程语言过于灵活,代码风格极易失控,维护起来痛苦不堪。团队中常常讨论能否有一门语法严谨、易于规范化、适合团队协作的编程语言?大家都希望提升代码质量,减少后期返工。
在实际开发和运维工作中,我们经常要写各种自动化脚本。由于编程语言过于灵活,代码风格极易失控,维护起来痛苦不堪。团队中常常讨论: 能否有一门语法严谨、易于规范化、适合团队协作的编程语言?大家都希望提升代码质量,减少后期返工。
* **自研编程语言的大胆设想**
随着 LLM 在自动化、辅助编程中的应用普及,越来越多场景下希望直接“让 LLM 写代码”。但事实是,不管是让 LLM 生成 Python 还是 PHP总要写很多提示还要人工修正各种细节。由此引发思考如果有一门对 LLM 友好的编程语言,语法特征清晰、行为可预测,能不能大幅提升代码自动生成与落地的效率?
随着 LLM 在自动化、辅助编程中的应用普及,越来越多场景下希望直接“让 LLM 写代码”。但事实是,不管是让 LLM 生成 Python 还是 PHP总要写很多提示还要人工修正各种细节。由此引发思考: 如果有一门对 LLM 友好的编程语言,语法特征清晰、行为可预测,能不能大幅提升代码自动生成与落地的效率?
## 2.3 项目愿景
@ -62,12 +62,12 @@
## 3.1 为什么开源
* **获得社区反馈,检验设计思路**闭门造车易“自嗨”,开源能快速获得用户和专家的多视角建议。
* **边开源边完善,更吸引贡献者**功能精简但可用时就发布,容易吸引早期用户参与共建。
* **获得社区反馈,检验设计思路**: 闭门造车易“自嗨”,开源能快速获得用户和专家的多视角建议。
* **边开源边完善,更吸引贡献者**: 功能精简但可用时就发布,容易吸引早期用户参与共建。
## 3.2 开源准备工作
* **许可证选择**
* **许可证选择**:
采用 [Apache-2.0](https://gitee.com/jcnc-org/snow/blob/main/LICENSE),最大程度降低贡献门槛。
## 3.3 项目运行输出
@ -248,11 +248,11 @@ Process has ended
## 4.1 v0.2 初步目标
1. **完善变量作用域与高级函数调用**
1. **完善变量作用域与高级函数调用**:
支持函数参数、返回值、本地与全局变量隔离,以及闭包基础,为并发/异步打基础。
2. **完善错误提示与调试信息**
2. **完善错误提示与调试信息**:
报错更精准,方便新手调试。
3. **预计发布日期2025 年 7 月 30 日**
3. **预计发布日期: 2025 年 7 月 30 日**
## 4.2 v0.3 目标
1. **IDE的支持**
@ -262,11 +262,11 @@ Process has ended
## 4.3 v1.0 长期规划
1. **初步标准库**
1. **初步标准库**:
I/O、字符串、JSON、文件系统满足日常脚本需求。
2. **包管理与模块加载**
2. **包管理与模块加载**:
设计 `snowpkg`,支持一键安装依赖、自动模块导入。
3. **社区协作与贡献**
3. **社区协作与贡献**:
开设设计讨论区、每月线上分享,鼓励贡献代码与案例,让更多人参与 Snow 的成长。
---
@ -275,15 +275,15 @@ Process has ended
## 5.1 学习收获与成就感
回望从零到 v0.1 的历程,我最开始设计了虚拟机,然后设计的编译器,最震撼的是让一个想法变成可运行的代码哪怕只输出一句“Hello, Snow!”也足以令人热血沸腾。每一次 Snow 在屏幕上输出,都让我更深刻理解了编译原理的乐趣。
回望从零到 v0.1 的历程,我最开始设计了虚拟机,然后设计的编译器,最震撼的是: 让一个想法变成可运行的代码哪怕只输出一句“Hello, Snow!”也足以令人热血沸腾。每一次 Snow 在屏幕上输出,都让我更深刻理解了编译原理的乐趣。
## 5.2 技术敬畏与情感共鸣
也许有人会说“输出一句话算什么”,但其实,每一个简单的表达式背后,都凝结了无数技术细节多字符运算符的处理、优先级解析、AST 与符号表、作用域管理、底层 GC 可行性……每一环都让人敬畏计算机科学之美。
也许有人会说“输出一句话算什么”,但其实,每一个简单的表达式背后,都凝结了无数技术细节: 多字符运算符的处理、优先级解析、AST 与符号表、作用域管理、底层 GC 可行性……每一环都让人敬畏计算机科学之美。
## 5.3 欢迎你的加入
真诚邀请所有对编程语言、编译原理、LLM 应用感兴趣的小伙伴
真诚邀请所有对编程语言、编译原理、LLM 应用感兴趣的小伙伴:
1. 在 Gitee 提交 Issue反馈使用体验和建议
2. Fork 仓库、贡献 PR参与语法和功能共建
@ -294,7 +294,7 @@ Process has ended
> 微信: xuxiaolankaka
> QQ: 1399528359
对于从未写过语言的初学者,我想说**不要害怕,从 Hello World 开始,你会发现编译原理其实很有趣。** 让我们一起,把 Snow 打造为兼顾 LLM 友好和人类易用的创新编程语言。也许,下一个改变编程世界的创举,就在我们手中诞生。
对于从未写过语言的初学者,我想说: **不要害怕,从 Hello World 开始,你会发现编译原理其实很有趣。** 让我们一起,把 Snow 打造为兼顾 LLM 友好和人类易用的创新编程语言。也许,下一个改变编程世界的创举,就在我们手中诞生。
---

View File

@ -1,6 +1,6 @@
# Snow 语言现状和下一阶段开发路线图
> 日期2025-06-11
> 日期: 2025-06-11
## 1. 代码结构与职责
| 层次 | 主要包/目录 | 说明 |
@ -30,7 +30,7 @@
6. **VM**
* 栈-基 / 寄存器混合架构
* 96 条已实现指令(按数据宽度泛化B/S/I/L/F/D
* 96 条已实现指令(按数据宽度泛化: B/S/I/L/F/D
* 运行时启动器 `VMLauncher`
@ -50,7 +50,7 @@
## 4. 下一阶段开发路线图
> 优先级P0 = 当前版本必须P1 = 下一个小版本P2 = 中长期
> 优先级: P0 = 当前版本必须P1 = 下一个小版本P2 = 中长期
| 优先级 | 功能 | 关键任务 |
|--------|------------------|----------------------------------------------------------------------------------------------------------------------|
@ -58,18 +58,18 @@
| **P0** | **一元表达式解析** | \* 实现 `UnaryOperatorParselet``-`, `+`, `!`)<br>\* 对应 `UnaryOpGenerator` 注册 |
| **P1** | **数组与切片** | \* 设计 `ArrayType`(元素类型 + 维度)<br>\* 新增 `IndexExpressionNode``NewArrayNode`<br>\* VM 扩充 `ALOAD/ASTORE` 指令 |
| **P1** | **基础标准库** | \* `print/println`, 文件读写<br>\* 编译期内置绑定到 VM calls |
| **P1** | **测试与 CI** | \* JUnit5 单测Lexer / Parser / Semantic / VM<br>\* CI/CD 自动构建、示例编译运行 |
| **P2** | **结构体 / 简单面向对象** | \* 结构体 语法、记录类型布局<br>\* 方法调度静态 or 虚表 |
| **P1** | **测试与 CI** | \* JUnit5 单测: Lexer / Parser / Semantic / VM<br>\* CI/CD 自动构建、示例编译运行 |
| **P2** | **结构体 / 简单面向对象** | \* 结构体 语法、记录类型布局<br>\* 方法调度: 静态 or 虚表 |
| **P2** | **优化管线** | \* 常量折叠、公共子表达式消除<br>\* 简易死代码清除 |
| **P2** | **错误与异常系统** | \* 语法`try … catch … end`<br>\* VM展开-收缩栈,异常表 |
| **P2** | **包管理 & CLI** | \* `snowc` 命令`build`, `run`, `test`<br>\* 本地缓存 `.snowpkg`与包版本语义 |
| **P2** | **错误与异常系统** | \* 语法: `try … catch … end`<br>\* VM: 展开-收缩栈,异常表 |
| **P2** | **包管理 & CLI** | \* `snowc` 命令: `build`, `run`, `test`<br>\* 本地缓存 `.snowpkg`与包版本语义 |
## 5.1 里程碑排期
| 时间 | 目标 |
|---------|----------------------------------------|
| 2025-07 | 发布 **v0.2.0**布尔类型 + 一元运算、20+ 单元测试 |
| 2025-08 | 发布 **v0.3.0**数组/切片 & 基础标准库;引入 CLI |
| 2025-10 | 发布 **v0.4.0**结构体支持、首批优化 Pass、>80% 覆盖率 |
| 2026-11 | 发布 **v1.0.0**异常系统、稳定包管理、文档完善 |
| 2025-07 | 发布 **v0.2.0**: 布尔类型 + 一元运算、20+ 单元测试 |
| 2025-08 | 发布 **v0.3.0**: 数组/切片 & 基础标准库;引入 CLI |
| 2025-10 | 发布 **v0.4.0**: 结构体支持、首批优化 Pass、>80% 覆盖率 |
| 2026-11 | 发布 **v1.0.0**: 异常系统、稳定包管理、文档完善 |

View File

@ -4,8 +4,8 @@
## 0 · 符号约定
* ⟦ … ⟧可选项0 或 1 次)
* { … }\*可重复项0 次或多次)
* ⟦ … ⟧: 可选项0 或 1 次)
* { … }\*: 可重复项0 次或多次)
---
@ -19,12 +19,12 @@
identifier ::= [A-Za-z_][A-Za-z0-9_]* ;
```
* **区分大小写**Foo 与 foo 为不同标识符。
* **区分大小写**: Foo 与 foo 为不同标识符。
* 保留字 (见 §1.3) **禁止** 用作标识符。
### 1.2 分隔符与强制空白
相邻两个标记之间 **推荐** 至少以 1 个空白字符分隔,除非记号本身带有定界符 (( ) , : = < > 等)。示例
相邻两个标记之间 **推荐** 至少以 1 个空白字符分隔,除非记号本身带有定界符 (( ) , : = < > 等)。示例:
```snow
module: Foo // 推荐
@ -44,22 +44,22 @@ end loop break continue self
### 1.4 文字量 (Literal)
* **整型**123 0 -42
* **浮点**3.14 0.0
* **布尔**true false
* **字符串**未来版本保留;当前规范未定义。
* **整型**: 123 0 -42
* **浮点**: 3.14 0.0
* **布尔**: true false
* **字符串**: 未来版本保留;当前规范未定义。
### 1.5 注释
* **单行注释**以 // 起,至当行行尾。
* **多行注释**/* … */ 可跨行。**不可嵌套**;嵌套会在最内层 */ 处终止外层,导致编译错误。
* **单行注释**: 以 // 起,至当行行尾。
* **多行注释**: /* … */ 可跨行。**不可嵌套**;嵌套会在最内层 */ 处终止外层,导致编译错误。
---
### 1.6 换行与缩进
* **只有换行有语义**以行末冒号(:)打开一个块时(如 module:、function:、if、loop: 等),块体**必须另起新行**。
* **缩进没有语义**缩进仅用于提高代码可读性,对语法无影响。缩进不一致不会报错。
* **只有换行有语义**: 以行末冒号(:)打开一个块时(如 module:、function:、if、loop: 等),块体**必须另起新行**。
* **缩进没有语义**: 缩进仅用于提高代码可读性,对语法无影响。缩进不一致不会报错。
* 块体通过显式关闭关键字(如 end module、end function 等)结束。
* 若关闭关键字与开始关键字之间的缩进不一致,不会报错,仍以关闭关键字为准。
@ -82,7 +82,7 @@ end module
* **允许** 不同文件夹下声明同名模块,但模块全名(含包路径,用点分隔)在全项目中必须唯一。
* 若项目中出现重复的模块全名,编译阶段将报重定义错误。
例如
例如:
> src/util/math.snow // module: util.math
> src/core/math.snow // module: core.math
>
@ -95,15 +95,15 @@ import: <ModuleA>⟦ as <AliasA>⟧, <ModuleB>⟦ as <AliasB>⟧, …
```
* **别名 (Alias)** 可为任何合法标识符,放在 as 关键字之后。
* **重复导入**对同一模块多次导入(无论是否带 alias只解析一次其余忽略告警。
* **循环依赖**当前规范未定义,若出现编译器可拒绝或延迟解析。
* **重复导入**: 对同一模块多次导入(无论是否带 alias只解析一次其余忽略告警。
* **循环依赖**: 当前规范未定义,若出现编译器可拒绝或延迟解析。
* **子模块**(诸如 A.B暂不支持。
### 2.3 全路径引用
* 跨模块引用必须使用 _Prefix_._Name_其中 *Prefix* 是模块名或导入时的别名。
例如Math.Point 或 M.sin。
* **解析顺序**未加前缀的标识符只在本模块查找;找不到则视为编译错误,不会隐式搜索导入模块。
例如: Math.Point 或 M.sin。
* **解析顺序**: 未加前缀的标识符只在本模块查找;找不到则视为编译错误,不会隐式搜索导入模块。
---
@ -111,27 +111,27 @@ import: <ModuleA>⟦ as <AliasA>⟧, <ModuleB>⟦ as <AliasB>⟧, …
### 3.1 作用域层级
1. **模块顶层**全局变量、结构体、模块级函数。
2. **结构体内部**字段、方法、构造函数。
3. **函数/方法**形参与局部变量。
1. **模块顶层**: 全局变量、结构体、模块级函数。
2. **结构体内部**: 字段、方法、构造函数。
3. **函数/方法**: 形参与局部变量。
4. **局部嵌套块** (if / loop 等) 的局部变量。
### 3.2 唯一性规则
* **模块顶层唯一**同一模块的 *结构体名*、*模块级函数名*、*全局变量名* **不得重名**
* **结构体内部**字段名与方法名不得相同;**允许有多个与结构体名同名的函数(即构造函数重载),但其参数签名必须互不相同。**
* **构造函数重载**结构体内部可以声明多个与结构体名同名的函数作为构造函数,参数类型与数量必须不同,否则属于 DuplicateName 错误。
* **跨层级遮蔽**内层可定义与外层同名标识符(除关键字限制外),遵循最近作用域原则。
* **模块顶层唯一**: 同一模块的 *结构体名*、*模块级函数名*、*全局变量名* **不得重名**
* **结构体内部**: 字段名与方法名不得相同;**允许有多个与结构体名同名的函数(即构造函数重载),但其参数签名必须互不相同。**
* **构造函数重载**: 结构体内部可以声明多个与结构体名同名的函数作为构造函数,参数类型与数量必须不同,否则属于 DuplicateName 错误。
* **跨层级遮蔽**: 内层可定义与外层同名标识符(除关键字限制外),遵循最近作用域原则。
### 3.3 访问控制约定
* **私有成员与方法**以单个下划线 `_` 开头的变量名、字段名或方法名,**仅在其所属结构体或模块内部可见**。外部不可访问,编译器应报错 `AccessDenied`
* **私有成员与方法**: 以单个下划线 `_` 开头的变量名、字段名或方法名,**仅在其所属结构体或模块内部可见**。外部不可访问,编译器应报错 `AccessDenied`
- 例如 `_foo`, `_barMethod`
* **公有成员与方法**非下划线开头的变量、字段、方法,默认为公有。可在模块外部通过模块名/别名前缀访问。
* **公有成员与方法**: 非下划线开头的变量、字段、方法,默认为公有。可在模块外部通过模块名/别名前缀访问。
#### 影响范围
- **模块级变量与函数**`globals``function` 语句声明的以 `_` 开头者,仅限本模块访问。
- **结构体字段与方法**声明为 `_name``_doSomething` 的,仅结构体本身或其方法体可访问。
- **模块级变量与函数**: `globals``function` 语句声明的以 `_` 开头者,仅限本模块访问。
- **结构体字段与方法**: 声明为 `_name``_doSomething` 的,仅结构体本身或其方法体可访问。
---
#### 访问示例
@ -220,7 +220,7 @@ struct: StructName
end struct
```
**实例化**
**实例化**:
* declare p: Point = Point(1, 2)
* declare p2: Point = Point(3)
@ -243,7 +243,7 @@ function: FuncName
end function
```
* **返回检查**若 returns: 指定类型非 void所有控制流路径必须显式 return 该类型值。
* **返回检查**: 若 returns: 指定类型非 void所有控制流路径必须显式 return 该类型值。
* 在 loop 内或经 break 跳出后能到达的路径亦计入检查;若缺失,编译错误。
---
@ -287,7 +287,7 @@ loop:
end loop
```
* **作用域**init 块声明的变量仅在本 loop 的 init/cond/step/body 有效。
* **作用域**: init 块声明的变量仅在本 loop 的 init/cond/step/body 有效。
* break 立即终止当前循环continue 跳过剩余 body执行 step → cond。
---
@ -296,7 +296,7 @@ end loop
### 6.1 数值类型
Snow-Lang 支持下列**数值类型**,用于声明变量、参数、结构体字段、函数返回等
Snow-Lang 支持下列**数值类型**,用于声明变量、参数、结构体字段、函数返回等:
| 类型名 | 关键字 | 位数 | 描述 |
|----------|--------|----|---------------------------|
@ -315,7 +315,7 @@ Snow-Lang 支持下列**数值类型**,用于声明变量、参数、结构体
#### 数值字面量后缀
为指定具体类型,可在数值字面量后加后缀字母(大小写均可)
为指定具体类型,可在数值字面量后加后缀字母(大小写均可):
| 后缀 | 类型 | 例子 |
|----|--------|----------|
@ -329,7 +329,7 @@ Snow-Lang 支持下列**数值类型**,用于声明变量、参数、结构体
- 没有后缀的整数字面量自动为 `int`
- 没有后缀的浮点字面量自动为 `double`
**示例**
**示例: **
```snow
declare a: int = 7 // int (默认)
declare b: long = 9l // long
@ -405,17 +405,17 @@ declare a: Point = Point(1, 2)
## 7 · 名字解析算法(概览)
1. **输入**未限定前缀的标识符 N当前作用域 S。
1. **输入**: 未限定前缀的标识符 N当前作用域 S。
2. 自内向外遍历作用域链查找 N首次匹配即确定绑定。
3. 若遍历至模块顶层仍未匹配,编译错误 *UnresolvedIdentifier*
4. 限定名 Prefix.N直接在模块表中查 Prefix包括别名成功后在该模块顶层查找 N找不到即 *UnresolvedQualifiedIdentifier*
4. 限定名 Prefix.N: 直接在模块表中查 Prefix包括别名成功后在该模块顶层查找 N找不到即 *UnresolvedQualifiedIdentifier*
---
## 8 · 编译单位与入口
* **单一入口**编译器需指定某模块某函数作为启动入口。
* **模块初始化**globals 块中的带初值变量在程序启动时自顶向下按出现顺序初始化;不同模块按依赖拓扑顺序初始化(循环依赖未定义)。
* **单一入口**: 编译器需指定某模块某函数作为启动入口。
* **模块初始化**: globals 块中的带初值变量在程序启动时自顶向下按出现顺序初始化;不同模块按依赖拓扑顺序初始化(循环依赖未定义)。
---
@ -445,7 +445,7 @@ module: RectExample
declare x: int
declare y: int
// 构造函数1两个参数
// 构造函数1: 两个参数
function: Point
params:
declare x: int
@ -456,7 +456,7 @@ module: RectExample
end body
end function
// 构造函数2一个参数
// 构造函数2: 一个参数
function: Point
params:
declare xy: int
@ -553,7 +553,7 @@ end module
## 11 · 构造函数重载示例
**示例**
**示例: **
````snow
struct: Point

View File

@ -31,14 +31,14 @@ end module
### 数据类型
bool 类型
bool 类型:
两种值`true``false`
两种值: `true``false`
数值类型
数值类型:
| Number | keyword |
|----------|---------|
@ -51,7 +51,7 @@ bool 类型:
默认整数的类型为 int浮点数的类型为 double。
数值字面量后缀
数值字面量后缀:
| 数值字面量后缀 | 例子 |
|---------|----|
@ -64,7 +64,7 @@ bool 类型:
### 变量
定义变量的形式如下,中括号表示可选
定义变量的形式如下,中括号表示可选:
```snow
declare name: type [= initial_value]
@ -72,24 +72,24 @@ declare name: type [= initial_value]
其中 `name` 是变量名,`type` 是变量类型,`initial_value` 是初始值
:
```snow
declare x: int
declare y: long = 123456789
```
读取变量值的方法,直接写变量的名字即可
读取变量值的方法,直接写变量的名字即可:
```snow
x
```
设置变量值的方法,先写变量名,后面接 `=`,最后写一个表达式即可
设置变量值的方法,先写变量名,后面接 `=`,最后写一个表达式即可:
```snow
x = 10
```
于是可以通过这种方式让变量参与计算并保存结果
于是可以通过这种方式让变量参与计算并保存结果:
```snow
x = y + 1
```
@ -99,7 +99,7 @@ x = y + 1
## 流程控制
### if
if 语句的形式如下else 是可选的
if 语句的形式如下else 是可选的:
```snow
if cond then
@ -111,7 +111,7 @@ end if
cond 可以是表达式(结果为 bool 类型)或者 bool 字面量
:
```snow
module: Main
@ -131,7 +131,7 @@ end module
```
### loop
loop 语句的形式如下
loop 语句的形式如下:
```snow
loop:
init:
@ -150,7 +150,7 @@ loop:
end loop
```
例子(求 1 ~ 100 的和)
例子(求 1 ~ 100 的和):
```snow
module: Main
function: main
@ -176,7 +176,7 @@ end module
```
## 函数
函数的形式如下
函数的形式如下:
```snow
function: add
parameter:
@ -197,7 +197,7 @@ end function
通过 import 语句导入模块,
snow 会自动将同名模块的函数合并。
在我们最初的例子中,就用了 module 这个关键字。让我们回忆一下
在我们最初的例子中,就用了 module 这个关键字。让我们回忆一下:
```snow
module: Main
@ -213,7 +213,7 @@ end module
可以看到模块名是 Main里面有函数 main。
假如现在有一个模块 Math代码如下
假如现在有一个模块 Math代码如下:
```snow
// Math.snow
module: Math
@ -229,7 +229,7 @@ module: Math
end module
```
可以使用 import 来导入 Math 模块
可以使用 import 来导入 Math 模块:
```snow
// main.snow
module: Main
@ -244,7 +244,7 @@ module: Main
end module
```
可以同时导入多个模块,用逗号(半角)分隔模块名即可
可以同时导入多个模块,用逗号(半角)分隔模块名即可:
```snow
// main.snow
module: Main

View File

@ -1,17 +1,8 @@
module: Main
function: main
return_type: int
body:
foo()
return 0
end body
end function
function: foo
return_type: void
body:
declare 1sum :int =1
end body
end function
end module

View File

@ -31,7 +31,7 @@
<plugins>
<!--
Java 编译插件
Java 编译插件:
- 使用 Maven 自带的 maven-compiler-plugin 进行源码编译
- <fork>true</fork> 表示在单独的进程中执行 javac提高兼容性
-->
@ -45,7 +45,7 @@
</plugin>
<!--
Jar 打包插件
Jar 打包插件:
- 使用 maven-jar-plugin 将编译产物打包成可执行 JAR
- 在 MANIFEST 中指定主类,支持命令行直接 java -jar 调用
-->
@ -71,7 +71,7 @@
<profiles>
<!--
原生镜像构建Linux 平台
原生镜像构建: Linux 平台
- 使用 GraalVM 的 native-image 工具,生成静态链接的可执行文件
- 依赖 musl libc需提前安装并配置 musl-gcc 工具链
-->
@ -133,7 +133,7 @@
</profile>
<!--
原生镜像构建Windows 平台
原生镜像构建: Windows 平台
- 使用 GraalVM 的 native-image 工具,生成 Windows 可执行文件
- Windows 上不使用 musl因此不配置静态链接
-->

View File

@ -13,13 +13,13 @@ import java.nio.file.Path;
import java.nio.file.Paths;
/**
* CLI 命令构建当前项目包含依赖解析编译打包
* CLI 命令: 构建当前项目包含依赖解析编译打包
* <p>
* 该命令会依次执行依赖解析源码编译和产物打包阶段
* </p>
*
* <pre>
* 用法示例
* 用法示例:
* $ snow build
* </pre>
*/

View File

@ -6,13 +6,13 @@ import org.jcnc.snow.pkg.lifecycle.LifecyclePhase;
import org.jcnc.snow.pkg.tasks.CleanTask;
/**
* CLI 命令清理构建输出和本地缓存目录
* CLI 命令: 清理构建输出和本地缓存目录
* <p>
* 用于清除项目生成的 builddist 等中间产物保持工作区整洁
* </p>
*
* <pre>
* 用法示例
* 用法示例:
* $ snow clean
* </pre>
*/

View File

@ -13,17 +13,17 @@ import java.util.Collections;
import java.util.List;
/**
* CLI 命令编译当前项目
* CLI 命令: 编译当前项目
*
* <p>工作模式说明</p>
* <p>工作模式说明: </p>
* <ul>
* <li><strong>Cloud 模式</strong>
* - 项目根目录存在 {@code project.cloud} 时触发
* - 解析 build 区块自动推导源码目录与输出文件名
* - 用法{@code snow compile [run]}</li>
* - 用法: {@code snow compile [run]}</li>
* <li><strong>Local 模式</strong>
* - 未检测到 {@code project.cloud} 时回退
* - 保持向后兼容{@code snow compile [run] [-o <name>] [-d <srcDir>] [file.snow ]}</li>
* - 保持向后兼容: {@code snow compile [run] [-o <name>] [-d <srcDir>] [file.snow ]}</li>
* </ul>
*
* <p>两种模式均将最终参数交由 {@link CompileTask} 处理</p>
@ -67,12 +67,12 @@ public final class CompileCommand implements CLICommand {
}
}
/* 源码目录build.srcDir -> 默认 src */
/* 源码目录: build.srcDir -> 默认 src */
String srcDir = project.getBuild().get("srcDir", "src");
argList.add("-d");
argList.add(srcDir);
/* 输出名称build.output -> fallback to artifact */
/* 输出名称: build.output -> fallback to artifact */
String output = project.getBuild().get("output", project.getArtifact());
argList.add("-o");
argList.add(output);

View File

@ -12,19 +12,19 @@ import java.nio.file.Path;
import java.nio.file.Paths;
/**
* CLI 命令根据 project.cloud 生成项目目录结构
* CLI 命令: 根据 project.cloud 生成项目目录结构
* <p>
* 负责解析云项目描述文件并通过 {@link GenerateTask}
* INIT 生命周期阶段内生成基础目录结构
* </p>
*
* <pre>
* 用法示例
* 用法示例:
* $ snow generate
* </pre>
*
* <p>
* 注意事项
* 注意事项:
* - 若当前目录不存在 project.cloud则提示用户先执行 `snow init`
* - 执行成功后会输出已创建的目录/文件
* </p>

View File

@ -8,13 +8,13 @@ import java.nio.file.Path;
import java.nio.file.Paths;
/**
* CLI 命令初始化项目配置文件
* CLI 命令: 初始化项目配置文件
* <p>
* 用于快速生成 DSL 配置文件project.cloud
* </p>
*
* <pre>
* 用法示例
* 用法示例:
* $ snow init
* </pre>
*/

View File

@ -8,13 +8,13 @@ import org.jcnc.snow.pkg.resolver.DependencyResolver;
import java.nio.file.Paths;
/**
* CLI 命令解析并下载项目依赖到本地缓存
* CLI 命令: 解析并下载项目依赖到本地缓存
* <p>
* 适用于离线使用和依赖预热场景会自动读取项目描述文件并处理依赖缓存
* </p>
*
* <pre>
* 用法示例
* 用法示例:
* $ snow install
* </pre>
*/

View File

@ -10,14 +10,14 @@ import org.jcnc.snow.pkg.tasks.PublishTask;
import java.nio.file.Paths;
/**
* CLI 命令将已构建的项目包发布到远程仓库
* CLI 命令: 将已构建的项目包发布到远程仓库
* <p>
* 用于持续集成交付或分发场景
* 支持自动读取 DSL 项目描述文件并注册和执行发布生命周期阶段的任务
* </p>
*
* <pre>
* 用法示例
* 用法示例:
* $ snow publish
* </pre>
*/

View File

@ -4,14 +4,14 @@ import org.jcnc.snow.cli.api.CLICommand;
import org.jcnc.snow.pkg.tasks.RunTask;
/**
* CLI 命令运行已编译的 VM 字节码文件.water
* CLI 命令: 运行已编译的 VM 字节码文件.water
* <p>
* 仅解析参数并委托给 {@link RunTask}
* VM 运行逻辑下沉至 pkg 保持 CLI 无状态薄封装
* </p>
*
* <pre>
* 用法示例
* 用法示例:
* $ snow run main.water
* </pre>
*/

View File

@ -4,13 +4,13 @@ import org.jcnc.snow.cli.SnowCLI;
import org.jcnc.snow.cli.api.CLICommand;
/**
* CLI 子命令输出当前 Snow 工具的版本号
* CLI 子命令: 输出当前 Snow 工具的版本号
* <p>
* 用于显示当前 CLI 工具版本便于诊断升级兼容性确认等场景
* </p>
*
* <pre>
* 用法示例
* 用法示例:
* $ snow version
* </pre>
*/

View File

@ -15,7 +15,7 @@ import java.util.Map;
* 各虚拟寄存器实际对应的物理寄存器或栈槽号采用简单的线性扫描分配策略
* </p>
* <p>
* 分配过程如下
* 分配过程如下:
* <ol>
* <li>优先为函数参数分配槽号 0 开始按参数顺序递增</li>
* <li>遍历函数体的每条指令为尚未分配的目标寄存器及其操作数分配新的槽号</li>
@ -28,8 +28,8 @@ public final class RegisterAllocator {
/**
* 虚拟寄存器到槽号的分配映射表
* <p>
* 虚拟寄存器 {@link IRVirtualRegister}
* 对应分配的槽编号 {@link Integer}
* : 虚拟寄存器 {@link IRVirtualRegister}
* : 对应分配的槽编号 {@link Integer}
* </p>
*/
private final Map<IRVirtualRegister, Integer> map = new HashMap<>();
@ -37,7 +37,7 @@ public final class RegisterAllocator {
/**
* 为指定 IR 函数分配所有虚拟寄存器的槽号
* <p>
* 分配顺序说明
* 分配顺序说明:
* <ol>
* <li>首先为所有参数分配槽号</li>
* <li>然后线性遍历函数体为每个指令涉及的虚拟寄存器目标或操作数分配槽号

View File

@ -16,7 +16,7 @@ import java.util.stream.Collectors;
* 仅负责根据指令类型分发到对应的 {@link InstructionGenerator} 子类完成实际生成
* </p>
* <p>
* 工作流程简述
* 工作流程简述:
* <ol>
* <li>接收一组已注册的 IR 指令生成器并建立类型到生成器的映射表</li>
* <li>遍历 IR 函数体的每条指令根据类型找到对应的生成器调用其 generate 方法生成 VM 指令</li>
@ -28,8 +28,8 @@ public final class VMCodeGenerator {
/**
* 指令类型到生成器的注册表调度表
* <p>
* IR 指令类型Class对象
* 对应的指令生成器实例
* : IR 指令类型Class对象
* : 对应的指令生成器实例
* </p>
*/
private final Map<Class<? extends IRInstruction>, InstructionGenerator<? extends IRInstruction>> registry;

View File

@ -5,7 +5,7 @@ import org.jcnc.snow.vm.engine.VMOpCode;
import java.util.*;
/**
* VMProgramBuilder构建线性 VM 程序即按顺序存放所有 VM 指令
* VMProgramBuilder: 构建线性 VM 程序即按顺序存放所有 VM 指令
* <p>
* 本类用于编译器后端将所有生成的 VM 指令包括分支和调用指令统一存储管理
* 支持符号如函数入口标签地址的延迟解析与回填fix-up机制
@ -22,7 +22,7 @@ public final class VMProgramBuilder {
/** 未解析目标的分支指令JUMP/IC_* 等待修补) */
private record BranchFix(int index, String label) {}
/** 占位符用于表示尚未确定的符号地址 */
/** 占位符: 用于表示尚未确定的符号地址 */
private static final String PLACEHOLDER = "-1";
/** 按顺序存放的 VM 指令文本 */
@ -102,7 +102,7 @@ public final class VMProgramBuilder {
/**
* 生成 CALL 指令
* 支持延迟修补若目标已知直接写入地址否则写入占位并登记 fix-up
* 支持延迟修补: 若目标已知直接写入地址否则写入占位并登记 fix-up
* @param target 目标函数名
* @param nArgs 参数个数
*/

View File

@ -5,22 +5,22 @@
## 项目简介
**后端模块Backend** 是 [Snow 编译器]() 的核心组成部分之一承接中间表示IR与运行时虚拟机VM之间的桥梁。
它主要完成以下工作
它主要完成以下工作:
1. **寄存器分配**将 IR 中的虚拟寄存器映射为物理槽号或栈槽;
2. **指令生成与调度**为每条 IR 指令分配对应的 VM 指令生成器,并负责调用它们输出指令文本;
3. **程序构建**管理函数入口、标签定义、延迟修补fix-upCALL/JUMP 等控制流指令地址;
4. **操作码与常量映射**提供 IR 操作码到 VM 操作码的映射工具,以及根据常量类型选择 PUSH/STORE 指令。
1. **寄存器分配**: 将 IR 中的虚拟寄存器映射为物理槽号或栈槽;
2. **指令生成与调度**: 为每条 IR 指令分配对应的 VM 指令生成器,并负责调用它们输出指令文本;
3. **程序构建**: 管理函数入口、标签定义、延迟修补fix-upCALL/JUMP 等控制流指令地址;
4. **操作码与常量映射**: 提供 IR 操作码到 VM 操作码的映射工具,以及根据常量类型选择 PUSH/STORE 指令。
后端模块设计注重可扩展性各类 IR → VM 的转换逻辑被拆分到不同的 `*Generator` 类中,新增指令只需注册新的生成器;寄存器分配和程序构建也各司其职,职责清晰,便于维护和测试。
后端模块设计注重可扩展性: 各类 IR → VM 的转换逻辑被拆分到不同的 `*Generator` 类中,新增指令只需注册新的生成器;寄存器分配和程序构建也各司其职,职责清晰,便于维护和测试。
## 核心功能
* **线性扫描寄存器分配**`RegisterAllocator` 按参数优先、指令顺序为 IR 虚拟寄存器分配连续槽号。
* **指令生成器体系**`InstructionGenerator<T>` 接口 + 多个 `*Generator` 实现,支持二元运算、跳转、调用、标签、常量加载、一元运算、返回等指令。
* **生成器调度**`VMCodeGenerator` 建立类型到生成器的映射,遍历 IR 函数体并分发调用,实现多态化指令生成。
* **程序构建与延迟修补**`VMProgramBuilder` 维护指令流、符号地址表及待修补列表,实现对 `CALL`/`JUMP` 等指令的延迟地址填充。
* **操作码与常量映射**`IROpCodeMapper` 提供 IR 操作码到 VM 指令名的静态映射;`OpHelper` 基于反射获取 VMOpCode 常量并根据值类型I/L/F…选择合适的 PUSH/STORE 操作码。
* **线性扫描寄存器分配**: `RegisterAllocator` 按参数优先、指令顺序为 IR 虚拟寄存器分配连续槽号。
* **指令生成器体系**: `InstructionGenerator<T>` 接口 + 多个 `*Generator` 实现,支持二元运算、跳转、调用、标签、常量加载、一元运算、返回等指令。
* **生成器调度**: `VMCodeGenerator` 建立类型到生成器的映射,遍历 IR 函数体并分发调用,实现多态化指令生成。
* **程序构建与延迟修补**: `VMProgramBuilder` 维护指令流、符号地址表及待修补列表,实现对 `CALL`/`JUMP` 等指令的延迟地址填充。
* **操作码与常量映射**: `IROpCodeMapper` 提供 IR 操作码到 VM 指令名的静态映射;`OpHelper` 基于反射获取 VMOpCode 常量并根据值类型I/L/F…选择合适的 PUSH/STORE 操作码。
## 模块结构
@ -51,6 +51,6 @@ backend/
* JDK 24 或更高版本
* Maven 构建管理
* 推荐 IDEIntelliJ IDEA
* 推荐 IDE: IntelliJ IDEA
---

View File

@ -20,7 +20,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* 并自动进行类型提升
* 同时实现 "+0 → MOV" Peephole 优化避免多余的 PUSH/ADD 序列
* </p>
* <p>类型提升优先级D &gt; F &gt; L &gt; I &gt; S &gt; B</p>
* <p>类型提升优先级: D &gt; F &gt; L &gt; I &gt; S &gt; B</p>
*/
public class BinaryOpGenerator implements InstructionGenerator<BinaryOperationInstruction> {
@ -143,11 +143,11 @@ public class BinaryOpGenerator implements InstructionGenerator<BinaryOperationIn
// 条件跳转成立 lblTrue
out.emitBranch(branchOp, lblTrue);
// 不成立 0
// 不成立: 0
out.emit(OpHelper.opcode("I_PUSH") + " 0");
out.emitBranch(OpHelper.opcode("JUMP"), lblEnd);
// 成立分支 1
// 成立分支: 1
out.emit(lblTrue + ":");
out.emit(OpHelper.opcode("I_PUSH") + " 1");

View File

@ -47,7 +47,7 @@ public class CmpJumpGenerator implements InstructionGenerator<IRCompareJumpInstr
* </ol>
*
* @param ins IR 条件比较跳转指令
* @param out VMProgramBuilder用于发出 VM 指令
* @param out VMProgramBuilder: 用于发出 VM 指令
* @param slotMap 虚拟寄存器到 VM 槽位的映射表
* @param currentFn 当前处理的函数名调试用当前未使用
*/

View File

@ -20,8 +20,8 @@ public final class IROpCodeMapper {
/**
* IR 操作码到 VM 指令名的静态映射表
* <ul>
* <li>IR 操作码{@link IROpCode} 枚举项</li>
* <li>对应虚拟机指令名字符串</li>
* <li>: IR 操作码{@link IROpCode} 枚举项</li>
* <li>: 对应虚拟机指令名字符串</li>
* </ul>
* 使用 {@link EnumMap}查找和存储高效
*/

View File

@ -1,25 +1,25 @@
package org.jcnc.snow.compiler.backend.utils;
/**
* 工具类提供基本数值类型的提升与类型转换辅助功能
* 工具类: 提供基本数值类型的提升与类型转换辅助功能
* <p>
* 在进行数值类型运算比较等操作时低优先级的类型会被提升为高优先级类型参与运算
* 例如 int + long 运算int 会被提升为 long最终运算结果类型为 long
* <p>
* 类型优先级从高到低依次为
* Ddouble6
* Ffloat 5
* Llong 4
* Iint 3
* Sshort 2
* Bbyte 1
* 未识别类型 0
* 类型优先级从高到低依次为:
* Ddouble: 6
* Ffloat : 5
* Llong : 4
* Iint : 3
* Sshort : 2
* Bbyte : 1
* 未识别类型 : 0
*/
public class TypePromoteUtils {
/**
* 返回数值类型的宽度优先级数值越大类型越宽
* 类型及优先级映射如下
* 类型及优先级映射如下:
* Ddouble: 6
* Ffloat : 5
* Llong : 4
@ -69,8 +69,8 @@ public class TypePromoteUtils {
* 获取类型转换指令名例如 "I2L", "F2D"表示从源类型到目标类型的转换操作
* 如果源类型和目标类型相同则返回 null表示无需转换
* <p>
* 支持的类型标记字符包括BbyteSshortIintLlongFfloatDdouble
* 所有可能的类型转换均已覆盖如下所示
* 支持的类型标记字符包括: BbyteSshortIintLlongFfloatDdouble
* 所有可能的类型转换均已覆盖如下所示:
* B S/I/L/F/D
* S B/I/L/F/D
* I B/S/L/F/D

View File

@ -19,7 +19,7 @@ import java.util.*;
* 该类负责将抽象语法树AST的表达式节点转换为中间表示IR指令和虚拟寄存器
* 是编译器IR生成阶段的核心工具
* <br/>
* 主要职责包括
* 主要职责包括:
* <ul>
* <li>将数字字面量标识符二元表达式函数调用等AST表达式节点翻译为对应的IR指令序列</li>
* <li>管理并分配虚拟寄存器保证IR操作的数据流正确</li>
@ -31,19 +31,19 @@ public record ExpressionBuilder(IRContext ctx) {
/**
* 构建并返回某个表达式节点对应的虚拟寄存器
*
* <p>会根据节点的实际类型分别处理
* <p>会根据节点的实际类型分别处理:
* <ul>
* <li>数字字面量新建常量寄存器</li>
* <li>布尔字面量生成值为 0 1 的常量寄存器</li>
* <li>标识符查找当前作用域中的寄存器</li>
* <li>二元表达式递归处理子表达式并进行相应运算</li>
* <li>一元运算符
* <li>数字字面量: 新建常量寄存器</li>
* <li>布尔字面量: 生成值为 0 1 的常量寄存器</li>
* <li>标识符: 查找当前作用域中的寄存器</li>
* <li>二元表达式: 递归处理子表达式并进行相应运算</li>
* <li>一元运算符:
* <ul>
* <li><code>-x</code>取负生成 <code>NEG_I32</code> 指令</li>
* <li>code>!x</code>逻辑非转换为 <code>x == 0</code> 比较指令</li>
* </ul>
* </li>
* <li>函数调用生成对应的Call指令</li>
* <li>函数调用: 生成对应的Call指令</li>
* <li>其它类型不支持抛出异常</li>
* </ul>
*

View File

@ -19,7 +19,7 @@ public class FunctionBuilder {
/**
* AST 中的 FunctionNode 构建为可执行的 IRFunction
* <p>
* 构建过程包括
* 构建过程包括:
* <ol>
* <li>初始化 IRFunction 实例和上下文</li>
* <li>根据函数返回类型设置默认类型后缀便于表达式推断</li>
@ -37,7 +37,7 @@ public class FunctionBuilder {
GlobalFunctionTable.register(functionNode.name(), functionNode.returnType());
// 0) 基本初始化创建 IRFunction 实例与对应上下文
// 0) 基本初始化: 创建 IRFunction 实例与对应上下文
IRFunction irFunction = new IRFunction(functionNode.name());
IRContext irContext = new IRContext(irFunction);
@ -53,14 +53,14 @@ public class FunctionBuilder {
ExpressionUtils.setDefaultSuffix(_returnSuffix);
try {
// 2) 声明形参为每个参数分配虚拟寄存器并声明到作用域
// 2) 声明形参: 为每个参数分配虚拟寄存器并声明到作用域
for (ParameterNode p : functionNode.parameters()) {
IRVirtualRegister reg = irFunction.newRegister(); // 新寄存器
irContext.getScope().declare(p.name(), p.type(), reg); // 变量名寄存器绑定
irFunction.addParameter(reg); // 添加到函数参数列表
}
// 3) 生成函数体 IR遍历每条语句逐一转化
// 3) 生成函数体 IR: 遍历每条语句逐一转化
StatementBuilder stmtBuilder = new StatementBuilder(irContext);
for (StatementNode stmt : functionNode.body()) {
stmtBuilder.build(stmt);

View File

@ -9,7 +9,7 @@ import java.util.Map;
/**
* IRBuilderScope 用于管理单个函数内变量名与虚拟寄存器的映射关系
*
* <p>主要功能包括
* <p>主要功能包括:
* <ul>
* <li>维护在当前作用域中已声明变量的寄存器分配信息</li>
* <li>支持将已有虚拟寄存器与变量名重新绑定</li>

View File

@ -10,7 +10,7 @@ import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
* 以及与之配套的作用域管理IRBuilderScope
* 并简化虚拟寄存器分配与 IR 指令添加操作
*
* <p>本类提供以下核心功能
* <p>本类提供以下核心功能:
* <ul>
* <li>持有并操作当前 IRFunction 对象</li>
* <li>管理变量名与虚拟寄存器的映射关系</li>
@ -62,7 +62,7 @@ public class IRContext {
/**
* 获取当前函数的变量与寄存器映射作用域
*
* <p>包内可见仅限 builder 包内部使用
* <p>包内可见: 仅限 builder 包内部使用
*
* @return IRBuilderScope 实例
*/

View File

@ -13,7 +13,7 @@ import java.util.List;
/**
* 本类负责将解析生成的 AST 根节点列表转换为可执行的 IRProgram
*
* <p>主要职责
* <p>主要职责:
* <ul>
* <li>遍历输入的顶层节点识别 ModuleNodeFunctionNode 及脚本式顶层 StatementNode</li>
* <li> ModuleNode 中的所有函数节点调用 FunctionBuilder 构建 IRFunction 并添加至 IRProgram</li>
@ -36,13 +36,13 @@ public final class IRProgramBuilder {
for (Node node : roots) {
switch (node) {
case ModuleNode moduleNode ->
// 模块节点批量构建并添加模块内所有函数
// 模块节点: 批量构建并添加模块内所有函数
moduleNode.functions().forEach(f -> irProgram.add(buildFunction(f)));
case FunctionNode functionNode ->
// 顶层函数节点直接构建并添加
// 顶层函数节点: 直接构建并添加
irProgram.add(buildFunction(functionNode));
case StatementNode statementNode ->
// 脚本式顶层语句封装为_start函数后构建并添加
// 脚本式顶层语句: 封装为_start函数后构建并添加
irProgram.add(buildFunction(wrapTopLevel(statementNode)));
default ->
// 严格校验节点类型遇不支持者立即失败
@ -65,7 +65,7 @@ public final class IRProgramBuilder {
/**
* 将单个脚本式顶层 StatementNode 封装为名称固定的_start函数节点
*
* <p>封装规则
* <p>封装规则:
* <ul>
* <li>函数名固定为_start</li>
* <li>返回类型设为 null由后续流程处理</li>

View File

@ -80,7 +80,7 @@ public class InstructionFactory {
/**
* Move 指令src dest若寄存器相同也安全
* <p>
* 实现方式dest = src + 0即加上常量 0
* 实现方式: dest = src + 0即加上常量 0
* </p>
*
* @param ctx 当前 IR 上下文
@ -92,7 +92,7 @@ public class InstructionFactory {
if (src == dest) {
return;
}
// 回退实现dest = src + 0
// 回退实现: dest = src + 0
IRVirtualRegister zero = loadConst(ctx, 0);
ctx.addInstruction(new BinaryOperationInstruction(IROpCode.ADD_I32, dest, src, zero));
}

View File

@ -150,7 +150,7 @@ public class StatementBuilder {
/**
* 构建循环语句for/while
* 处理流程初始语句 条件判断 循环体 更新语句 跳回条件
* 处理流程: 初始语句 条件判断 循环体 更新语句 跳回条件
*
* @param loop 循环节点
*/
@ -176,7 +176,7 @@ public class StatementBuilder {
/**
* 构建分支语句if/else
* 处理流程条件判断 then 分支 else 分支可选
* 处理流程: 条件判断 then 分支 else 分支可选
*
* @param ifNode if 语句节点
*/

View File

@ -22,8 +22,8 @@ public final class GlobalFunctionTable {
/**
* 存储全局函数返回类型映射表
* <ul>
* <li>Key函数名不含模块限定</li>
* <li>Value返回类型统一转换为小写字符串若无返回值则为 {@code "void"}</li>
* <li>Key: 函数名不含模块限定</li>
* <li>Value: 返回类型统一转换为小写字符串若无返回值则为 {@code "void"}</li>
* </ul>
*/
private static final Map<String, String> RETURN_TYPES = new ConcurrentHashMap<>();

View File

@ -112,7 +112,7 @@ public class IRFunction {
}
/**
* 以IR代码表示示例
* 以IR代码表示示例:
* <pre>
* func 名称(%0, %1, ...) {
* 指令0

View File

@ -24,95 +24,95 @@ public enum IROpCode {
CONV_D64_TO_F32,
/* ───── 算术运算8位整数byte───── */
ADD_B8, // 8位整型加法a = b + c
SUB_B8, // 8位整型减法a = b - c
MUL_B8, // 8位整型乘法a = b * c
DIV_B8, // 8位整型除法a = b / c
NEG_B8, // 8位整型取负a = -b
/* ───── 算术运算8位整数: byte───── */
ADD_B8, // 8位整型加法: a = b + c
SUB_B8, // 8位整型减法: a = b - c
MUL_B8, // 8位整型乘法: a = b * c
DIV_B8, // 8位整型除法: a = b / c
NEG_B8, // 8位整型取负: a = -b
/* ───── 算术运算16位整数short───── */
/* ───── 算术运算16位整数: short───── */
ADD_S16, // 16位整型加法
SUB_S16, // 16位整型减法
MUL_S16, // 16位整型乘法
DIV_S16, // 16位整型除法
NEG_S16, // 16位整型取负
/* ───── 算术运算32位整数int───── */
/* ───── 算术运算32位整数: int───── */
ADD_I32, // 32位整型加法
SUB_I32, // 32位整型减法
MUL_I32, // 32位整型乘法
DIV_I32, // 32位整型除法
NEG_I32, // 32位整型取负
/* ───── 算术运算64位整数long───── */
/* ───── 算术运算64位整数: long───── */
ADD_L64, // 64位整型加法
SUB_L64, // 64位整型减法
MUL_L64, // 64位整型乘法
DIV_L64, // 64位整型除法
NEG_L64, // 64位整型取负
/* ───── 算术运算32位浮点数float───── */
/* ───── 算术运算32位浮点数: float───── */
ADD_F32, // 32位浮点加法
SUB_F32, // 32位浮点减法
MUL_F32, // 32位浮点乘法
DIV_F32, // 32位浮点除法
NEG_F32, // 32位浮点取负
/* ───── 算术运算64位浮点数double───── */
/* ───── 算术运算64位浮点数: double───── */
ADD_D64, // 64位浮点加法
SUB_D64, // 64位浮点减法
MUL_D64, // 64位浮点乘法
DIV_D64, // 64位浮点除法
NEG_D64, // 64位浮点取负
/* ───── 逻辑与比较运算指令8位整数byte ───── */
CMP_BEQ, // 8位整数相等比较a == b
CMP_BNE, // 8位整数不等比较a != b
CMP_BLT, // 8位整数小于比较a < b
CMP_BGT, // 8位整数大于比较a > b
CMP_BLE, // 8位整数小于等于a <= b
CMP_BGE, // 8位整数大于等于a >= b
/* ───── 逻辑与比较运算指令8位整数: byte ───── */
CMP_BEQ, // 8位整数相等比较: a == b
CMP_BNE, // 8位整数不等比较: a != b
CMP_BLT, // 8位整数小于比较: a < b
CMP_BGT, // 8位整数大于比较: a > b
CMP_BLE, // 8位整数小于等于: a <= b
CMP_BGE, // 8位整数大于等于: a >= b
/* ───── 逻辑与比较运算指令16位整数int ───── */
CMP_SEQ, // 16位整数相等比较a == b
CMP_SNE, // 16位整数不等比较a != b
CMP_SLT, // 16位整数小于比较a < b
CMP_SGT, // 16位整数大于比较a > b
CMP_SLE, // 16位整数小于等于a <= b
CMP_SGE, // 16位整数大于等于a >= b
/* ───── 逻辑与比较运算指令16位整数: int ───── */
CMP_SEQ, // 16位整数相等比较: a == b
CMP_SNE, // 16位整数不等比较: a != b
CMP_SLT, // 16位整数小于比较: a < b
CMP_SGT, // 16位整数大于比较: a > b
CMP_SLE, // 16位整数小于等于: a <= b
CMP_SGE, // 16位整数大于等于: a >= b
/* ───── 逻辑与比较运算指令32位整数int ───── */
CMP_IEQ, // 32位整数相等比较a == b
CMP_INE, // 32位整数不等比较a != b
CMP_ILT, // 32位整数小于比较a < b
CMP_IGT, // 32位整数大于比较a > b
CMP_ILE, // 32位整数小于等于a <= b
CMP_IGE, // 32位整数大于等于a >= b
/* ───── 逻辑与比较运算指令32位整数: int ───── */
CMP_IEQ, // 32位整数相等比较: a == b
CMP_INE, // 32位整数不等比较: a != b
CMP_ILT, // 32位整数小于比较: a < b
CMP_IGT, // 32位整数大于比较: a > b
CMP_ILE, // 32位整数小于等于: a <= b
CMP_IGE, // 32位整数大于等于: a >= b
/* ───── 逻辑与比较运算指令64位整数long ───── */
CMP_LEQ, // 64位整数相等比较a == b
CMP_LNE, // 64位整数不等比较a != b
CMP_LLT, // 64位整数小于比较a < b
CMP_LGT, // 64位整数大于比较a > b
CMP_LLE, // 64位整数小于等于a <= b
CMP_LGE, // 64位整数大于等于a >= b
/* ───── 逻辑与比较运算指令64位整数: long ───── */
CMP_LEQ, // 64位整数相等比较: a == b
CMP_LNE, // 64位整数不等比较: a != b
CMP_LLT, // 64位整数小于比较: a < b
CMP_LGT, // 64位整数大于比较: a > b
CMP_LLE, // 64位整数小于等于: a <= b
CMP_LGE, // 64位整数大于等于: a >= b
/* ───── 逻辑与比较运算指令32位浮点数float ───── */
CMP_FEQ, // 32位浮点相等比较a == b
CMP_FNE, // 32位浮点不等比较a != b
CMP_FLT, // 32位浮点小于比较a < b
CMP_FGT, // 32位浮点大于比较a > b
CMP_FLE, // 32位浮点小于等于a <= b
CMP_FGE, // 32位浮点大于等于a >= b
/* ───── 逻辑与比较运算指令32位浮点数: float ───── */
CMP_FEQ, // 32位浮点相等比较: a == b
CMP_FNE, // 32位浮点不等比较: a != b
CMP_FLT, // 32位浮点小于比较: a < b
CMP_FGT, // 32位浮点大于比较: a > b
CMP_FLE, // 32位浮点小于等于: a <= b
CMP_FGE, // 32位浮点大于等于: a >= b
/* ───── 逻辑与比较运算指令64位浮点数double ───── */
CMP_DEQ, // 64位浮点相等比较a == b
CMP_DNE, // 64位浮点不等比较a != b
CMP_DLT, // 64位浮点小于比较a < b
CMP_DGT, // 64位浮点大于比较a > b
CMP_DLE, // 64位浮点小于等于a <= b
CMP_DGE, // 64位浮点大于等于a >= b
/* ───── 逻辑与比较运算指令64位浮点数: double ───── */
CMP_DEQ, // 64位浮点相等比较: a == b
CMP_DNE, // 64位浮点不等比较: a != b
CMP_DLT, // 64位浮点小于比较: a < b
CMP_DGT, // 64位浮点大于比较: a > b
CMP_DLE, // 64位浮点小于等于: a <= b
CMP_DGE, // 64位浮点大于等于: a >= b
/* ───── 数据访问与常量操作 ───── */
LOAD, // 从内存加载数据至寄存器

View File

@ -11,11 +11,11 @@ import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
* 实现该接口的类型可以作为 {@link IRInstruction} 中的操作数出现
* </p>
*
* <p>当前支持的 IR 值类型包括</p>
* <p>当前支持的 IR 值类型包括: </p>
* <ul>
* <li>{@link IRVirtualRegister}虚拟寄存器表示计算结果或中间变量</li>
* <li>{@link IRConstant}常量值表示不可变的字面量或数值</li>
* <li>{@link IRLabel}标签表示跳转指令的目标地址</li>
* <li>{@link IRVirtualRegister}: 虚拟寄存器表示计算结果或中间变量</li>
* <li>{@link IRConstant}: 常量值表示不可变的字面量或数值</li>
* <li>{@link IRLabel}: 标签表示跳转指令的目标地址</li>
* </ul>
*
* <p>

View File

@ -7,12 +7,12 @@ import org.jcnc.snow.compiler.ir.instruction.*;
* <p>
* 它定义了访问者模式的核心机制通过对每种 {@link IRInstruction} 子类
* 提供独立的 {@code visit} 方法实现对指令的分发与处理
* 不同的访问者实现可用于执行不同任务例如
* 不同的访问者实现可用于执行不同任务例如:
* </p>
* <ul>
* <li>{@code IRPrinter}打印指令内容</li>
* <li>{@code IROptimizer}分析与重写 IR 以优化性能</li>
* <li>{@code IRCodeGenerator}生成平台相关的机器码或汇编代码</li>
* <li>{@code IRPrinter}: 打印指令内容</li>
* <li>{@code IROptimizer}: 分析与重写 IR 以优化性能</li>
* <li>{@code IRCodeGenerator}: 生成平台相关的机器码或汇编代码</li>
* </ul>
*
* <p>

View File

@ -11,27 +11,27 @@ IR 模块以类 SSAStatic Single Assignment形式设计通过统一的
## 核心功能
* **统一的中间表示模型**表达控制流与数据流,支持函数、指令、值等核心结构
* **IR 构建器体系**模块化构建函数、表达式与语句 IR简化前端对接
* **灵活的指令层级结构**支持二元操作、跳转、返回等多种基本指令
* **寄存器与常量模型**统一管理虚拟寄存器、常量、标签等值类型
* **IR 打印与调试支持**辅助输出 IR 文本格式,支持可视化与调试
* **统一的中间表示模型**: 表达控制流与数据流,支持函数、指令、值等核心结构
* **IR 构建器体系**: 模块化构建函数、表达式与语句 IR简化前端对接
* **灵活的指令层级结构**: 支持二元操作、跳转、返回等多种基本指令
* **寄存器与常量模型**: 统一管理虚拟寄存器、常量、标签等值类型
* **IR 打印与调试支持**: 辅助输出 IR 文本格式,支持可视化与调试
## 模块结构
```
ir/
├── builder/ // 构建器模块负责构造表达式、函数与语句的 IR
├── core/ // 核心定义IR 基础结构,如函数、指令、程序、访问器等
├── instruction/ // 指令实现具体的 IR 指令类型(如加法、跳转、返回等)
├── utils/ // 工具模块提供 IR 操作相关的辅助函数(如表达式工具、操作码工具等)
└── value/ // 值模型常量、标签、虚拟寄存器等
├── builder/ // 构建器模块: 负责构造表达式、函数与语句的 IR
├── core/ // 核心定义: IR 基础结构,如函数、指令、程序、访问器等
├── instruction/ // 指令实现: 具体的 IR 指令类型(如加法、跳转、返回等)
├── utils/ // 工具模块: 提供 IR 操作相关的辅助函数(如表达式工具、操作码工具等)
└── value/ // 值模型: 常量、标签、虚拟寄存器等
```
## 开发环境
* JDK 24 或更高版本
* Maven 构建管理
* 推荐 IDEIntelliJ IDEA
* 推荐 IDE: IntelliJ IDEA
---

View File

@ -9,7 +9,7 @@ import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
import java.util.List;
/**
* BinaryOperationInstruction 表示一个二元运算指令格式为dest = lhs OP rhs
* BinaryOperationInstruction 表示一个二元运算指令格式为: dest = lhs OP rhs
* <p>
* 该类用于描述形如 a = b + c a = x * y 的二元运算指令
* 运算类型OP {@link IROpCode} 指定包括加法减法乘法除法等
@ -76,7 +76,7 @@ public final class BinaryOperationInstruction extends IRInstruction {
/**
* 转换为字符串格式便于调试与打印
* v1 = ADD_I32 v2, v3
* : v1 = ADD_I32 v2, v3
*
* @return 指令的字符串表示形式
*/

View File

@ -46,7 +46,7 @@ public class CallInstruction extends IRInstruction {
return isVoidReturn() ? null : dest;
}
/** 操作数列表void 调用不包含 dest */
/** 操作数列表: void 调用不包含 dest */
@Override
public List<IRValue> operands() {
List<IRValue> ops = new ArrayList<>();

View File

@ -9,7 +9,7 @@ import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
import java.util.List;
/**
* IRAddInstruction 表示一个加法指令形如dest = lhs + rhs
* IRAddInstruction 表示一个加法指令形如: dest = lhs + rhs
* <p>
* 本类是一个具体的 IRInstruction 子类表示将两个值相加并将结果写入目标寄存器的操作
* 虽然功能与通用的 {@link BinaryOperationInstruction} 类似但它作为更简化明确的指令实现
@ -40,7 +40,7 @@ public class IRAddInstruction extends IRInstruction {
}
/**
* 返回该指令的操作码ADD_I32
* 返回该指令的操作码: ADD_I32
*
* @return 加法操作码
*/
@ -81,7 +81,7 @@ public class IRAddInstruction extends IRInstruction {
/**
* 返回指令的字符串形式方便调试
* 例如v1 = v2 + v3
* 例如: v1 = v2 + v3
*
* @return 字符串表示形式
*/

View File

@ -6,7 +6,7 @@ import org.jcnc.snow.compiler.ir.core.IRVisitor;
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
/**
* 比较 + 条件跳转 复合指令
* 比较 + 条件跳转 复合指令:
* if ( left <cmpOp> right ) jump targetLabel;
* <p>
* 其中 cmpOp 只能是 IROpCode.CMP_* 六种比较操作码

View File

@ -25,7 +25,7 @@ public class IRJumpInstruction extends IRInstruction {
}
/**
* 获取该指令对应的操作码JUMP
* 获取该指令对应的操作码: JUMP
*
* @return IROpCode.JUMP
*/
@ -55,7 +55,7 @@ public class IRJumpInstruction extends IRInstruction {
/**
* 将指令转为字符串形式便于打印与调试
* 例如jump L1
* 例如: jump L1
*
* @return 指令的字符串表示
*/

View File

@ -29,7 +29,7 @@ public class IRReturnInstruction extends IRInstruction {
}
/**
* 获取该指令的操作码RET
* 获取该指令的操作码: RET
*
* @return IROpCode.RET表示返回操作
*/
@ -60,7 +60,7 @@ public class IRReturnInstruction extends IRInstruction {
/**
* 转换为字符串形式便于调试与打印
* 示例ret v1
* 示例: ret v1
*
* @return 字符串形式的返回指令
*/

View File

@ -10,7 +10,7 @@ import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
import java.util.List;
/**
* LoadConstInstruction 表示一个常量加载指令格式为dest = CONST k
* LoadConstInstruction 表示一个常量加载指令格式为: dest = CONST k
* <p>
* 该指令的功能是将一个常量字面量或编译期已知值加载到一个虚拟寄存器中
* 供后续指令使用例如在表达式计算参数传递初始化等场景中常用
@ -66,7 +66,7 @@ public final class LoadConstInstruction extends IRInstruction {
/**
* 返回该指令的字符串形式便于调试或打印
* 例如v1 = CONST 42
* 例如: v1 = CONST 42
*
* @return 指令的字符串表示
*/

View File

@ -9,11 +9,11 @@ import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
import java.util.List;
/**
* ReturnInstruction 表示函数返回指令格式RET RET <value>
* ReturnInstruction 表示函数返回指令格式: RET RET <value>
* <p>
* 此类用于描述函数执行完毕后的返回操作支持两种返回形式
* - 无返回值void生成无参的 RET 指令
* - 有返回值将指定虚拟寄存器中的值返回给调用者
* 此类用于描述函数执行完毕后的返回操作支持两种返回形式:
* - 无返回值void: 生成无参的 RET 指令
* - 有返回值: 将指定虚拟寄存器中的值返回给调用者
* <p>
* {@link IRReturnInstruction} 类似但更通用适配多种函数返回风格
*/
@ -36,7 +36,7 @@ public final class ReturnInstruction extends IRInstruction {
}
/**
* 返回该指令的操作码类型RET
* 返回该指令的操作码类型: RET
*
* @return IROpCode.RET
*/
@ -68,8 +68,8 @@ public final class ReturnInstruction extends IRInstruction {
/**
* 转换为字符串形式便于调试与输出
* - 无返回值RET
* - 有返回值RET v1
* - 无返回值: RET
* - 有返回值: RET v1
*
* @return 字符串表示的返回指令
*/

View File

@ -9,14 +9,14 @@ import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
import java.util.List;
/**
* UnaryOperationInstruction 表示一个一元运算指令格式dest = OP val
* UnaryOperationInstruction 表示一个一元运算指令格式: dest = OP val
* <p>
* 用于对单个操作数 val 执行指定的一元运算 OP例如取负 NEG
* 并将结果写入目标虚拟寄存器 dest
* <p>
* 支持的操作由 {@link IROpCode} 定义目前常见的一元操作包括
* 支持的操作由 {@link IROpCode} 定义目前常见的一元操作包括:
* <ul>
* <li>NEG_I32 整数取负dest = -val</li>
* <li>NEG_I32 整数取负: dest = -val</li>
* <li>可扩展逻辑非按位非等</li>
* </ul>
*/
@ -76,7 +76,7 @@ public final class UnaryOperationInstruction extends IRInstruction {
/**
* 将该指令格式化为字符串便于打印与调试
* 形式dest = OP val例如v1 = NEG v2
* 形式: dest = OP val例如: v1 = NEG v2
*
* @return 字符串形式的指令
*/

View File

@ -16,11 +16,11 @@ import java.util.Map;
* 支持自动类型提升保证 intlongfloatdouble 等类型的比较均能得到正确的 IR 指令
* </p>
*
* 类型判定支持
* 类型判定支持:
* <ul>
* <li>字面量后缀支持 B/S/I/L/F/D大小写均可</li>
* <li>浮点数支持如无后缀但有小数点视为 double</li>
* <li>变量类型根据传入变量表推断类型未识别则默认 int</li>
* <li>字面量后缀: 支持 B/S/I/L/F/D大小写均可</li>
* <li>浮点数支持: 如无后缀但有小数点视为 double</li>
* <li>变量类型: 根据传入变量表推断类型未识别则默认 int</li>
* </ul>
*/
public final class ComparisonUtils {
@ -39,7 +39,7 @@ public final class ComparisonUtils {
}
/**
* 返回类型宽度优先级越大代表类型越宽类型对应的优先级
* 返回类型宽度优先级越大代表类型越宽类型对应的优先级:
* - D (double): 6
* - F (float): 5
* - L (long): 4
@ -106,7 +106,7 @@ public final class ComparisonUtils {
}
/**
* 内部工具方法根据表达式节点和变量表推断类型标记字符
* 内部工具方法: 根据表达式节点和变量表推断类型标记字符
* 字面量支持 B/S/I/L/F/D大小写均可浮点数默认 double
* 标识符类型按变量表映射未知则默认 int
*

View File

@ -14,7 +14,7 @@ import java.util.Map;
/**
* 表达式分析与操作符选择工具类
* <p>
* 主要功能
* 主要功能:
* - 解析字面量常量自动推断类型
* - 自动匹配并选择适合的算术/比较操作码
* - 表达式类型的合并与类型提升
@ -138,7 +138,7 @@ public final class ExpressionUtils {
}
/**
* 兼容旧逻辑仅凭操作符直接返回 int32 比较指令
* 兼容旧逻辑: 仅凭操作符直接返回 int32 比较指令
*
* @param op 比较操作符
* @return int32 类型的比较操作码
@ -148,7 +148,7 @@ public final class ExpressionUtils {
}
/**
* 推荐调用根据左右表达式类型自动选择 int/long/float/double 等合适的比较操作码
* 推荐调用: 根据左右表达式类型自动选择 int/long/float/double 等合适的比较操作码
*
* @param variables 变量名到类型的映射
* @param op 比较符号
@ -196,7 +196,7 @@ public final class ExpressionUtils {
/**
* 返回两个类型后缀中的最大类型宽度优先
* 优先级d > f > l > i > s > b > '\0'
* 优先级: d > f > l > i > s > b > '\0'
*
* @param l 类型后缀1
* @param r 类型后缀2

View File

@ -9,18 +9,18 @@ import org.jcnc.snow.compiler.ir.core.IRValue;
* {@link IRVirtualRegister} 不同常量不需要通过寄存器存储
* 可直接作为 IR 指令的操作数使用
* <p>
* 典型应用
* - 加载常量指令v1 = CONST 42
* - 计算表达式v2 = ADD v1, 100
* 典型应用:
* - 加载常量指令: v1 = CONST 42
* - 计算表达式: v2 = ADD v1, 100
*/
public record IRConstant(Object value) implements IRValue {
/**
* 将常量值转换为字符串用于打印 IR 指令或调试输出
* <p>
* 例如
* - 整数常量42
* - 字符串常量"hello"
* 例如:
* - 整数常量: 42
* - 字符串常量: "hello"
*
* @return 常量的字符串表示
*/

View File

@ -8,11 +8,11 @@ import org.jcnc.snow.compiler.ir.core.IRValue;
* IR 系统中虚拟寄存器用于存储每个中间计算结果 SSAStatic Single Assignment形式的核心
* 每个虚拟寄存器在程序中只被赋值一次其值来源于一条明确的指令输出
* <p>
* 特点
* 特点:
* <ul>
* <li>每个寄存器有唯一编号 {@code id} {@code IRFunction.newRegister()} 自动生成</li>
* <li>实现 {@link IRValue} 接口可作为 IRInstruction 的操作数</li>
* <li>具备良好的打印与调试格式%id</li>
* <li>具备良好的打印与调试格式: %id</li>
* </ul>
*
* 适用于表达式求值参数传递函数返回值临时变量等所有中间值场景
@ -23,7 +23,7 @@ public record IRVirtualRegister(int id) implements IRValue {
/**
* 将虚拟寄存器转换为字符串格式方便输出和调试
* 格式为%<id>例如 %3 表示编号为 3 的虚拟寄存器
* 格式为: %<id>例如 %3 表示编号为 3 的虚拟寄存器
*
* @return 格式化的字符串表示
*/

View File

@ -9,7 +9,7 @@ import org.jcnc.snow.compiler.lexer.base.TokenScanner;
* {@link TokenScanner} 实现进行词法识别的基础设施
* </p>
* <p>
* 设计要点
* 设计要点:
* <ul>
* <li>构造时统一将 Windows 换行符 (<code>\r\n</code>) 转换为 Unix 风格 (<code>\n</code>)</li>
* <li>所有坐标均以 <strong>1</strong> 为起始行列号更贴合人类直觉</li>

View File

@ -12,7 +12,7 @@ import java.util.List;
/**
* Snow 语言词法分析器核心实现
* <p>采用<b>先扫描 后批量校验 统一报告</b>策略
* <p>采用<b>先扫描 后批量校验 统一报告</b>策略:
* <ol>
* <li>{@link #scanAllTokens()} 用扫描器链把字符流拆成 {@link Token}</li>
* <li>{@link #validateTokens()} 基于 token 序列做轻量上下文校验</li>
@ -68,7 +68,7 @@ public class LexerEngine {
System.out.println("\n## 词法分析通过,没有发现错误\n");
return;
}
System.err.println("\n词法分析发现 " + errors.size() + " 个错误");
System.err.println("\n词法分析发现 " + errors.size() + " 个错误: ");
errors.forEach(e -> System.err.println(" " + e));
}
@ -76,7 +76,7 @@ public class LexerEngine {
public List<LexicalError> getErrors() { return List.copyOf(errors); }
/**
* 逐字符扫描依次尝试各扫描器扫描器抛出的
* 逐字符扫描: 依次尝试各扫描器扫描器抛出的
* {@link LexicalException} 被捕获并转为 {@link LexicalError}
*/
private void scanAllTokens() {
@ -105,7 +105,7 @@ public class LexerEngine {
}
/**
* 目前包含三条规则<br>
* 目前包含三条规则: <br>
* 1. Dot-Prefix'.' 不能作标识符前缀<br>
* 2. Declare-Ident declare 后必须紧跟合法标识符并且只能一个<br>
* 3. Double-Ident declare 后若出现第二个 IDENTIFIER 视为多余<br>
@ -149,6 +149,6 @@ public class LexerEngine {
/** 构造统一的 LexicalError */
private LexicalError err(Token t, String msg) {
return new LexicalError(absPath, t.getLine(), t.getCol(), "非法的标记序列" + msg);
return new LexicalError(absPath, t.getLine(), t.getCol(), "非法的标记序列: " + msg);
}
}

View File

@ -10,8 +10,8 @@ package org.jcnc.snow.compiler.lexer.core;
* <li>完全禁止 Java 堆栈信息输出使命令行输出保持整洁</li>
* </ul>
* <pre>
*
* Main.snow: 7, 20: 词法错误非法字符序列 '@'
* :
* Main.snow: 7, 20: 词法错误: 非法字符序列 '@'
* </pre>
*/
public class LexicalException extends RuntimeException {
@ -24,7 +24,7 @@ public class LexicalException extends RuntimeException {
/**
* 构造词法异常
* @param reason 错误原因非法字符描述
* @param reason 错误原因: 非法字符描述
* @param line 出错行号
* @param column 出错列号
*/

View File

@ -11,11 +11,11 @@
## 核心功能
- **词法分析引擎**从源代码提取标准化 Token 流
- **模块化扫描器体系**按需扩展不同类型的 Token 识别
- **灵活的上下文管理**跟踪源代码位置,支持错误处理
- **统一的 Token 工厂**集中创建 Token 实例
- **工具支持**Token 打印与调试辅助
- **词法分析引擎**: 从源代码提取标准化 Token 流
- **模块化扫描器体系**: 按需扩展不同类型的 Token 识别
- **灵活的上下文管理**: 跟踪源代码位置,支持错误处理
- **统一的 Token 工厂**: 集中创建 Token 实例
- **工具支持**: Token 打印与调试辅助
## 模块结构
@ -33,6 +33,6 @@ lexer/
* JDK 24 或更高版本
* Maven 构建管理
* 推荐 IDEIntelliJ IDEA
* 推荐 IDE: IntelliJ IDEA
---

View File

@ -35,7 +35,7 @@ public abstract class AbstractTokenScanner implements TokenScanner {
}
/**
* 抽象方法由子类实现具体的扫描逻辑
* 抽象方法: 由子类实现具体的扫描逻辑
* <p>
* 实现应消费一定字符并根据规则构造 Token
* 若无需生成 Token可返回 null
@ -49,7 +49,7 @@ public abstract class AbstractTokenScanner implements TokenScanner {
protected abstract Token scanToken(LexerContext ctx, int line, int col);
/**
* 工具方法连续读取字符直到遇到不满足指定条件的字符
* 工具方法: 连续读取字符直到遇到不满足指定条件的字符
*
* @param ctx 当前词法上下文
* @param predicate 字符匹配条件

View File

@ -8,17 +8,17 @@ import org.jcnc.snow.compiler.lexer.token.TokenType;
/**
* {@code CommentTokenScanner} 注释解析器基于有限状态机FSM
*
* <p>负责将源码中的两种注释形式切分为 {@link TokenType#COMMENT COMMENT} token</p>
* <p>负责将源码中的两种注释形式切分为 {@link TokenType#COMMENT COMMENT} token: </p>
* <ol>
* <li>单行注释 {@code //} 开头直至行尾或文件末尾</li>
* <li>多行注释 {@code /*} 开头 <code>*&#47;</code> 结束可跨多行</li>
* <li>单行注释: {@code //} 开头直至行尾或文件末尾</li>
* <li>多行注释: {@code /*} 开头 <code>*&#47;</code> 结束可跨多行</li>
* </ol>
*
* <p>本扫描器遵循发现即捕获原则注释文本被完整保留在 Token 供后续的文档提取源映射等分析使用</p>
* <p>本扫描器遵循发现即捕获原则: 注释文本被完整保留在 Token 供后续的文档提取源映射等分析使用</p>
*
* <p>错误处理策略</p>
* <ul>
* <li>未终止的多行注释若文件结束时仍未遇到 <code>*&#47;</code>抛出 {@link LexicalException}</li>
* <li>未终止的多行注释: 若文件结束时仍未遇到 <code>*&#47;</code>抛出 {@link LexicalException}</li>
* </ul>
*/
public class CommentTokenScanner extends AbstractTokenScanner {
@ -61,7 +61,7 @@ public class CommentTokenScanner extends AbstractTokenScanner {
break;
case SINGLE_LINE:
// 单行注释处理读取直到行尾
// 单行注释处理: 读取直到行尾
if (ctx.isAtEnd() || ctx.peek() == '\n') {
// 如果遇到换行符停止读取并返回注释内容
return new Token(TokenType.COMMENT, literal.toString(), line, col);

View File

@ -9,7 +9,7 @@ import org.jcnc.snow.compiler.lexer.token.TokenType;
/**
* {@code IdentifierTokenScanner} 标识符扫描器负责识别源代码中的标识符如变量名函数名等
*
* <p>标识符的识别遵循以下规则</p>
* <p>标识符的识别遵循以下规则: </p>
* <ul>
* <li>标识符必须以字母A-Za-z或下划线_开头</li>
* <li>标识符的后续字符可以是字母数字0-9或下划线</li>

View File

@ -5,7 +5,7 @@ import org.jcnc.snow.compiler.lexer.token.Token;
import org.jcnc.snow.compiler.lexer.token.TokenType;
/**
* 换行符扫描器将源代码中的换行符\n识别为 {@code NEWLINE} 类型的 Token
* 换行符扫描器: 将源代码中的换行符\n识别为 {@code NEWLINE} 类型的 Token
* <p>
* 用于记录行的分界辅助语法分析阶段进行行敏感的判断或保持结构清晰
*/

View File

@ -8,7 +8,7 @@ import org.jcnc.snow.compiler.lexer.token.TokenType;
/**
* NumberTokenScanner 基于有限状态机FSM的数字字面量解析器
* <p>
* 该扫描器负责将源码中的数字字符串切分为 NUMBER_LITERAL token当前支持
* 该扫描器负责将源码中的数字字符串切分为 NUMBER_LITERAL token当前支持:
* <ol>
* <li>十进制整数 042123456</li>
* <li>十进制小数 3.140.5</li>
@ -18,7 +18,7 @@ import org.jcnc.snow.compiler.lexer.token.TokenType;
* 如果后续需要支持科学计数法下划线分隔符不同进制等只需扩展现有状态机的转移规则
*
* <pre>
* 状态机简述
* 状态机简述:
* INT_PART --'.'--> DEC_POINT
* | |
* | v
@ -27,28 +27,28 @@ import org.jcnc.snow.compiler.lexer.token.TokenType;
* v
* DEC_POINT --digit--> FRAC_PART
* </pre>
* 状态说明
* 状态说明:
* <ul>
* <li>INT_PART 读取整数部分遇到 '.' 进入 DEC_POINT否则结束</li>
* <li>DEC_POINT 已读到小数点必须下一个字符是数字否则报错</li>
* <li>FRAC_PART 读取小数部分遇非法字符则结束主体</li>
* <li>END 主体扫描结束进入后缀/尾随字符判定</li>
* <li>INT_PART : 读取整数部分遇到 '.' 进入 DEC_POINT否则结束</li>
* <li>DEC_POINT : 已读到小数点必须下一个字符是数字否则报错</li>
* <li>FRAC_PART : 读取小数部分遇非法字符则结束主体</li>
* <li>END : 主体扫描结束进入后缀/尾随字符判定</li>
* </ul>
*
* 错误处理策略
* 错误处理策略:
* <ol>
* <li>数字后跟未知字母 42X 抛出 LexicalException</li>
* <li>数字与合法后缀间有空白 3 L 抛出 LexicalException</li>
* <li>小数点后缺失数字 1. 抛出 LexicalException</li>
* </ol>
*
* 支持的单字符类型后缀包括b, s, l, f, d 及其大写形式若需支持多字符后缀可将该集合扩展为 Set<String>
* 支持的单字符类型后缀包括: b, s, l, f, d 及其大写形式若需支持多字符后缀可将该集合扩展为 Set<String>
*/
public class NumberTokenScanner extends AbstractTokenScanner {
/**
* 支持的单字符类型后缀集合
* 包含b, s, l, f, d 及其大写形式
* 包含: b, s, l, f, d 及其大写形式
* 对于多字符后缀可扩展为 Set<String> 并在扫描尾部做贪婪匹配
*/
private static final String SUFFIX_CHARS = "bslfdBSLFD";

View File

@ -8,14 +8,14 @@ import org.jcnc.snow.compiler.lexer.token.TokenType;
* 运算符扫描器OperatorTokenScanner
*
* <p>负责在词法分析阶段识别由 <b>= ! &lt; &gt; | &amp; %</b> 等字符
* 起始的单字符或双字符运算符并生成相应 {@link Token}</p>
* 起始的单字符或双字符运算符并生成相应 {@link Token}: </p>
*
* <ul>
* <li>赋值 / 比较{@code =}, {@code ==}, {@code !=}</li>
* <li>关系运算{@code >}, {@code >=}, {@code <}, {@code <=}</li>
* <li>逻辑运算{@code &&}, {@code ||}</li>
* <li>取模运算{@code %}</li>
* <li>逻辑非{@code !}</li>
* <li>赋值 / 比较: {@code =}, {@code ==}, {@code !=}</li>
* <li>关系运算: {@code >}, {@code >=}, {@code <}, {@code <=}</li>
* <li>逻辑运算: {@code &&}, {@code ||}</li>
* <li>取模运算: {@code %}</li>
* <li>逻辑非: {@code !}</li>
* </ul>
*
* <p>如果无法匹配到合法组合将返回 {@link TokenType#UNKNOWN}</p>

View File

@ -5,9 +5,9 @@ import org.jcnc.snow.compiler.lexer.token.Token;
import org.jcnc.snow.compiler.lexer.token.TokenType;
/**
* 字符串扫描器处理双引号包裹的字符串字面量支持基本的转义字符
* 字符串扫描器: 处理双引号包裹的字符串字面量支持基本的转义字符
* <p>
* 支持格式示例
* 支持格式示例:
* <ul>
* <li>"hello"</li>
* <li>"line\\nbreak"</li>

View File

@ -5,13 +5,13 @@ import org.jcnc.snow.compiler.lexer.token.Token;
import org.jcnc.snow.compiler.lexer.token.TokenType;
/**
* 符号扫描器识别常见的单字符符号如冒号逗号括号和算术符号
* 符号扫描器: 识别常见的单字符符号如冒号逗号括号和算术符号
* <p>
* 支持的符号包括
* 支持的符号包括:
* <ul>
* <li>标点符号: , .</li>
* <li>括号( )</li>
* <li>算术运算符+ - *</li>
* <li>标点符号: : , .</li>
* <li>括号: ( )</li>
* <li>算术运算符: + - *</li>
* </ul>
* <p>
* 生成的 Token 类型根据字符分别对应 {@link TokenType} 枚举中的定义

View File

@ -11,7 +11,7 @@ import org.jcnc.snow.compiler.lexer.token.Token;
* 由本类处理并抛出 {@link LexicalException}终止词法分析流程
* </p>
* <p>
* 主要作用保证所有非法不可识别的字符@$等不会被静默跳过或误当作合法 Token
* 主要作用: 保证所有非法不可识别的字符@$等不会被静默跳过或误当作合法 Token
* 而是在词法阶段立刻定位并报错有助于尽早发现源代码问题
* </p>
*/
@ -50,6 +50,6 @@ public class UnknownTokenScanner extends AbstractTokenScanner {
if (lexeme.isEmpty())
lexeme = String.valueOf(ctx.advance());
// 抛出词法异常并带上错误片段与具体位置
throw new LexicalException("词法错误非法字符序列 '" + lexeme + "'", line, col);
throw new LexicalException("词法错误: 非法字符序列 '" + lexeme + "'", line, col);
}
}

View File

@ -4,7 +4,7 @@ import org.jcnc.snow.compiler.lexer.core.LexerContext;
import org.jcnc.snow.compiler.lexer.token.Token;
/**
* 空白符扫描器跳过非换行的空白字符不生成任何 Token
* 空白符扫描器: 跳过非换行的空白字符不生成任何 Token
* <p>
* 支持的空白字符包括空格制表符Tab但不包括换行符 {@link NewlineTokenScanner} 处理
* <p>

View File

@ -12,7 +12,7 @@ import java.util.Set;
* </p>
*
* <p>
* 主要功能与特性
* 主要功能与特性:
* <ul>
* <li>统一管理语言关键字和类型名集合便于扩展与维护</li>
* <li>自动推断 Token 类型无需外部干预</li>
@ -35,7 +35,7 @@ public class TokenFactory {
/**
* 创建一个根据内容自动推断类型的 {@link Token} 实例
* <p>
* 优先级顺序为类型TYPE &gt; 关键字KEYWORD &gt; 标识符IDENTIFIER &gt; 未知UNKNOWN
* 优先级顺序为: 类型TYPE &gt; 关键字KEYWORD &gt; 标识符IDENTIFIER &gt; 未知UNKNOWN
* 若原始字符串同时属于多类则按优先级最高者处理
* </p>
*
@ -52,7 +52,7 @@ public class TokenFactory {
/**
* 判断并推断给定字符串的 {@link TokenType} 类型
* <p>
* 优先级依次为TYPE &gt; KEYWORD &gt; IDENTIFIER &gt; UNKNOWN
* 优先级依次为: TYPE &gt; KEYWORD &gt; IDENTIFIER &gt; UNKNOWN
* </p>
*
* @param raw 原始词素字符串
@ -106,7 +106,7 @@ public class TokenFactory {
* <p>
* 合法标识符需以字母a-z/A-Z或下划线_开头
* 后续可包含字母数字或下划线
* 例如_abc, a1b2, name_123 均为合法标识符
* 例如: _abc, a1b2, name_123 均为合法标识符
* </p>
*
* @param raw 输入的字符串

View File

@ -17,7 +17,7 @@ public class TokenPrinter {
/**
* 将给定的 Token 列表打印到标准输出控制台
* <p>
* 输出格式
* 输出格式:
* <pre>
* line col type lexeme
* ----------------------------------------------------
@ -33,7 +33,7 @@ public class TokenPrinter {
* 都应包含有效的行号列号类型和词素信息
*/
public static void print(List<Token> tokens) {
// 打印表头列名对齐宽度分别为 6616
// 打印表头: 列名对齐宽度分别为 6616
System.out.printf("%-6s %-6s %-16s %s%n", "line", "col", "type", "lexeme");
System.out.println("----------------------------------------------------");
@ -45,7 +45,7 @@ public class TokenPrinter {
.replace("\t", "\\t")
.replace("\r", "\\r");
// 按照固定格式输出行号列号类型词素
// 按照固定格式输出: 行号列号类型词素
System.out.printf("%-6d %-6d %-16s %s%n",
token.getLine(),
token.getCol(),

View File

@ -25,7 +25,7 @@ public record BinaryExpressionNode(
/**
* 返回该二元运算表达式的字符串表示形式
* <p>
* 输出格式为{@code left + " " + operator + " " + right}
* 输出格式为: {@code left + " " + operator + " " + right}
* 适用于调试或打印语法树结构
* </p>
*

View File

@ -8,7 +8,7 @@ import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
* {@code ExpressionStatementNode} 表示抽象语法树AST中的表达式语句节点
* <p>
* 表达式语句通常由一个单独的表达式组成并以语句形式出现
* 例如{@code foo();}{@code x = 1;}{@code print("hello");}
* 例如: {@code foo();}{@code x = 1;}{@code print("hello");}
* </p>
*
* @param expression 表达式主体通常为函数调用赋值方法链式调用等可求值表达式

View File

@ -11,7 +11,7 @@ import java.util.List;
* <p>
* 函数定义通常包含函数名形参列表返回类型以及函数体
* 在语义分析类型检查与代码生成等阶段具有核心地位
* 示例{@code int add(int a, int b) { return a + b; }}
* 示例: {@code int add(int a, int b) { return a + b; }}
* </p>
*
* @param name 函数名称标识符

View File

@ -6,7 +6,7 @@ import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
/**
* {@code ImportNode} 表示抽象语法树AST中的 import 语句节点
* <p>
* import 语句用于引入外部模块或库文件其语法形式一般为
* import 语句用于引入外部模块或库文件其语法形式一般为:
* {@code import my.module;}
* </p>
* <p>

View File

@ -12,7 +12,7 @@ import java.util.Optional;
* return 语句用于从当前函数中返回控制权并可携带一个可选的返回值表达式
* </p>
* <p>
* 示例
* 示例:
* <ul>
* <li>{@code return;}</li>
* <li>{@code return x + 1;}</li>

View File

@ -6,10 +6,10 @@ import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
/**
* {@code UnaryExpressionNode} 前缀一元运算 AST 节点
*
* <p>代表两种受支持的一元前缀表达式
* <p>代表两种受支持的一元前缀表达式:
* <ul>
* <li><b>取负</b>{@code -x}</li>
* <li><b>逻辑非</b>{@code !x}</li>
* <li><b>取负</b>: {@code -x}</li>
* <li><b>逻辑非</b>: {@code !x}</li>
* </ul>
*
* {@link #equals(Object)}{@link #hashCode()} 等方法</p>

View File

@ -3,12 +3,12 @@ package org.jcnc.snow.compiler.parser.ast.base;
/**
* {@code Node} 是抽象语法树AST中所有语法节点的统一根接口
* <p>
* 作为标记接口Marker Interface该接口定义 3 个方法line()column() file() 用于定位错误
* 主要用于统一标识并组织 AST 体系中的各种语法构件节点包括
* 作为标记接口Marker Interface该接口定义 3 个方法: line()column() file() 用于定位错误
* 主要用于统一标识并组织 AST 体系中的各种语法构件节点包括:
* </p>
* <ul>
* <li>{@link ExpressionNode}表达式节点如常量变量引用函数调用等</li>
* <li>{@link StatementNode}语句节点如声明赋值条件控制循环返回语句等</li>
* <li>{@link ExpressionNode}: 表达式节点如常量变量引用函数调用等</li>
* <li>{@link StatementNode}: 语句节点如声明赋值条件控制循环返回语句等</li>
* <li>模块函数参数等高层结构节点</li>
* </ul>
* <p>

View File

@ -70,7 +70,7 @@ public record ParserEngine(ParserContext ctx) {
}
/**
* 同步跳过当前行或直到遇到显式注册的顶层关键字
* 同步: 跳过当前行或直到遇到显式注册的顶层关键字
* <p>
* 该机制用于语法出错后恢复到下一个可能的有效解析点防止指针停滞导致死循环或重复抛错
* 同步过程中会优先跳过本行所有未识别 token并在遇到换行或注册关键字时停止随后跳过连续空行

View File

@ -11,13 +11,13 @@
## 核心功能
- **抽象语法树AST生成**定义丰富的 AST 节点类型
- **表达式解析器**基于 Pratt 解析,支持优先级、调用、成员访问等
- **语句解析器**支持 Snow 语言中的声明、控制流等
- **模块解析器**处理 `import` 导入声明
- **函数解析器**支持函数定义与调用
- **灵活的解析上下文管理**错误处理与流式 Token 管理
- **工具支持**AST JSON 序列化,便于调试与前后端通信
- **抽象语法树AST生成**: 定义丰富的 AST 节点类型
- **表达式解析器**: 基于 Pratt 解析,支持优先级、调用、成员访问等
- **语句解析器**: 支持 Snow 语言中的声明、控制流等
- **模块解析器**: 处理 `import` 导入声明
- **函数解析器**: 支持函数定义与调用
- **灵活的解析上下文管理**: 错误处理与流式 Token 管理
- **工具支持**: AST JSON 序列化,便于调试与前后端通信
## 模块结构
@ -39,7 +39,7 @@ parser/
* JDK 24 或更高版本
* Maven 构建管理
* 推荐 IDEIntelliJ IDEA
* 推荐 IDE: IntelliJ IDEA
---

View File

@ -10,10 +10,10 @@ import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet;
/**
* {@code UnaryOperatorParselet} 前缀一元运算符的 Pratt 解析器
*
* <p>当前 parselet 负责解析两种前缀运算
* <p>当前 parselet 负责解析两种前缀运算:
* <ul>
* <li><b>取负</b>{@code -x}</li>
* <li><b>逻辑非</b>{@code !x}</li>
* <li><b>取负</b>: {@code -x}</li>
* <li><b>逻辑非</b>: {@code !x}</li>
* </ul>
*
* 解析过程:
@ -25,7 +25,7 @@ import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet;
* <li>最终生成 {@link UnaryExpressionNode} AST 节点记录运算符与操作数</li>
* </ol>
*
* <p>此类仅负责<strong>语法结构</strong>的构建
* <p>此类仅负责<strong>语法结构</strong>的构建:
* <ul>
* <li>类型正确性在 {@code UnaryExpressionAnalyzer} 中校验</li>
* <li>IR 生成在 {@code ExpressionBuilder.buildUnary} 中完成</li>

View File

@ -10,7 +10,7 @@ import org.jcnc.snow.compiler.parser.context.ParserContext;
* 构建一个有效的 {@link ExpressionNode} 抽象语法树结构
* </p>
* <p>
* 不同的实现可以采用不同的解析技术
* 不同的实现可以采用不同的解析技术:
* <ul>
* <li>递归下降Recursive Descent</li>
* <li>Pratt Parser前缀/中缀优先级驱动</li>

View File

@ -11,7 +11,7 @@ import org.jcnc.snow.compiler.parser.expression.Precedence;
* Pratt 解析器架构中处理中缀操作的关键组件
* </p>
* <p>
* 每个中缀解析器负责
* 每个中缀解析器负责:
* <ul>
* <li>根据左侧已解析的表达式结合当前运算符继续解析右侧部分</li>
* <li>提供运算符优先级用于判断是否继续嵌套解析</li>

View File

@ -8,7 +8,7 @@ import org.jcnc.snow.compiler.lexer.token.Token;
* {@code PrefixParselet} 是用于解析前缀表达式的通用接口
* <p>
* 前缀表达式是以某个词法单元Token作为起始的表达式结构
* 常见类型包括
* 常见类型包括:
* <ul>
* <li>数字字面量 {@code 42}</li>
* <li>标识符 {@code foo}</li>

View File

@ -18,7 +18,7 @@ import java.util.HashMap;
*/
public class StatementParserFactory {
/** 注册表语句关键字 -> 对应语句解析器 */
/** 注册表: 语句关键字 -> 对应语句解析器 */
private static final Map<String, StatementParser> registry = new HashMap<>();
static {
@ -28,7 +28,7 @@ public class StatementParserFactory {
registry.put("loop", new LoopStatementParser());
registry.put("return", new ReturnStatementParser());
// 默认处理器表达式语句
// 默认处理器: 表达式语句
registry.put("", new ExpressionStatementParser());
}

View File

@ -18,7 +18,7 @@ public class TopLevelParserFactory {
/** 关键字 → 解析器注册表 */
private static final Map<String, TopLevelParser> registry = new HashMap<>();
/** 缺省解析器脚本模式(单条语句可执行) */
/** 缺省解析器: 脚本模式(单条语句可执行) */
private static final TopLevelParser DEFAULT = new ScriptTopLevelParser();
static {

View File

@ -22,7 +22,7 @@ import java.util.*;
* 实现 {@link TopLevelParser} 接口用于将源代码中的函数块解析为抽象语法树AST中的 {@link FunctionNode}
*
* <p>
* 本类使用 {@link FlexibleSectionParser} 机制按照语义区块结构对函数进行模块化解析支持以下部分
* 本类使用 {@link FlexibleSectionParser} 机制按照语义区块结构对函数进行模块化解析支持以下部分:
* </p>
*
* <ul>
@ -110,7 +110,7 @@ public class FunctionParser implements TopLevelParser {
* 构造函数定义中各区块的解析规则parameterreturn_typebody
*
* <p>
* 每个 {@link SectionDefinition} 包含两个部分区块起始判断器基于关键字与具体的解析逻辑
* 每个 {@link SectionDefinition} 包含两个部分: 区块起始判断器基于关键字与具体的解析逻辑
* </p>
*
* @param params 参数节点收集容器解析结果将存入此列表
@ -180,7 +180,7 @@ public class FunctionParser implements TopLevelParser {
* 解析函数参数列表
*
* <p>
* 支持声明后附加注释格式示例
* 支持声明后附加注释格式示例:
* <pre>
* parameter:
* declare x: int // 说明文字

View File

@ -11,7 +11,7 @@ import java.util.List;
/**
* {@code ImportParser} 类用于解析源码中的 import 导入语句
* <p>
* 支持以下格式的语法
* 支持以下格式的语法:
* <pre>
* import: module1, module2, module3
* </pre>
@ -23,7 +23,7 @@ public class ImportParser {
/**
* 解析 import 语句并返回表示被导入模块的语法树节点列表
* <p>
* 该方法会依次执行以下操作
* 该方法会依次执行以下操作:
* <ol>
* <li>确认当前语句以关键字 {@code import} 开头</li>
* <li>确认后跟一个冒号 {@code :}</li>

View File

@ -22,7 +22,7 @@ import java.util.List;
* </p>
*
* <p>
* 典型模块语法结构
* 典型模块语法结构:
* <pre>
* module: mymod
* import ...
@ -37,7 +37,7 @@ public class ModuleParser implements TopLevelParser {
/**
* 解析一个模块定义块返回完整的 {@link ModuleNode} 语法树节点
* <p>
* 解析过程包括
* 解析过程包括:
* <ol>
* <li>匹配模块声明起始 {@code module: IDENTIFIER}</li>
* <li>收集模块体内所有 import function 语句允许穿插空行</li>

View File

@ -10,12 +10,12 @@ import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser;
/**
* {@code DeclarationStatementParser} 类负责解析变量声明语句是语句级解析器的一部分
* <p>
* 本解析器支持以下两种形式的声明语法
* 本解析器支持以下两种形式的声明语法:
* <pre>{@code
* declare myVar:Integer
* declare myVar:Integer = 42 + 3
* }</pre>
* 其中
* 其中:
* <ul>
* <li>{@code myVar} 为变量名必须为标识符类型</li>
* <li>{@code Integer} 为类型标注必须为类型标记</li>
@ -29,7 +29,7 @@ public class DeclarationStatementParser implements StatementParser {
/**
* 解析一条 {@code declare} 声明语句并返回对应的抽象语法树节点 {@link DeclarationNode}
* <p>
* 解析流程如下
* 解析流程如下:
* <ol>
* <li>匹配关键字 {@code declare}</li>
* <li>读取变量名称标识符类型</li>

View File

@ -14,7 +14,7 @@ import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser;
/**
* {@code ExpressionStatementParser} 用于解析通用表达式语句赋值或普通表达式
* <p>
* 支持以下两种语法结构
* 支持以下两种语法结构:
* <pre>{@code
* x = 1 + 2 // 赋值语句
* doSomething() // 一般表达式语句
@ -51,7 +51,7 @@ public class ExpressionStatementParser implements StatementParser {
int column = ts.peek().getCol();
String file = ctx.getSourceName();
// 赋值语句IDENTIFIER = expr
// 赋值语句: IDENTIFIER = expr
if (ts.peek().getType() == TokenType.IDENTIFIER && "=".equals(ts.peek(1).getLexeme())) {
String varName = ts.next().getLexeme();
ts.expect("=");

View File

@ -15,7 +15,7 @@ import java.util.List;
/**
* {@code IfStatementParser} 类负责解析 if 条件语句是语句级解析器中的条件分支处理器
* <p>
* 本解析器支持以下结构的条件语法
* 本解析器支持以下结构的条件语法:
* <pre>{@code
* if <condition> then
* <then-statements>
@ -23,7 +23,7 @@ import java.util.List;
* <else-statements>]
* end if
* }</pre>
* 其中
* 其中:
* <ul>
* <li>{@code <condition>} 为任意可解析的布尔或数值表达式使用 {@link PrattExpressionParser} 解析</li>
* <li>{@code <then-statements>} {@code <else-statements>} 可包含多条语句自动跳过空行</li>
@ -119,7 +119,7 @@ public class IfStatementParser implements StatementParser {
}
// -------------------------
// 统一结束处理end if
// 统一结束处理: end if
// -------------------------
ts.expect("end");
ts.expect("if");

View File

@ -21,7 +21,7 @@ import java.util.Map;
/**
* {@code LoopStatementParser} 类负责解析自定义结构化的 {@code loop} 语句块
* <p>
* 该语法结构参考了传统的 for-loop并将其拆解为命名的语义区块
* 该语法结构参考了传统的 for-loop并将其拆解为命名的语义区块:
* <pre>{@code
* loop:
* init:
@ -36,12 +36,12 @@ import java.util.Map;
* end loop
* }</pre>
*
* 各区块说明
* 各区块说明:
* <ul>
* <li>{@code init}初始化语句通常为变量声明</li>
* <li>{@code cond}循环判断条件必须为布尔或数值表达式</li>
* <li>{@code step}每轮执行后更新逻辑通常为赋值语句</li>
* <li>{@code body}主执行语句块支持任意多条语句</li>
* <li>{@code init}: 初始化语句通常为变量声明</li>
* <li>{@code cond}: 循环判断条件必须为布尔或数值表达式</li>
* <li>{@code step}: 每轮执行后更新逻辑通常为赋值语句</li>
* <li>{@code body}: 主执行语句块支持任意多条语句</li>
* </ul>
* 本类依赖 {@link FlexibleSectionParser} 实现各区块的统一处理确保结构明确可扩展
*/
@ -50,7 +50,7 @@ public class LoopStatementParser implements StatementParser {
/**
* 解析 {@code loop} 语句块构建出对应的 {@link LoopNode} 抽象语法树节点
* <p>
* 本方法会按顺序检查各个命名区块可乱序书写并分别绑定其对应语义解析器
* 本方法会按顺序检查各个命名区块可乱序书写并分别绑定其对应语义解析器:
* <ul>
* <li>通过 {@link ParserUtils#matchHeader} 匹配区块开头</li>
* <li>通过 {@link FlexibleSectionParser} 派发区块逻辑</li>
@ -83,7 +83,7 @@ public class LoopStatementParser implements StatementParser {
// 定义各命名区块的识别与处理逻辑
Map<String, FlexibleSectionParser.SectionDefinition> sections = new HashMap<>();
// init 区块仅支持一条语句通常为 declare
// init 区块: 仅支持一条语句通常为 declare
sections.put("init", new FlexibleSectionParser.SectionDefinition(
ts1 -> ts1.peek().getLexeme().equals("init"),
(ctx1, ts1) -> {
@ -93,7 +93,7 @@ public class LoopStatementParser implements StatementParser {
}
));
// cond 区块支持任意可解析为布尔的表达式
// cond 区块: 支持任意可解析为布尔的表达式
sections.put("cond", new FlexibleSectionParser.SectionDefinition(
ts1 -> ts1.peek().getLexeme().equals("cond"),
(ctx1, ts1) -> {
@ -104,7 +104,7 @@ public class LoopStatementParser implements StatementParser {
}
));
// step 区块目前仅支持单一变量赋值语句
// step 区块: 目前仅支持单一变量赋值语句
sections.put("step", new FlexibleSectionParser.SectionDefinition(
ts1 -> ts1.peek().getLexeme().equals("step"),
(ctx1, ts1) -> {
@ -122,7 +122,7 @@ public class LoopStatementParser implements StatementParser {
}
));
// body 区块支持多条语句直到遇到 end body
// body 区块: 支持多条语句直到遇到 end body
sections.put("body", new FlexibleSectionParser.SectionDefinition(
ts1 -> ts1.peek().getLexeme().equals("body"),
(ctx1, ts1) -> {

View File

@ -10,7 +10,7 @@ import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser;
/**
* {@code ReturnStatementParser} 负责解析 return 语句是语句级解析器的一部分
* <p>
* 支持以下两种 return 语句形式
* 支持以下两种 return 语句形式:
* <pre>{@code
* return // 无返回值
* return expression // 带返回值
@ -23,7 +23,7 @@ public class ReturnStatementParser implements StatementParser {
/**
* 解析一条 return 语句并返回对应的 {@link ReturnNode} 抽象语法树节点
* <p>
* 解析逻辑如下
* 解析逻辑如下:
* <ol>
* <li>匹配起始关键字 {@code return}</li>
* <li>判断其后是否为 {@code NEWLINE}若否则表示存在返回值表达式</li>

View File

@ -14,7 +14,7 @@ import java.util.*;
* 并可借助 {@code JSONParser.toJson(Object)} 方法将其序列化为 JSON 字符串用于调试
* 可视化或跨语言数据传输
* <p>
* 支持的节点类型包括新增对 {@code BoolLiteralNode}{@code UnaryExpressionNode} 的完整支持
* 支持的节点类型包括新增对 {@code BoolLiteralNode}{@code UnaryExpressionNode} 的完整支持:
* <ul>
* <li>{@link ModuleNode}</li>
* <li>{@link FunctionNode}</li>
@ -213,7 +213,7 @@ public class ASTJsonSerializer {
"object", exprToMap(object),
"member", member
);
// 默认兜底处理只写类型
// 默认兜底处理: 只写类型
default -> Map.of("type", expr.getClass().getSimpleName());
};
}

Some files were not shown because too many files have changed in this diff Show More