# chplus **Repository Path**: chengyiok/chplus ## Basic Information - **Project Name**: chplus - **Description**: No description available - **Primary Language**: Unknown - **License**: AGPL-3.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-31 - **Last Updated**: 2026-01-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # .ch 文件中文解释器 ## 项目简介 这是一个使用 C++ 实现的 `.ch` 文件中文解释器,直接解析并执行 `.ch` 后缀文件,无需转换为其他语言。解释器采用类 C++ 的编译解析逻辑,所有关键字均使用中文,支持变量定义、函数定义、基本运算、控制台输出、数组操作、结构体、文件操作和流程控制等核心功能。 ## 版本信息 ### v1.4.0(最新版本) - **修复内容**: - 修复"函数未定义: sin(小数)"错误,改进函数调用时的参数类型推断逻辑 - 修复文件库函数重复定义问题,移除重复的"文件存在"函数定义 - 修复字符串库函数调用问题,将"字符串长度"统一为"长度"函数 - 增强解释器跨平台兼容性,使用Windows API实现命令执行功能 - 优化编译配置,移除不必要的filesystem库依赖 - 改进错误调试机制,添加详细的函数查找和参数匹配调试信息 - **Bug反馈**:有bug请tg @abcdefgjha反馈 ### v1.3.0 - **修复内容**: - 修复结构体数组语法错误,支持结构体数组的成员访问和赋值 - 修复未格式化代码的中文标点符号问题,支持中文注释和标点符号 - 增强解释器兼容性,支持更多中文语法特性 - 优化错误处理机制,提供更精确的错误定位 - **Bug反馈**:有bug请tg @abcdefgjha反馈 ### v1.2.0 - **修复内容**:修复了一些bug - **Bug反馈**:有bug请tg @abcdefgjha反馈 ### v1.1.0 - **新功能**:增加格式化工具,增加取字符串长度 - **Bug反馈**:有bug请tg @abcdefgha ### v1.0.0(初始版本) - **描述**:初代版本 - **Bug反馈**:有bug请tg @abcdefgjha提交 **主要特性:** - ✅ 完整的错误定位系统,所有错误都包含精确的行号信息 - ✅ 智能类型系统:整型运算返回整型,浮点数运算返回浮点数 - ✅ 多维数组支持:支持1-5维数组,最多5维,语法类似C/C++ - ✅ 完整的数组支持:数组定义、初始化、元素访问和赋值 - ✅ 动态数组大小支持:支持使用变量和表达式作为数组大小,语法灵活 - ✅ 文件读写操作:支持文件读取、写入和追加操作 - ✅ 结构体定义和成员访问:支持结构体定义、变量实例化和成员访问 - ✅ 结构体成员赋值:支持直接对结构体成员进行赋值操作 - ✅ 函数重载:支持同名函数不同参数 - ✅ 函数作用域限制:全局作用域只允许变量定义和结构体定义 - ✅ 函数返回类型检查:确保函数返回类型与定义一致 - ✅ 否则如果语句:支持完整的if-else if-else条件判断链 - ✅ ASCII字符兼容:完全支持ASCII码表和中文字符 - ✅ 严格的代码规范:移除所有简化处理,提高代码健壮性 - ✅ 精确错误处理:移除所有"假设"和"默认"处理,提供详细错误信息 - ✅ 系统命令行:支持系统命令行执行功能,类似system()函数 - ✅ 字符类型支持:新增字符型数据类型和字符字面量支持 - ✅ 基础类型转换:提供基础的类型转换功能,包括整数、浮点数、布尔值转换 ## 目录结构 ``` chplus/ ├── main.cpp # 主程序入口 ├── CMakeLists.txt # CMake构建配置文件 ├── README.md # 项目文档 ├── include/ # 头文件目录 │ ├── lexer.h # 词法分析器头文件 │ ├── parser.h # 语法分析器头文件 │ └── interpreter.h # 执行器头文件 ├── src/ # 源代码目录 │ ├── lexer/ # 词法分析器实现 │ ├── parser/ # 语法分析器实现 │ ├── executor/ # 执行器实现 │ └── utils/ # 工具函数 ├── examples/ # 示例文件目录 ├── ch_Lib/ # 标准库目录 │ ├── math.ch # 完整数学库 (100%中文化) │ ├── string.ch # 完整字符串库 (100%中文化) │ ├── file.ch # 完整文件库 (100%中文化) │ ├── readme.math.ch.md # 数学库详细文档 │ ├── readme.string.ch.md # 字符串库详细文档 │ └── readme.file.ch.md # 文件库详细文档 └── tests/ # 测试文件目录 ``` ## 模块化编程与导入功能 .ch解释器支持模块化编程,允许通过导入功能将代码组织成多个文件。 ### 导入语法 ```ch 导入("ch_Lib/库名.ch"); ``` ### 标准库概述 .ch解释器提供了三个核心标准库,全部使用中文函数名: #### 1. 数学库 (math.ch) 完整的C++ cmath功能实现,包含: - **三角函数**: sin, cos, tan, asin, acos, atan - **双曲函数**: sinh, cosh, tanh - **指数对数**: exp, log, log10, sqrt, cbrt - **取整函数**: ceil, floor, round, trunc - **绝对值函数**: abs, fabs - **其他函数**: fmod, gcd, lcm等 - **数学常量**: PI, E, SQRT2等 **使用示例:** ```ch 导入("ch_Lib/math.ch"); 定义(空类型) 主函数() { 定义(小数) radius = 5.0; 定义(小数) area = PI * radius * radius; 控制台输出("圆的面积: " + area); // 输出: 78.539815 } ``` #### 2. 字符串库 (string.ch) 完整的C++ string功能实现,包含: - **基础操作**: 连接、重复、子串、长度 - **转换功能**: 转大写、转小写、去空白 - **查找功能**: 查找、反向查找、替换 - **验证功能**: 为数字、为字母、为空白 - **字符操作**: 获取字符、翻转、计数 - **高级功能**: 填充、分割、连接 - **类型转换**: 整数转字符串、小数转字符串、布尔值转字符串、字符串转数值 - **内置优化**: 长度、子串、查找等核心函数直接集成在解释器中,性能优化 **使用示例:** ```ch 导入("ch_Lib/string.ch"); 定义(空类型) 主函数() { 定义(字符串) text = "Hello World"; 控制台输出(长度(text)); // 输出: 11 控制台输出(子串(text, 0, 5)); // 输出: Hello 控制台输出(查找(text, "World")); // 输出: 6 控制台输出(转大写(text)); // 输出: HELLO WORLD 控制台输出(转小写(text)); // 输出: hello world // 类型转换示例 定义(整型) num = 123; 控制台输出(整数转字符串(num)); // 输出: 123 定义(小数) pi = 3.14159; 控制台输出(小数转字符串(pi)); // 输出: 3.14 // 高级操作 定义(字符串) messy = " hello "; 控制台输出(去空白(messy)); // 输出: hello 控制台输出(重复("Hi", 3)); // 输出: HiHiHi } ``` #### 3. 文件库 (file.ch) 完整的C++文件操作和freopen功能实现,包含: - **文件重定向**: 类似freopen的流重定向功能 - **文件读写**: 读取、写入、追加文件 - **文件系统**: 检查存在、获取大小、路径操作 - **目录操作**: 创建、删除、重命名 - **文本处理**: 逐行读取、分割、合并 - **临时文件**: 创建临时文件、获取系统目录 **使用示例:** ```ch 导入("ch_Lib/file.ch"); 定义(空类型) 主函数() { // 文件重定向 重定向标准输出("log.txt"); 控制台输出("这条信息写入文件"); 恢复标准输出(); // 文件操作 如果 (文件存在("config.txt")) { 定义(字符串) content = 读取文件("config.txt"); 控制台输出("配置文件内容: " + content); } } ``` ### 循环导入检测 导入功能内置循环导入检测,防止: - 文件A导入B,B又导入A - 多层循环导入链 - 嵌套导入循环 **安全特性:** - 自动检测循环依赖 - 防止无限递归 - 错误提示和回滚机制 ### 导入功能使用指南 1. **导入位置**:导入语句通常放在程序开头 2. **相对路径**:支持相对路径和绝对路径 3. **库结构**:建议将库文件放在ch_Lib目录 4. **循环检测**:避免创建循环依赖关系 **最佳实践:** ```ch // 导入多个库 导入("ch_Lib/math.ch"); 导入("ch_Lib/string.ch"); 导入("ch_Lib/file.ch"); // 在主函数中使用库功能 定义(空类型) 主函数() { // 使用数学库 定义(小数) result = sin(30) + cos(60); // 使用字符串库 定义(字符串) msg = 连接("计算结果: ", 整数转字符串(result)); // 使用文件库 写入文件("result.txt", msg); // 使用系统命令行 系统命令行("echo 系统命令行功能演示"); 系统命令行("dir"); } ``` ## 系统命令行功能 .ch解释器支持系统命令行执行功能,类似于C++中的`system()`函数。 ### 语法 ```ch 系统命令行("要执行的命令"); ``` ### 功能特性 - **直接执行**:使用系统的shell环境执行命令 - **返回值处理**:获取命令执行的返回码 - **表达式支持**:支持作为表达式使用,返回命令执行结果 - **文件操作集成**:与文件库完美集成,支持文件读取 - **错误报告**:命令执行失败时显示错误信息 - **中文友好**:支持中文路径和中文命令 ### 使用示例 ```ch 定义(空类型) 主函数() { // 传统系统命令行语句(不返回值) 系统命令行("echo Hello World"); 系统命令行("dir"); // 系统命令行表达式(返回命令执行结果) 定义(字符串) result = 系统命令行("echo 测试"); 控制台输出("命令结果: " + result); // 文件操作 系统命令行("mkdir new_folder"); // 读取文件内容(改进版) 导入("ch_Lib/file.ch"); 定义(字符串) fileContent = 读取文件("test.txt"); 控制台输出("文件内容: " + fileContent); } ``` ### 实际应用 系统命令行功能特别适合用于: - **文件管理**:创建、删除、复制、移动文件和目录 - **系统信息**:获取时间、用户信息、系统状态 - **网络操作**:ping、curl、wget等网络工具 - **程序调用**:执行外部程序和脚本 - **自动化任务**:批量处理和系统维护 ## 语法说明 ### 变量定义 变量定义遵循固定格式:`定义(数据类型) 变量名;`,支持变量初始化和数组定义。 **示例:** ```ch // 基本类型 定义(整型) a = 10; 定义(字符串) b = "测试内容"; 定义(小数) pi = 3.14; 定义(布尔型) isActive = 真; // 布尔型变量 定义(字符型) ch = 'A'; // 字符型变量 定义(整型) c; // 数组类型 定义(整型) arr[10]; // 整型数组 定义(字符串) names[5]; // 字符串数组 定义(小数) prices[100]; // 小数数组 定义(布尔型) flags[5]; // 布尔型数组 定义(字符型) chars[26]; // 字符型数组 // 结构体数组(新增功能) 定义(结构体) Point { 整型 x; 整型 y; }; 定义(Point) points[10]; // 结构体数组 ``` ## 未来计划解决 基于当前测试结果,以下文件存在执行问题,将在未来版本中解决: ### ❌ 无法执行的文件列表 #### 1. 结构体数组相关文件 - **file_basic.ch** - 文件基础操作(导入成功但执行异常) - **file_redirect.ch** - 文件重定向(导入成功但执行异常) - **math_demo.ch** - 数学演示(导入成功但执行异常) - **simple_struct_array.ch** - 简化结构体数组(结构体变量格式错误) - **string_find_replace.ch** - 字符串查找替换(导入成功但执行异常) - **struct_array_test.ch** - 结构体数组测试(结构体变量格式错误) ### 🔧 计划修复内容 #### 高优先级修复 1. **结构体数组语法完善** - 修复结构体数组成员赋值语法 - 优化结构体实例格式处理 - 增强结构体数组访问支持 2. **文件操作功能增强** - 完善文件库函数实现 - 修复文件读写异常 - 增强文件操作错误处理 #### 中优先级修复 3. **字符串操作功能完善** - 完善字符串查找替换功能 - 增强字符串库兼容性 - 优化字符串处理性能 4. **数学库功能增强** - 完善数学函数实现 - 修复数学演示文件执行问题 - 增强数学计算精度 #### 低优先级优化 5. **错误处理机制优化** - 提供更详细的错误信息 - 增强错误恢复能力 - 优化错误定位精度 6. **性能优化** - 优化解释器执行效率 - 减少内存占用 - 提升大型文件处理能力 ### 📊 当前测试统计 - **总样例文件**: 23个 - **成功执行**: 17个 (✅ 73.9%) - **需要修复**: 6个 (❌ 26.1%) ### 🎯 目标 在下一个版本中,目标是将所有样例文件的执行成功率提升到95%以上,确保核心功能的稳定性和兼容性。 ### 函数定义 函数定义规则与变量定义一致,无需额外显式声明「函数」关键字,`定义()`内填写返回值类型(可留空对应无返回值)。 **重要约束:** - 函数作用域限制:全局作用域(主函数之外)只能定义变量和结构体,不允许执行其他操作(如文件读写、控制台输出等) - 函数重载:支持同名函数不同参数类型 - 返回类型检查:函数返回类型必须与定义一致 **示例:** ```ch // 无返回值主函数 定义(空类型) 主函数() { 控制台输出("Hello World"); } // 有参数有返回值函数 定义(整型) 求和函数(定义(整型) x, 定义(整型) y) { 定义(整型) result = x + y; 返回 result; } // 函数重载示例 定义(整型) 计算(定义(整型) a, 定义(整型) b) { 返回 a + b; } 定义(小数) 计算(定义(小数) a, 定义(小数) b) { 返回 a + b; } 定义(字符串) 计算(定义(字符串) a, 定义(字符串) b) { 返回 a + b; } // 空类型函数示例 定义(空类型) printMessage(定义(字符串) msg) { 控制台输出(msg); // 可以使用返回退出函数,但不返回值 返回; } ``` ### 流程控制 **if-else if-else 语句:** ```ch 如果 (条件) { // 条件为真时执行 } 否则如果 (其他条件) { // 第一个条件为假,其他条件为真时执行 } 否则 { // 所有条件为假时执行 } ``` **示例:** ```ch 定义(整型) score = 85; 如果 (score >= 90) { 控制台输出("成绩优秀"); } 否则如果 (score >= 80) { 控制台输出("成绩良好"); } 否则如果 (score >= 70) { 控制台输出("成绩中等"); } 否则如果 (score >= 60) { 控制台输出("成绩及格"); } 否则 { 控制台输出("成绩不及格"); } ``` ### 控制台输入输出 **控制台输出:** 使用 `控制台输出()` 函数进行输出: ```ch 控制台输出("Hello World"); 控制台输出(a + b); ``` **控制台输入:** 使用 `控制台输入()` 函数进行输入: ```ch 控制台输入(年龄); // 从控制台读取输入到变量年龄 ``` **文件操作:** **文件写入:** 使用 `文件写入()` 函数创建或覆盖文件: ```ch 定义(字符串) content = "这是文件内容"; 文件写入("example.txt", content); ``` **文件读取:** 使用 `文件读取()` 函数从文件读取内容: ```ch 定义(字符串) fileContent; 文件读取("example.txt", fileContent); 控制台输出("文件内容: " + fileContent); ``` **文件追加:** 使用 `文件追加()` 函数向文件末尾追加内容: ```ch 定义(字符串) additional = "追加的内容"; 文件追加("example.txt", additional); ``` **完整示例:** ```ch 定义(空类型) 主函数() { // 写入文件 定义(字符串) data = "Hello, File!"; 文件写入("test.txt", data); // 读取文件 定义(字符串) content; 文件读取("test.txt", content); 控制台输出("读取的内容: " + content); // 追加内容 文件追加("test.txt", "\n这是追加的内容"); } ``` **布尔类型操作:** ```ch // 布尔型变量定义 定义(布尔型) isActive = 真; // 真值 定义(布尔型) isEmpty = 假; // 假值 // 布尔运算符 isActive && 假; // 逻辑与:真 && 假 = 假 isActive || 假; // 逻辑或:真 || 假 = 真 !isActive; // 逻辑非:!真 = 假 // 基本运算符 定义(整型) a = 5; 定义(整型) b = 2; 定义(小数) x = 3.0; 定义(小数) y = 2.0; // 算术运算符 a + b; // 加法:5 + 2 = 7 a - b; // 减法:5 - 2 = 3 a * b; // 乘法:5 * 2 = 10 a / b; // 除法:5 / 2 = 2 a % b; // 取模:5 % 2 = 1 a ^ b; // 乘方:5 ^ 2 = 25 x ^ y; // 小数乘方:3.0 ^ 2.0 = 9.0 x ^ 2; // 混合类型:3.0 ^ 2 = 9.0 // 比较运算返回布尔值 a < b; // 返回 真 a == b; // 返回 假 ``` **数组操作:** ```ch // 一维数组 定义(整型) arr[10]; 控制台输出(arr[0]); // 输出数组第一个元素 arr[5] = 100; // 给数组元素赋值 // 动态数组大小(新增功能) 定义(整型) size = 5; 定义(整型) dynamicArr[size]; // 使用变量定义数组大小 定义(整型) n1 = 3, n2 = 4; 定义(整型) exprArr[n1 + n2]; // 使用表达式定义数组大小 // 多维数组(支持1-5维) 定义(整型) matrix[3][4]; // 二维数组 3x4 定义(整型) cube[2][2][2]; // 三维数组 2x2x2 定义(整型) arr5[2][2][2][2][2]; // 五维数组 // 多维动态数组 定义(整型) rows = 2, cols = 3; 定义(整型) dynamicMatrix[rows][cols]; // 多维动态数组 // 多维数组访问和赋值 matrix[1][2] = 42; // 给二维数组元素赋值 cube[0][1][1] = 100; // 给三维数组元素赋值 arr5[1][1][1][1][1] = 999; // 给五维数组元素赋值 // 数组索引可以是变量 定义(整型) i = 3; 定义(整型) j = 2; matrix[i][j] = 42; // matrix[3][2] = 42 dynamicArr[i] = 42; // 动态数组元素赋值 dynamicMatrix[i][j] = 42; // 多维动态数组元素赋值 ``` **结构体操作:** **结构体定义:** 使用 `定义(结构体)` 关键字定义结构体类型: **重要:结构体定义必须在主函数外部!** ```ch // 结构体定义(在主函数外部) 定义(结构体) Person { 整型 age; // 年龄成员 字符串 name; // 姓名成员 小数 score; // 分数成员 }; 定义(结构体) Point { 整型 x; // X坐标 整型 y; // Y坐标 字符串 color; // 颜色 }; // 主函数(在主函数外部) 定义(空类型) 主函数() { // 在主函数内部创建结构体变量和使用结构体 } ``` **结构体变量和成员访问:** 使用 `定义(结构体类型名)` 语法定义结构体变量,结构体变量只能通过以下方式初始化: 1. **无初始化器**:创建一个具有默认值的结构体变量 2. **同类型变量赋值**:从已存在的同类型结构体变量赋值 ```ch // 方式1:无初始化器(创建默认实例) 定义(Person) person1; // 创建默认的Person实例,所有成员使用默认值 定义(Point) point1; // 创建默认的Point实例,所有成员使用默认值 // 方式2:同类型变量赋值 定义(Person) person2 = person1; // 正确:Person 类型赋值给 Person 类型 定义(Point) point2 = point1; // 正确:Point 类型赋值给 Point 类型 // 错误示例: // 定义(Person) person3 = "Person:age=25;name=张三;score=85.5"; // 错误:不能使用字面量初始化 // 定义(Point) point3 = person1; // 错误:不能将 Person 类型赋值给 Point 类型 // 访问结构体成员 控制台输出("姓名: " + person1.name); // 输出:空字符串(默认值) 控制台输出("年龄: " + person1.age); // 输出:0(默认值) 控制台输出("分数: " + person1.score); // 输出:0.0(默认值) 控制台输出("X坐标: " + point1.x); // 输出:0(默认值) 控制台输出("Y坐标: " + point1.y); // 输出:0(默认值) 控制台输出("颜色: " + point1.color); // 输出:空字符串(默认值) ``` **结构体成员赋值:** ```ch // 创建结构体变量 定义(Point) point1; // 直接对结构体成员赋值 point1.x = 100; point1.y = 200; point1.color = "红色"; // 访问更新后的成员值 控制台输出("Point: x=" + point1.x + ", y=" + point1.y + ", color=" + point1.color); ``` **结构体变量赋值规则:** - 结构体变量只能从同类型的变量初始化 - 不能使用字面量(如 "Person:age=25;name=张三")直接初始化结构体变量 - 不同类型的结构体变量之间不能互相赋值 - 结构体变量可以赋值给同类型的其他变量 - 支持直接对结构体成员进行赋值操作 **完整结构体示例:** ```ch // 定义结构体 定义(结构体) Student { 整型 id; 字符串 name; 小数 gpa; 布尔型 isGraduate; }; 定义(空类型) 主函数() { // 创建学生对象(使用默认值) 定义(Student) student1; // 创建默认的Student实例 定义(Student) student2; // 创建另一个默认的Student实例 // 结构体变量赋值(相同类型) 定义(Student) student3 = student1; // 直接对结构体成员赋值 student1.id = 1001; student1.name = "张三"; student1.gpa = 3.8; student1.isGraduate = 假; // 输出学生信息 控制台输出("学生1姓名: " + student1.name); // 输出:张三 控制台输出("学生1ID: " + student1.id); // 输出:1001 控制台输出("学生1GPA: " + student1.gpa); // 输出:3.8 控制台输出("学生3姓名: " + student3.name); // 输出:空字符串(从 student1 赋值) } ``` ### 小数类型 使用 `小数` 关键字定义小数类型变量: ```ch 定义(小数) pi = 3.14; 定义(小数) radius = 5.0; 定义(小数) area = pi * radius * radius; 控制台输出("圆的面积: " + area); ``` ### 循环语句 **while循环:** ```ch 定义(整型) i = 0; 当 (i < 5) { 控制台输出("i = " + i); i = i + 1; } ``` **for循环:** ```ch 定义(整型) j = 0; 对于 (j = 0; j < 3; j = j + 1) { 控制台输出("j = " + j); } ``` ### 函数重载 解释器支持函数重载,即同名函数可以有不同的参数类型: ```ch // 定义多个同名函数,参数类型不同 定义(整型) add(定义(整型) a, 定义(整型) b) { 返回 a + b; } 定义(小数) add(定义(小数) a, 定义(小数) b) { 返回 a + b; } 定义(字符串) add(定义(字符串) a, 定义(字符串) b) { 返回 a + b; } // 调用时会根据参数类型自动选择合适的函数 定义(空类型) 主函数() { 控制台输出(add(10, 20)); // 调用整型版本,输出30 控制台输出(add(3.14, 2.86)); // 调用小数版本,输出6.0 控制台输出(add("Hello", "World")); // 调用字符串版本,输出HelloWorld } ``` ### 函数返回类型检查 所有函数都必须严格遵守返回类型: ```ch // 正确的返回类型 定义(整型) getInt() { 返回 42; // 正确,返回整型 } 定义(小数) getDouble() { 返回 3.14; // 正确,返回小数 } 定义(布尔型) getBool() { 返回 真; // 正确,返回布尔型 } 定义(空类型) print() { 控制台输出("Hello"); 返回; // 正确,空类型函数可以使用返回退出 } // 错误的返回类型(会导致编译错误) 定义(整型) wrongFunc() { 返回 3.14; // 错误:返回小数,但声明为整型 } 定义(空类型) wrongFunc2() { 返回 42; // 错误:空类型函数不能返回值 } ``` ## 中文关键字与 C++ 关键字对照表 | 中文关键字 | C++ 关键字 | 说明 | |----------|-----------|------| | 定义 | - | 用于变量和函数定义 | | 整型 | int | 整数类型 | | 字符串 | string | 字符串类型 | | 空类型 | void | 无返回值类型 | | 主函数 | main | 程序入口函数 | | 如果 | if | 条件判断 | | 否则 | else | 条件判断的分支 | | 否则如果 | else if | 条件判断的中间分支 | | 控制台输出 | cout | 输出到控制台 | | 控制台输入 | cin | 从控制台输入 | | 返回 | return | 函数返回值 | | 小数 | double | 小数类型 | | 布尔型 | bool | 布尔类型 | | 真 | true | 布尔真值 | | 假 | false | 布尔假值 | | 当 | while | 循环语句 | | 对于 | for | 循环语句 | | 文件读取 | - | 从文件读取内容 | | 文件写入 | - | 向文件写入内容 | | 文件追加 | - | 向文件追加内容 | | 结构体 | struct | 结构体关键字(用于定义(结构体)) | | 数组 | - | 数组类型关键字 | | ^ | pow | 乘方运算符 | | +, -, *, /, % | +, -, *, /, % | 算术运算符 | | &&, \|\| | &&, \|\| | 逻辑运算符 | | ==, !=, <, >, <=, >= | ==, !=, <, >, <=, >= | 比较运算符 | ## 运行/解析流程 1. **读取文件**:读取 `.ch` 文件内容 2. **词法分析**:将源代码转换为 Token 序列 3. **语法分析**:构建抽象语法树 (AST) 4. **执行**:遍历 AST 并执行相应的操作 5. **输出结果**:将执行结果输出到控制台 ## 示例代码 ### 示例 1:Hello World **文件名:** `examples/hello.ch` ```ch 定义(空类型) 主函数() { 控制台输出("Hello World!"); } ``` **运行结果:** ``` Hello World! ``` ### 示例 2:基本运算 **文件名:** `examples/calculator.ch` ```ch 定义(空类型) 主函数() { 定义(整型) a = 10; 定义(整型) b = 20; 定义(整型) sum = a + b; 定义(整型) product = a * b; 控制台输出("a + b = " + sum); 控制台输出("a * b = " + product); } ``` **运行结果:** ``` a + b = 30 a * b = 200 ``` ### 示例 3:条件判断 **文件名:** `examples/conditions.ch` ```ch 定义(空类型) 主函数() { 定义(整型) score = 85; 如果 (score >= 90) { 控制台输出("成绩优秀"); } 否则如果 (score >= 80) { 控制台输出("成绩良好"); } 否则如果 (score >= 70) { 控制台输出("成绩中等"); } 否则如果 (score >= 60) { 控制台输出("成绩及格"); } 否则 { 控制台输出("成绩不及格"); } } ``` **运行结果:** ``` 成绩良好 ``` ### 示例 4:函数重载 **文件名:** `examples/function_overload.ch` ```ch 定义(整型) add(定义(整型) a, 定义(整型) b) { 返回 a + b; } 定义(小数) add(定义(小数) a, 定义(小数) b) { 返回 a + b; } 定义(字符串) add(定义(字符串) a, 定义(字符串) b) { 返回 a + b; } 定义(空类型) 主函数() { 控制台输出(add(10, 20)); // 调用整型版本 控制台输出(add(3.14, 2.86)); // 调用小数版本 控制台输出(add("Hello", "World")); // 调用字符串版本 } ``` **运行结果:** ``` 30 6 HelloWorld ``` ### 示例 5:结构体操作 **文件名:** `examples/struct_demo.ch` ```ch 定义(结构体) Point { 整型 x; 整型 y; 字符串 color; }; 定义(空类型) 主函数() { // 创建结构体变量 定义(Point) point1; // 直接对结构体成员赋值 point1.x = 100; point1.y = 200; point1.color = "红色"; // 输出结构体成员 控制台输出("Point: x=" + point1.x + ", y=" + point1.y + ", color=" + point1.color); } ``` **运行结果:** ``` Point: x=100, y=200, color=红色 ``` ### 示例 6:数组操作 **文件名:** `examples/array_demo.ch` ```ch 定义(空类型) 主函数() { // 数组定义和初始化 定义(整型) numbers[5]; 定义(整型) i = 0; // 给数组赋值 对于 (i = 0; i < 5; i = i + 1) { numbers[i] = (i + 1) * 10; } // 输出数组内容 控制台输出("数组内容:"); 对于 (i = 0; i < 5; i = i + 1) { 控制台输出("numbers[" + i + "] = " + numbers[i]); } // 数组计算 定义(整型) sum = 0; 对于 (i = 0; i < 5; i = i + 1) { sum = sum + numbers[i]; } 控制台输出("数组总和: " + sum); } ``` **运行结果:** ``` 数组内容: numbers[0] = 10 numbers[1] = 20 numbers[2] = 30 numbers[3] = 40 numbers[4] = 50 数组总和: 150 ``` ### 示例 7:文件操作 **文件名:** `examples/file_demo.ch` ```ch 定义(空类型) 主函数() { // 写入文件 定义(字符串) content = "Hello, File!"; 文件写入("test.txt", content); // 读取文件 定义(字符串) fileContent; 文件读取("test.txt", fileContent); 控制台输出("读取的内容: " + fileContent); // 追加内容 文件追加("test.txt", "\n这是追加的内容"); } ``` **运行结果:** ``` 读取的内容: Hello, File! ``` ### 示例 8:作用域限制 **文件名:** `examples/scope_test.ch` ```ch // 全局作用域:只能定义变量和结构体 定义(整型) globalVar = 100; 定义(结构体) GlobalStruct { 整型 value; }; 定义(空类型) 主函数() { // 函数内部可以执行各种操作 控制台输出("在函数内部可以执行各种操作"); 控制台输出("全局变量值: " + globalVar); // 函数内定义的变量 定义(整型) localVar = 50; 控制台输出("局部变量值: " + localVar); // 文件操作(只在函数内允许) 文件写入("test.txt", "这是函数内的操作"); } ``` **注意:** 如果在全局作用域中尝试执行文件读写等操作,会产生错误: ``` 在全局作用域中不允许执行此操作,只能定义变量或结构体 在第 X 行 ``` ## 字符编码支持 **ASCII码表适配:** - 完全支持ASCII字符(0-127) - 自动兼容中文字符(128+) - 支持UTF-8编码环境下的所有字符 **乱码修复实现原理:** 为确保中文关键字、中文输出内容和中文报错信息能正常显示,解释器在启动时会尝试设置中文 locale: 1. 首先尝试设置 `zh_CN.UTF-8` 编码的 locale 2. 如果失败,尝试设置 `Chinese` locale 3. 如果仍然失败,使用默认 locale 4. Windows环境下自动设置控制台代码页为65001(UTF-8) 这样可以保证在不同操作系统环境下(Windows、Linux、macOS)都能正确显示中文。 ## 核心功能 1. **中文关键字**:所有关键字全部使用中文,无任何英文关键字 2. **数据类型支持**: - 基础类型:整型、字符串、小数、布尔型 - 字面量:真、假(布尔型字面量) - 完整的布尔运算:&&、||、!运算符 3. **变量定义**:支持整型、字符串、小数、布尔型变量的定义与初始化 4. **多维数组支持**: - 支持1-5维数组,最多5维 - 语法类似C/C++:`定义(整型) arr[3][4][5];` - 完整的数组定义、初始化、访问和赋值功能 - 支持动态索引:`arr[i][j]` (i,j为变量) - 数组元素自动初始化为0 5. **函数定义**:支持无返回值和有返回值的函数定义 6. **函数重载**:支持同名函数不同参数类型 7. **函数作用域限制**:全局作用域只允许变量定义和结构体定义 8. **函数返回类型检查**:确保函数返回类型与定义一致 9. **智能类型系统**: - 整型运算返回整型(如:10 + 3 = 13) - 浮点数运算返回浮点数(如:3.14 * 2 = 6.28) - 混合运算支持类型自动转换 10. **布尔逻辑运算**: - 逻辑与:`&&` 运算符 - 逻辑或:`||` 运算符 - 逻辑非:`!` 运算符 - 比较运算:`<、>、<=、>=、==、!=`,返回布尔值 11. **基本运算**:支持加减乘除、取模、乘方、比较运算、逻辑运算 12. **控制台输入输出**:支持从控制台输入和输出变量值、字符串 13. **文件读写操作**: - 文件写入:创建或覆盖文件内容 - 文件读取:从文件读取内容到变量 - 文件追加:在文件末尾追加内容 - 支持复杂的表达式作为文件名和内容 14. **流程控制**:if-else if-else条件判断、while/for循环 15. **结构体支持**: - 结构体定义:使用 `定义(结构体)` 关键字 - 结构体变量:支持结构体类型的变量实例化 - 成员访问:通过 `.` 运算符访问结构体成员 - 成员赋值:支持直接对结构体成员进行赋值操作 - 完整类型支持:整型、字符串、小数、布尔型成员 16. **主函数机制**:以 `主函数()` 作为程序唯一入口 17. **ASCII兼容**:完全支持ASCII码表和中文字符 18. **精确错误定位**:所有错误都包含行号和列号信息 19. **严格错误处理**:移除所有"假设"和"简化处理",提供详细错误信息 ## 使用方法 ### 编译 #### 方式一:直接使用g++编译 ```bash # 编译chplus解释器 g++ main.cpp src/lexer/lexer.cpp src/parser/parser.cpp src/executor/interpreter.cpp -std=c++17 -o chplus.exe ``` #### 方式二:使用CMake编译(推荐) ```bash # 创建构建目录 mkdir build && cd build # 配置项目(Linux/MacOS) cmake .. # 配置项目(Windows MinGW) cmake -G "MinGW Makefiles" .. # 构建项目 cmake --build . # 运行程序 ./chplus.exe ../examples/hello.ch ``` #### 2. 代码格式化工具 chplus集成了智能代码格式化功能,支持: **自动格式化(默认):** - 修复松散格式(如 `定义( 空类型 )主函数( )` → `定义(空类型)主函数()`) - 标准化缩进和换行 - 中文符号自动转换为英文符号 - 保持语法错误不修改 - 智能换行:`{` 不换行,`}` 必须换行 **命令行选项:** -- `-a` : 自动格式化并覆盖原文件 -- `-d` : 启用调试模式,显示详细执行信息 -- `--no-format, -n` : 不自动格式化代码 -- `--help, -h` : 显示帮助信息 **格式化效果示例:** **输入(松散格式):** ```ch 定义( 空类型 )主函数( ) { 控制台输出 ( "Hello World" ) ; } ``` **输出(标准格式):** ```ch 定义(空类型)主函数(){ 控制台输出("Hello World"); } ``` ### 运行 ```bash # 标准运行(自动格式化) ./chplus.exe examples/hello.ch # 不自动格式化运行 ./chplus.exe --no-format examples/hello.ch # 查看帮助 ./chplus.exe --help ``` ## 错误处理 解释器的所有报错输出均使用中文,所有错误都包含精确的行号信息: **错误信息格式:** - 错误类型和具体原因 - 错误位置(行号) - 详细的错误说明 **示例错误信息:** ``` 错误: 变量未定义: x 在第 5 行 错误: 数组未定义: dp 在第 8 行 错误: 除零错误 在第 15 行 错误: 无效的数组索引: abc 在第 20 行 错误: 不支持的运算符: ^ 在第 25 行 错误: 函数未定义: add(整型, 整型) 在第 30 行 错误: 返回类型不匹配: 期望 整型,但实际返回 小数 在第 35 行 错误: 在全局作用域中不允许执行此操作,只能定义变量或结构体 在第 40 行 ``` **改进的错误检查:** - ✅ 变量存在性检查:访问未定义变量会报错 - ✅ 数组边界检查:防止访问不存在的数组元素 - ✅ 类型检查:确保运算类型兼容 - ✅ 除零检查:防止除零运算 - ✅ 语法错误检查:确保代码语法正确 - ✅ 函数重载检查:确保函数参数类型匹配 - ✅ 返回类型检查:确保函数返回类型与定义一致 - ✅ 作用域检查:确保全局作用域只允许定义操作 **严格的错误处理:** - 移除了所有"假设"和"简化处理"代码 - 添加了完整的类型验证 - 改进了数组操作的错误处理 - 优化了表达式求值的错误检测 - 添加了函数重载的错误处理 - 改进了返回类型检查 ## 注意事项 1. 解释器支持完整的数组功能和智能类型系统 2. 变量类型支持整型、字符串、小数、布尔型类型 3. 所有错误都有精确的行号定位 4. 建议使用 UTF-8 编码保存 `.ch` 文件,以避免字符编码问题 5. 结构体变量只能通过两种方式初始化:无初始化器(创建默认实例)或同类型变量赋值 6. 支持直接对结构体成员进行赋值操作 7. **函数作用域限制**:全局作用域(主函数外部)只能定义变量和结构体,不允许执行其他操作 8. **函数重载**:同名函数必须有不同的参数类型,调用时会自动选择合适的函数 9. **返回类型检查**:所有函数都必须严格遵守返回类型,不匹配会报错 10. **空类型函数**:可以使用返回语句退出函数,但不能返回值 ## 未来计划 1. 增加更多数据类型支持(如枚举类型等) 2. 完善函数参数列表的解析 3. 增加更多流程控制语句(如 switch 语句等) 4. 增加调试功能和断点支持 5. 优化性能,支持更大规模的程序 ## 许可证 本项目采用 **GNU AGPL v3.0 + Commons Clause 1.0** 协议授权,核心规则如下: 1. 🆓 个人非商业用途可自由使用、修改、分发 2. 🚫 禁止任何形式的商业使用(包括出售、出租、作为商业产品组件等) 3. 🔧 修改后的衍生作品必须: - 保留原项目版权和许可证信息 - 以相同协议开源并附带完整源代码 - 明确标注衍生作品与原项目的差异,并提供原项目源库链接 4. 📄 完整许可证内容请查看项目根目录下的 `LICENSE` 文件 原项目源库:[https://github.com/abcdefgjh-li/chplus]