# dlang **Repository Path**: da9527/dlang ## Basic Information - **Project Name**: dlang - **Description**: 用来学习编译原理 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-30 - **Last Updated**: 2026-04-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # DLang - 一个用Go实现的编程语言 DLang 是一个用 Go 语言编写的简单编程语言解释器,支持基本的数据类型、控制流、函数、数组、哈希表等特性。 ## 项目结构 ``` mylang/ ├── main.go # 程序入口 ├── lexer.go # 词法分析器 ├── token.go # 词法单元定义 ├── parser.go # 语法分析器 ├── ast.go # 抽象语法树定义 ├── evaluator.go # 解释器/求值器 ├── object.go # 运行时对象类型定义 ├── builtins.go # 内置函数实现 ├── environment.go # 变量环境管理 └── main_test.go # 测试用例 ``` ## 基本数据类型 ### 1. 整数 (Integer) ```dlang let x = 42; let y = -10; ``` ### 2. 浮点数 (Float) ```dlang let pi = 3.14; let e = 2.718; ``` ### 3. 布尔值 (Boolean) ```dlang let isTrue = true; let isFalse = false; ``` ### 4. 字符串 (String) ```dlang let name = "Hello, World!"; let greeting = "Hello"; ``` 支持的转义序列: | 转义序列 | 描述 | |----------|------| | `\n` | 换行符 | | `\t` | 制表符 | | `\r` | 回车符 | | `\"` | 双引号 | | `\\` | 反斜杠 | 示例: ```dlang let msg = "Hello\nWorld"; // 包含换行 let path = "C:\\Users\\Admin"; // 包含反斜杠 let quote = "He said \"Hi\""; // 包含双引号 ``` ### 5. 空值 (Null) ```dlang let empty = null; ``` ### 6. 数组 (Array) ```dlang let arr = [1, 2, 3, 4, 5]; let mixed = [1, "two", 3.0, true]; ``` 数组索引(从0开始): ```dlang let first = arr[0]; // 1 let second = arr[1]; // 2 ``` ### 7. 哈希表 (Hash) ```dlang let map = {"name": "Alice", "age": 30}; let scores = {"math": 95, "english": 87}; ``` 哈希表查找: ```dlang let name = map["name"]; // "Alice" let age = map["age"]; // 30 ``` 支持的键类型:整数、浮点数、字符串、布尔值。 ### 8. 函数 (Function) ```dlang // 方式1: 使用 fn 关键字定义 fn add(a, b) { return a + b; } // 方式2: 赋值给变量 let multiply = fn(a, b) { return a * b; }; ``` ## 语法特性 ### 注释 DLang 支持两种注释方式: #### 单行注释 使用 `//` 开头,注释到行尾: ```dlang // 这是单行注释 let x = 10; // 行尾注释 ``` #### 多行注释 使用 `/*` 和 `*/` 包裹,可以跨多行: ```dlang /* 这是多行注释 可以跨越多行 */ let y = 20; let z = /* 注释可以出现在表达式中间 */ 30; ``` ### 变量声明 ```dlang let x = 10; let name = "Alice"; let flag = true; ``` ### 变量赋值 ```dlang let x = 5; x = x + 2; // x 现在是 7 ``` ### 自增和自减 ```dlang let x = 5; x++; // x 变成 6 x--; // x 变成 5 ``` 注意:自增/自减操作只支持整数类型。 ### 条件语句 (if-else) ```dlang let x = 10; if (x > 5) { return 1; } else { return 0; } ``` 也支持没有 else 分支: ```dlang if (x > 5) { return "greater"; } ``` ### While 循环 ```dlang let i = 0; while (i < 5) { i++; } ``` ### For 循环 ```dlang // 完整形式 for (let i = 0; i < 5; i++) { // 循环体 } // 省略初始化 let i = 0; for (; i < 5; i++) { // 循环体 } // 无限循环(省略条件) for (;;) { // 需要配合 break 使用 break; } ``` ### 循环控制 #### Break 语句 跳出当前循环: ```dlang let i = 0; while (i < 10) { if (i == 5) { break; // 当 i 等于 5 时跳出循环 } i++; } ``` #### Continue 语句 跳过当前迭代,继续下一次循环: ```dlang let sum = 0; for (let i = 0; i < 5; i++) { if (i == 3) { continue; // 跳过 i=3 的情况 } sum = sum + i; } ``` ### 函数定义和调用 #### 基本函数 ```dlang fn add(a, b) { return a + b; } let result = add(3, 4); // result = 7 ``` #### 递归函数 ```dlang fn factorial(n) { if (n <= 1) { return 1; } return n * factorial(n - 1); } let result = factorial(5); // result = 120 ``` #### 斐波那契数列 ```dlang fn fib(n) { if (n <= 1) { return n; } return fib(n - 1) + fib(n - 2); } let result = fib(10); // result = 55 ``` #### 闭包 ```dlang fn outer(x) { return fn(y) { return x + y; }; } let inner = outer(5); let result = inner(3); // result = 8 ``` #### 函数作为头等公民 函数可以作为值使用: - 赋值给变量 - 作为参数传递给其他函数 - 存储在数组或哈希表中 示例: ```dlang // 函数赋值给变量 let add = fn(a, b) { return a + b; }; // 函数作为参数 fn apply(f, x, y) { return f(x, y); } let result = apply(add, 3, 4); // 7 // 函数存储在数组中 let funcs = [add, fn(x) { return x * 2; }]; // 函数存储在哈希表中 let ops = {"add": add, "sub": fn(a,b) { return a - b; }}; ``` ### 返回语句 ```dlang fn getValue() { return 42; } fn isPositive(x) { if (x > 0) { return true; } return false; } ``` ## 内置函数 DLang 提供以下内置函数,无需定义即可使用: ### 输出函数 #### `print` - 打印不换行 ```dlang print("Hello"); // 输出: Hello print("World"); // 输出: World (在同一行) ``` #### `println` - 打印并换行 ```dlang println("Hello"); // 输出: Hello\n println("World"); // 输出: World\n println(1, 2, 3); // 输出: 1 2 3\n (空格分隔) ``` ### 类型查询与转换 #### `len` - 获取长度 返回字符串长度或数组元素个数。 ```dlang println(len("Hello")); // 5 println(len([1, 2, 3, 4])); // 4 ``` #### `type` - 获取类型名 返回对象的类型字符串。 ```dlang println(type(42)); // "INTEGER" println(type(3.14)); // "FLOAT" println(type("hello")); // "STRING" println(type(true)); // "BOOLEAN" println(type(null)); // "NULL" println(type([1, 2])); // "ARRAY" println(type({"a": 1})); // "HASH" ``` #### `int` - 转换为整数 将参数转换为整数;转换失败返回 `null`。 ```dlang println(int("123")); // 123 println(int(3.14)); // 3 println(int(true)); // 1 println(int(false)); // 0 println(int(null)); // null println(int("abc")); // null (解析失败) ``` #### `float` - 转换为浮点数 将参数转换为浮点数;转换失败返回 `null`。 ```dlang println(float("3.14")); // 3.14 println(float(42)); // 42.0 println(float(true)); // 1.0 println(float(null)); // null ``` #### `str` - 转换为字符串 将任意对象转换为字符串表示。 ```dlang println(str(42)); // "42" println(str(3.14)); // "3.14" println(str(true)); // "true" ``` #### `bool` - 转换为布尔值 按 isTruthy 规则转换(0、0.0、空字符串、null 为 false,其余为 true)。 ```dlang println(bool(0)); // false println(bool(1)); // true println(bool("")); // false println(bool("hi")); // true println(bool(null)); // false println(bool([1, 2])); // true ``` ### 数组操作 #### `push` - 追加元素 向数组末尾追加一个元素,返回新长度。 ```dlang let arr = [1, 2, 3]; println(push(arr, 4)); // 4 println(arr); // [1, 2, 3, 4] ``` #### `pop` - 弹出元素 移除数组最后一个元素并返回,空数组返回 `null`。 ```dlang let arr = [1, 2, 3]; println(pop(arr)); // 3 println(arr); // [1, 2] println(pop([])); // null ``` ### 哈希表操作 #### `keys` - 获取所有键 返回哈希表所有键的数组。 ```dlang let map = {"a": 1, "b": 2, "c": 3}; println(keys(map)); // [a, b, c] ``` #### `values` - 获取所有值 返回哈希表所有值的数组。 ```dlang let map = {"a": 1, "b": 2, "c": 3}; println(values(map)); // [1, 2, 3] ``` ### 范围与随机数 #### `range` - 生成整数范围 模拟 Python 的 `range` 函数,生成整数数组。 ```dlang println(range(5)); // [0, 1, 2, 3, 4] println(range(2, 5)); // [2, 3, 4] println(range(0, 10, 2)); // [0, 2, 4, 6, 8] println(range(5, 0, -1)); // [5, 4, 3, 2, 1] ``` 参数说明: - `range(stop)` → 生成 `[0, 1, ..., stop-1]` - `range(start, stop)` → 生成 `[start, ..., stop-1]` - `range(start, stop, step)` → 按步长生成,步长可为负数 #### `random` - 生成随机数 ```dlang println(random()); // [0, 1) 的随机浮点数 println(random(10)); // [0, 10) 的随机整数 println(random(5.0)); // [0, 5) 的随机浮点数 ``` ### 字符串处理 #### `split` - 分割字符串 使用分隔符分割字符串,返回字符串数组。 ```dlang println(split("a,b,c", ",")); // [a, b, c] println(split("hello world", " ")); // [hello, world] ``` #### `join` - 连接数组元素 将数组元素用分隔符连接成字符串。 ```dlang println(join(["a", "b", "c"], ",")); // "a,b,c" println(join([1, 2, 3], "-")); // "1-2-3" ``` ### 数学函数 #### `sqrt` - 计算平方根 使用 `math.Sqrt` 计算平方根。 ```dlang println(sqrt(4)); // 2 println(sqrt(2)); // 1.4142135623730951 ``` 参数不能为负数,否则返回错误。 ## 运算符 ### 算术运算符 | 运算符 | 描述 | 示例 | |--------|------|------| | `+` | 加法 | `1 + 2` → `3` | | `-` | 减法 | `5 - 3` → `2` | | `*` | 乘法 | `3 * 4` → `12` | | `/` | 除法 | `10 / 2` → `5` | 注意: - 整数除法结果为整数(截断小数) - 浮点数除法结果为浮点数 - 整数和浮点数可以混合运算,结果为浮点数 ### 比较运算符 | 运算符 | 描述 | 示例 | |--------|------|------| | `<` | 小于 | `3 < 5` → `true` | | `>` | 大于 | `5 > 3` → `true` | | `<=` | 小于等于 | `3 <= 3` → `true` | | `>=` | 大于等于 | `5 >= 3` → `true` | | `==` | 等于 | `5 == 5` → `true` | | `!=` | 不等于 | `5 != 3` → `true` | ### 逻辑运算符 | 运算符 | 描述 | 示例 | |--------|------|------| | `&&` | 逻辑与 | `true && false` → `false` | | `\|\|` | 逻辑或 | `true \|\| false` → `true` | | `!` | 逻辑非 | `!true` → `false` | ### 前缀运算符 ```dlang let x = 5; let y = -x; // y = -5 let flag = true; let notFlag = !flag; // notFlag = false ``` ### 索引运算符 用于访问数组元素和哈希表值: ```dlang let arr = [10, 20, 30]; let first = arr[0]; // 10 let map = {"a": 1, "b": 2}; let val = map["a"]; // 1 ``` ### 字符串拼接 使用 `+` 运算符可以拼接字符串: ```dlang let greeting = "Hello" + " " + "World"; // "Hello World" let msg = "Result: " + 42; // "Result: 42" let info = 3.14 + " is pi"; // "3.14 is pi" ``` ## 完整示例 ### 示例1:计算1到5的和 ```dlang let sum = 0; let i = 1; while (i <= 5) { sum = sum + i; i++; } return sum; // 15 ``` ### 示例2:使用for循环计算1到5的和 ```dlang let sum = 0; for (let i = 1; i <= 5; i++) { sum = sum + i; } return sum; // 15 ``` ### 示例3:数组操作 ```dlang let arr = [10, 20, 30, 40, 50]; let first = arr[0]; // 10 let third = arr[2]; // 30 return first + third; // 40 ``` ### 示例4:哈希表操作 ```dlang let person = {"name": "Bob", "age": 25}; let name = person["name"]; // "Bob" let age = person["age"]; // 25 return age; // 25 ``` ### 示例5:函数与循环结合 ```dlang fn sumTo(n) { let sum = 0; let i = 1; while (i <= n) { sum = sum + i; i++; } return sum; } return sumTo(10); // 55 ``` ## 运行测试 使用以下命令运行测试: ```bash go test -v ``` ## 编译为解释器 ```bash go build -o dlang.exe ``` ## 如何运行 ```bash echo "return 1 + 1" > test.dl go run main.go test.dl # or dlang.ext test.dl ``` 目前程序会执行 `main.go` 中定义的测试代码。你可以修改 `main.go` 中的代码来测试不同的语言特性。 ## 错误类型 解释器会返回以下错误: - **除零错误**:`除数不能为0` - **未定义变量**:`未找到标识符: xxx` - **类型错误**:`自增操作只支持整数类型`、`不支持的操作符` 等 - **函数调用错误**:`不是函数`、`参数数量不匹配` - **哈希表错误**:`不支持的哈希键类型` ## 特性总结 - ✅ 基本数据类型:整数、浮点数、布尔值、字符串、空值 - ✅ 复合数据类型:数组、哈希表 - ✅ 变量声明和赋值 - ✅ 注释:单行注释 `//` 和多行注释 `/* ... */` - ✅ 算术和比较运算 - ✅ 逻辑运算 - ✅ 条件语句 (if-else) - ✅ 循环语句 (while, for) - ✅ 循环控制 (break, continue) - ✅ 函数定义和调用 - ✅ 递归 - ✅ 闭包 - ✅ 数组索引和哈希表查找 - ✅ 字符串拼接 - ✅ 内置函数:print、println、len、type、int、float、str、bool、push、pop、keys、values、range、split、join、sqrt、random - ✅ 错误处理