diff --git a/README.md b/README.md index 4702eb6..1b74415 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ L Language 是一门学习型编译语言,手写词法分析、递归下降 + Pratt 解析、语义分析和 LLVM IR 代码生成,最终生成原生可执行文件。语法借鉴 Rust,类型系统支持类型推断。 +📖 **[语言参考手册](docs/language-reference.md)** — 完整的语法、类型、示例教程 + ```rust fn fib(n: i64) -> i64 { if n < 2 { return n; } diff --git a/docs/language-reference.md b/docs/language-reference.md new file mode 100644 index 0000000..9ed0ff1 --- /dev/null +++ b/docs/language-reference.md @@ -0,0 +1,575 @@ +# L Language 语言参考手册 + +> 版本 v0.5 | 145 测试全部通过 | LLVM 后端编译型语言 + +--- + +## 目录 + +1. [快速开始](#1-快速开始) +2. [基本类型](#2-基本类型) +3. [变量](#3-变量) +4. [运算符](#4-运算符) +5. [控制流](#5-控制流) +6. [函数](#6-函数) +7. [结构体](#7-结构体) +8. [枚举](#8-枚举) +9. [数组](#9-数组) +10. [类型别名](#10-类型别名) +11. [内置函数](#11-内置函数) +12. [注释](#12-注释) +13. [完整示例](#13-完整示例) +14. [编译与运行](#14-编译与运行) + +--- + +## 1. 快速开始 + +### Hello, World + +```rust +fn main() -> i64 { + print_i64(42); + return 0; +} +``` + +编译运行: +```bash +l_lang.exe hello.l -o hello.exe +./hello.exe +# 输出: 42 +``` + +### 程序结构 + +- 文件扩展名 `.l` +- 一个 `.l` 文件包含若干函数和类型声明 +- 必须有 `main` 函数作为入口点 +- 所有声明在顶层,不支持嵌套函数 + +--- + +## 2. 基本类型 + +| 类型 | 关键字 | 范围/说明 | 示例 | +|------|--------|----------|------| +| 整数 | `i64` | 64位有符号,`-2^63 ~ 2^63-1` | `42`, `-7`, `0` | +| 浮点 | `f64` | 64位双精度 | `3.14`, `-0.5`, `1.0` | +| 布尔 | `bool` | `true` 或 `false` | `true`, `false` | +| 字符串 | `str` | UTF-8 文本 | `"Hello"`, `"你好"` | +| 空类型 | `void` | 无返回值 | 用于函数返回类型 | + +### 类型转换 + +- `i64` 和 `f64` 混合运算时,`i64` 自动提升为 `f64` +- `bool` 和数值之间**不能**隐式转换 +- `str` 不能隐式转换为其他类型 + +--- + +## 3. 变量 + +### 声明 + +```rust +let x = 42; // 不可变,类型推断为 i64 +let y: i64 = 100; // 不可变,显式类型标注 +let z = 3.14; // 类型推断为 f64 +let msg = "hello"; // 类型推断为 str +let flag = true; // 类型推断为 bool +``` + +### 可变变量 + +```rust +let mut count: i64 = 0; // 可变变量 +count = count + 1; // 赋值 +count += 1; // 复合赋值 (等价于 count = count + 1) +``` + +> **规则**: 对 `let` 声明的不可变变量赋值会在编译时报错。 + +### 类型标注语法 + +```rust +let name: Type = value; // 完整写法 +let name = value; // 类型推断 +let mut name: Type = value; // 可变变量 +``` + +--- + +## 4. 运算符 + +### 算术 + +| 运算符 | 说明 | 示例 | +|--------|------|------| +| `+` | 加法 | `1 + 2` → `3` | +| `-` | 减法 | `5 - 3` → `2` | +| `*` | 乘法 | `3 * 4` → `12` | +| `/` | 除法 | `10 / 3` → `3` (整数) | +| `%` | 取模 | `10 % 3` → `1` | + +### 比较(返回 bool) + +| 运算符 | 说明 | +|--------|------| +| `==` | 等于 | +| `!=` | 不等于 | +| `<` | 小于 | +| `>` | 大于 | +| `<=` | 小于等于 | +| `>=` | 大于等于 | + +### 逻辑 + +| 运算符 | 说明 | +|--------|------| +| `&&` | 逻辑与 | +| `\|\|` | 逻辑或 | +| `!` | 逻辑非 | + +### 复合赋值 + +| 运算符 | 等价于 | +|--------|--------| +| `x += y` | `x = x + y` | +| `x -= y` | `x = x - y` | +| `x *= y` | `x = x * y` | +| `x /= y` | `x = x / y` | + +### 字符串拼接 + +```rust +let greeting = "Hello, " + "World!"; +// greeting = "Hello, World!" +``` + +### 优先级(从高到低) + +``` +! -(一元负) +* / % ++ - +== != < > <= >= +&& +|| +``` + +--- + +## 5. 控制流 + +### if / else + +```rust +if x > 0 { + print_i64(1); +} else if x == 0 { + print_i64(0); +} else { + print_i64(-1); +} +``` + +### while 循环 + +```rust +let mut i: i64 = 0; +while i < 5 { + print_i64(i); + i += 1; +} +// 输出: 0 1 2 3 4 +``` + +### for 循环 + +```rust +for i in 0..5 { + print_i64(i); +} +// 输出: 0 1 2 3 4 +``` + +`for i in start..end` 等价于 `let mut i = start; while i < end { ...; i += 1; }` + +### match + +```rust +enum Color { Red, Green, Blue } + +let c = Color::Green; +match c { + Color::Red => { print_i64(10); } + Color::Green => { print_i64(20); } + _ => { print_i64(0); } // 通配符 +} +// 输出: 20 +``` + +- 每个分支用 `=>` 分隔,花括号包围 +- `_` 表示通配符(匹配所有未列出的情况) +- `match` 是语句,不是表达式 + +--- + +## 6. 函数 + +### 定义 + +```rust +fn add(a: i64, b: i64) -> i64 { + return a + b; +} + +fn greet() -> void { + print_str("Hello"); +} +``` + +- `fn` 关键字定义函数 +- 参数格式: `name: Type` +- 返回类型: `-> Type`,可省略(默认 `void`) +- 支持递归调用 + +### 调用 + +```rust +let result = add(3, 5); +greet(); +``` + +--- + +## 7. 结构体 + +### 声明 + +```rust +struct Point { + x: i64, + y: i64, +} +``` + +### 初始化 + +```rust +let p = Point { x: 10, y: 20 }; +``` + +### 字段访问 + +```rust +print_i64(p.x); // 10 +print_i64(p.y); // 20 +``` + +### 嵌套结构体 + +```rust +struct Rect { + tl: Point, // 左上角 + br: Point, // 右下角 +} + +let r = Rect { + tl: Point { x: 0, y: 10 }, + br: Point { x: 5, y: 0 }, +}; + +print_i64(r.tl.x); // 0 (链式访问) +``` + +### 函数参数和返回值 + +```rust +fn make_point(x: i64, y: i64) -> Point { + return Point { x: x, y: y }; +} + +fn print_point(p: Point) -> void { + print_i64(p.x); + print_i64(p.y); +} +``` + +### impl — 方法 + +```rust +impl Point { + fn new(x: i64, y: i64) -> Point { + return Point { x: x, y: y }; + } + + fn get_x(self: Point) -> i64 { + return self.x; + } +} + +let p = Point.new(10, 20); // 方法调用 +print_i64(p.get_x()); // 10 +``` + +- `impl StructName { fn ... }` 定义方法 +- 第一个参数必须是 `self: StructName` +- 调用: `instance.method(args)` + +--- + +## 8. 枚举 + +### 声明 + +```rust +enum Color { + Red, + Green, + Blue, +} +``` + +### 访问变体 + +```rust +let c = Color::Green; +print_i64(c); // 1 (索引值: Red=0, Green=1, Blue=2) +``` + +```rust +let is_red = (c == Color::Red); // false +``` + +--- + +## 9. 数组 + +### 声明类型 + +```rust +let arr: [i64; 5] = arr; // 未初始化的 5 个 i64 数组 +``` + +数组类型语法: `[元素类型; 大小]` + +- 大小必须是整数常量 +- 元素类型支持: `i64`, `f64`, `bool` + +### 索引 + +```rust +arr[0] = 100; // 给第一个元素赋值 +arr[1] = 200; + +print_i64(arr[0]); // 100 +print_i64(arr[1]); // 200 +``` + +### 循环遍历 + +```rust +let mut arr: [i64; 5] = arr; +let mut i: i64 = 0; +while i < 5 { + arr[i] = i * 10; + i += 1; +} +``` + +--- + +## 10. 类型别名 + +```rust +type Meters = i64; +type Kilometers = i64; + +fn run(distance: Meters) -> void { + print_i64(distance); +} + +let d: Meters = 5000; +run(d); // 输出: 5000 +``` + +支持别名指向 struct: + +```rust +type P = Point; +let p: P = Point { x: 1, y: 2 }; +``` + +--- + +## 11. 内置函数 + +| 函数 | 参数 | 输出 | +|------|------|------| +| `print_i64(x)` | `i64` | 整数 + 换行 | +| `print_f64(x)` | `f64` | 浮点 + 换行 | +| `print_bool(x)` | `bool` | `true`/`false` + 换行 | +| `print_str(s)` | `str` | 字符串 + 换行 | + +--- + +## 12. 注释 + +```rust +// 这是单行注释 + +/* + 这是 + 多行注释 +*/ +``` + +--- + +## 13. 完整示例 + +### 斐波那契 + +```rust +fn fib(n: i64) -> i64 { + if n < 2 { + return n; + } + return fib(n - 1) + fib(n - 2); +} + +fn main() -> i64 { + print_i64(fib(10)); // 55 + return 0; +} +``` + +### 学生成绩统计 + +```rust +struct Student { + name_id: i64, + score: i64, +} + +impl Student { + fn new(id: i64, score: i64) -> Student { + return Student { name_id: id, score: score }; + } + + fn is_pass(self: Student) -> bool { + return self.score >= 60; + } +} + +enum Grade { A, B, C, D, F } + +fn get_grade(score: i64) -> i64 { + match score { + 90 => { return 0; } + 80 => { return 1; } + 70 => { return 2; } + 60 => { return 3; } + _ => { return 4; } + } +} + +fn main() -> i64 { + let s = Student.new(1001, 85); + print_i64(s.name_id); + print_i64(s.score); + + if s.is_pass() { + print_str("PASS"); + } else { + print_str("FAIL"); + } + + print_i64(get_grade(85)); // 1 (Grade::B) + + return 0; +} +``` + +### 数组操作 + +```rust +fn main() -> i64 { + let mut arr: [i64; 5] = arr; + + // 填充数组 + let mut i: i64 = 0; + while i < 5 { + arr[i] = i * i; + i += 1; + } + + // 打印数组 + i = 0; + while i < 5 { + print_i64(arr[i]); + i += 1; + } + return 0; +} +// 输出: 0 1 4 9 16 +``` + +--- + +## 14. 编译与运行 + +### 安装编译器 + +```bash +# 从源码构建 +git clone git@lhy-git.liuhangyv.top:Serendipity/l-language.git +cd l-language +mkdir build && cd build +cmake .. -G "MinGW Makefiles" -DCMAKE_PREFIX_PATH="D:/settings/Language/LLVM" +mingw32-make -j4 +``` + +依赖: GCC 15.x (MinGW-w64), CMake 3.20+, LLVM 22.x + +### 使用 + +```bash +# 编译 +l_lang.exe source.l -o program.exe + +# 运行 +./program.exe + +# 查看生成的 LLVM IR +l_lang.exe source.l --emit-ir +``` + +### 错误信息格式 + +``` +错误: 文件名:行号:列号: 错误描述 +``` + +- 词法/语法错误: 立即终止 +- 类型错误: 收集所有错误后统一输出 + +--- + +## 快速参考卡片 + +``` +类型: i64 f64 bool str void struct enum [T;N] +声明: let x = val let mut x = val + let x: Type = val type Alias = Type +控制流: if/else while for i in 0..N match +函数: fn name(p: T) -> Ret { return expr; } +结构体: struct Name { f: Type } Name { f: val } +枚举: enum Name { A, B, C } Name::B +方法: impl T { fn m(self: T) } obj.m() +内建: print_i64 print_f64 print_bool print_str +运算符: + - * / % == != < > <= >= && || ! += -= *= /= +注释: // 行注释 /* 块注释 */ +```