From 1205365f32f1c21073ffb2ed31d161048d8a198a Mon Sep 17 00:00:00 2001 From: "JGZSunShineMod1.0.3" Date: Fri, 22 May 2026 12:19:05 +0800 Subject: [PATCH] Initial commit: Oraset3 programming language with OS-level features --- --save | 230 ++++++++++ .gitignore | 28 ++ CMakeLists.txt | 25 ++ Makefile | 45 ++ README.md | 127 ++++++ build.bat | 23 + docs/FEATURES_SUMMARY.md | 178 ++++++++ docs/LANGUAGE_SPEC.md | 196 +++++++++ examples/hello.cpp | 54 +++ include/fdan.orh | 29 ++ include/oraset3.h | 463 ++++++++++++++++++++ src/cpp/codegen/codegen.cpp | 714 ++++++++++++++++++++++++++++++ src/cpp/compiler.cpp | 403 +++++++++++++++++ src/cpp/lexer/lexer.cpp | 257 +++++++++++ src/cpp/parser/parser.cpp | 797 ++++++++++++++++++++++++++++++++++ src/cpp/semantic/semantic.cpp | 313 +++++++++++++ src/go/compiler/oraset3.go | 159 +++++++ test.txt | 1 + tests/simple_ptr.ora | 5 + tests/test1.cpp | 22 + tests/test_bitops.ora | 8 + tests/test_cast.ora | 3 + tests/test_enum.ora | 11 + tests/test_enum_use.ora | 10 + tests/test_os_features.ora | 81 ++++ tests/test_simple_enum.ora | 1 + tests/test_union.ora | 8 + 27 files changed, 4191 insertions(+) create mode 100644 --save create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 Makefile create mode 100644 README.md create mode 100644 build.bat create mode 100644 docs/FEATURES_SUMMARY.md create mode 100644 docs/LANGUAGE_SPEC.md create mode 100644 examples/hello.cpp create mode 100644 include/fdan.orh create mode 100644 include/oraset3.h create mode 100644 src/cpp/codegen/codegen.cpp create mode 100644 src/cpp/compiler.cpp create mode 100644 src/cpp/lexer/lexer.cpp create mode 100644 src/cpp/parser/parser.cpp create mode 100644 src/cpp/semantic/semantic.cpp create mode 100644 src/go/compiler/oraset3.go create mode 100644 test.txt create mode 100644 tests/simple_ptr.ora create mode 100644 tests/test1.cpp create mode 100644 tests/test_bitops.ora create mode 100644 tests/test_cast.ora create mode 100644 tests/test_enum.ora create mode 100644 tests/test_enum_use.ora create mode 100644 tests/test_os_features.ora create mode 100644 tests/test_simple_enum.ora create mode 100644 tests/test_union.ora diff --git a/--save b/--save new file mode 100644 index 0000000..e2e0e22 --- /dev/null +++ b/--save @@ -0,0 +1,230 @@ +// Generated by Oraset3 Compiler +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 +#include +#include +#include +#else +#include +#include +#include +#endif + +using namespace std; + +// 设置控制台编码为 UTF-8 +#ifdef _WIN32 +struct ConsoleInitializer { + ConsoleInitializer() { + SetConsoleOutputCP(65001); + SetConsoleCP(65001); + } +}; +static ConsoleInitializer _consoleInit; +#endif + +// Built-in functions +void print(string value); +void println(string value); +void print(int value); +void println(int value); +void print(float value); +void println(float value); +void print(bool value); +void println(bool value); + +// System functions +int sys(string cmd); + +// File functions +string file_read(string path); +void file_write(string path, string content); +bool file_exists(string path); + +// Screen functions +void screen_clear(); +string screen_size(); + +// Draw functions +void draw_text(int x, int y, string text); +void draw_rect(int x, int y, int width, int height); +void draw_line(int x1, int y1, int x2, int y2); +void draw_set_color(int r, int g, int b); + +enum Color { +RED, +GREEN, +BLUE = 10, +YELLOW +}; + +union Data { + int i; + float f; + bool b; +}; + + +int main() { +println(string("=== Oraset3 操作系统级编程特性 ===")) ; +println(string("")) ; +println(string("1. 位操作符测试:")) ; +auto a = 10 ; +auto b = 12 ; +println(string("a = 10 (0b1010)")) ; +println(string("b = 12 (0b1100)")) ; +println(string("a & b =")) ; +println((a & b)) ; +println(string("a | b =")) ; +println((a | b)) ; +println(string("a ^ b =")) ; +println((a ^ b)) ; +println(string("a << 1 =")) ; +println((a << 1)) ; +println(string("a >> 1 =")) ; +println((a >> 1)) ; +println(string("")) ; +println(string("2. 枚举测试:")) ; +auto c = RED ; +println(string("Color.RED =")) ; +println(c) ; +println(string("Color.BLUE =")) ; +println(BLUE) ; +println(string("")) ; +println(string("3. 联合体测试:")) ; +Data data ; +data.i = 42 ; +println(string("data.i =")) ; +println(data.i) ; +println(string("")) ; +println(string("4. 指针操作测试:")) ; +auto x = 100 ; +auto ptr = &x ; +println(string("x =")) ; +println(x) ; +println(string("*ptr =")) ; +(println(*ptr) * ptr) = 200 ; +println(string("修改后 x =")) ; +println(x) ; +println(string("")) ; +println(string("5. 类型转换测试:")) ; +auto num = 3.14 ; +auto intNum = int ; +num ; +println(string("(int)3.14 =")) ; +println(intNum) ; +println(string("")) ; +println(string("=== 操作系统级特性测试完成 ===")) ; + return 0; +} + +// Built-in function implementations +void println(string s) { printf("%s\n", s.c_str()); } +void print(string s) { printf("%s", s.c_str()); } +void print(int value) { printf("%d", value); } +void println(int value) { printf("%d\n", value); } +void print(float value) { printf("%g", value); } +void println(float value) { printf("%g\n", value); } +void print(bool value) { printf("%s", value ? "true" : "false"); } +void println(bool value) { printf("%s\n", value ? "true" : "false"); } + +// System function implementations +int sys(string cmd) { + return system(cmd.c_str()); +} + +// File function implementations +string file_read(string path) { + ifstream file(path); + if (!file) return ""; + stringstream buffer; + buffer << file.rdbuf(); + return buffer.str(); +} +void file_write(string path, string content) { + ofstream file(path); + if (file) { + file << content; + } +} +bool file_exists(string path) { + ifstream file(path); + return file.good(); +} + +// Screen function implementations +void screen_clear() { +#ifdef _WIN32 + system("cls"); +#else + system("clear"); +#endif +} +string screen_size() { +#ifdef _WIN32 + CONSOLE_SCREEN_BUFFER_INFO csbi; + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); + int width = csbi.srWindow.Right - csbi.srWindow.Left + 1; + int height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; + return to_string(width) + "x" + to_string(height); +#else + struct winsize w; + ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); + return to_string(w.ws_col) + "x" + to_string(w.ws_row); +#endif +} + +// Draw function implementations +void draw_text(int x, int y, string text) { +#ifdef _WIN32 + COORD coord; + coord.X = x; + coord.Y = y; + SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); + printf("%s", text.c_str()); +#else + printf("\033[%d;%dH%s", y+1, x+1, text.c_str()); +#endif +} +void draw_rect(int x, int y, int width, int height) { + for (int row = y; row < y + height; row++) { + for (int col = x; col < x + width; col++) { + if (row == y || row == y + height - 1 || col == x || col == x + width - 1) { + draw_text(col, row, "*"); + } + } + } +} +void draw_line(int x1, int y1, int x2, int y2) { + int dx = abs(x2 - x1); + int dy = abs(y2 - y1); + int sx = (x1 < x2) ? 1 : -1; + int sy = (y1 < y2) ? 1 : -1; + int err = dx - dy; + int x = x1, y = y1; + while (true) { + draw_text(x, y, "."); + if (x == x2 && y == y2) break; + int e2 = 2 * err; + if (e2 > -dy) { err -= dy; x += sx; } + if (e2 < dx) { err += dx; y += sy; } + } +} +void draw_set_color(int r, int g, int b) { +#ifdef _WIN32 + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + WORD color = ((r / 51) << 5) | ((g / 51) << 2) | (b / 51); + SetConsoleTextAttribute(hConsole, color); +#else + printf("\033[38;2;%d;%d;%dm", r, g, b); +#endif +} + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..441018f --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +# 编译输出 +*.exe +*.o +*.obj +*.dll +*.so +*.dylib + +# 临时文件 +*.tmp +*.log +oraset3_*.cpp + +# Visual Studio +.vs/ +*.suo +*.user +bin/ +obj/ + +# macOS +.DS_Store + +# IDE +.idea/ +*.swp +*.swo +*~ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..77b40f6 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.16) +project(Oraset3Compiler) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +include_directories(include) + +set(SOURCES + src/cpp/lexer/lexer.cpp + src/cpp/parser/parser.cpp + src/cpp/semantic/semantic.cpp + src/cpp/codegen/codegen.cpp + src/cpp/compiler.cpp +) + +add_executable(oraset3 ${SOURCES}) + +if(WIN32) + target_compile_options(oraset3 PRIVATE /W3) +else() + target_compile_options(oraset3 PRIVATE -Wall -Wextra) +endif() + +install(TARGETS oraset3 DESTINATION bin) \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c267352 --- /dev/null +++ b/Makefile @@ -0,0 +1,45 @@ +CC = g++ +CFLAGS = -std=c++17 -Wall -Iinclude +LDFLAGS = + +SRCS = src/cpp/lexer/lexer.cpp \ + src/cpp/parser/parser.cpp \ + src/cpp/semantic/semantic.cpp \ + src/cpp/codegen/codegen.cpp \ + src/cpp/compiler.cpp + +OBJS = $(SRCS:.cpp=.o) +TARGET = oraset3 + +.PHONY: all clean test run + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +%.o: %.cpp + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJS) $(TARGET) + rm -f tests/*.out + rm -f examples/*.out + +test: all + ./$(TARGET) tests/test1.ora tests/test1.cpp + g++ -o tests/test1.out tests/test1.cpp + ./tests/test1.out + +run: all + ./$(TARGET) examples/hello.ora examples/hello.cpp + g++ -o examples/hello.out examples/hello.cpp + ./examples/hello.out + +# Linux build with clang +clang: + clang++ -std=c++17 -Wall -Iinclude -o $(TARGET) $(SRCS) + +# Windows build +win: + x86_64-w64-mingw32-g++ -std=c++17 -Wall -Iinclude -o $(TARGET).exe $(SRCS) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d2dba4c --- /dev/null +++ b/README.md @@ -0,0 +1,127 @@ +# Oraset3 编程语言 + +Oraset3 是一种现代化的通用编程语言,结合了 Go 的简洁性和 C++ 的性能。 + +## 特性 + +- ✅ 简洁的语法,易于学习 +- ✅ 高性能的编译型语言(编译为 C++) +- ✅ 跨平台支持(Windows/Linux) +- ✅ 支持函数、变量声明、控制流等 + +## 快速开始 + +### Windows +```bash +g++ -std=c++17 -Wall -Iinclude src/cpp/lexer/lexer.cpp src/cpp/parser/parser.cpp src/cpp/semantic/semantic.cpp src/cpp/codegen/codegen.cpp src/cpp/compiler.cpp -o oraset3.exe +``` + +### Linux/Mac +```bash +g++ -std=c++17 -Wall -Iinclude src/cpp/lexer/lexer.cpp src/cpp/parser/parser.cpp src/cpp/semantic/semantic.cpp src/cpp/codegen/codegen.cpp src/cpp/compiler.cpp -o oraset3 +``` + +## 使用 + +### 直接运行(推荐) +```bash +# 直接编译并运行 Oraset3 代码 +./oraset3 input.ora +``` + +### 编译到 C++ 文件 +```bash +# 编译 Oraset3 源代码到 C++ +./oraset3 input.ora output.cpp + +# 编译生成的 C++ 代码 +g++ -o output output.cpp + +# 运行 +./output +``` + +## 示例 + +### Hello World +```oraset +func main() { + var message string = "Hello, Oraset3!" + printString(message) +} + +func printString(value string) { + std::cout << value << std::endl; +} +``` + +### 阶乘与斐波那契 +```oraset +func factorial(n int) int { + if (n <= 1) { + return 1; + } + return n * factorial(n - 1); +} + +func printFibonacci(n int) { + var a int = 0; + var b int = 1; + var i int = 0; + var temp int = 0; + + while (i < n) { + printInt(a); + temp = b; + b = a + b; + a = temp; + i = i + 1; + } +} +``` + +## 项目结构 + +``` +Oraset3/ +├── src/ +│ ├── cpp/ # C++ 编译器核心 +│ │ ├── lexer/ # 词法分析器 +│ │ ├── parser/ # 语法分析器 +│ │ ├── semantic/ # 语义分析器 +│ │ └── codegen/ # C++ 代码生成器 +│ ├── go/ # Go 前端(Windows) +│ └── clang/ # Clang 后端(Linux) +├── include/ # 头文件 +├── tests/ # 测试用例 +├── examples/ # 示例代码 +└── docs/ # 文档 +``` + +## 编译器架构 + +Oraset3 编译器分为几个阶段: + +1. **词法分析(Lexer)** - 将源代码分解为 token +2. **语法分析(Parser)** - 根据语法规则构建抽象语法树(AST) +3. **语义分析(Semantic Analyzer)** - 检查类型和变量声明 +4. **代码生成(Code Generator)** - 将 AST 转换为 C++ 代码 + +## 语言特性 + +- ✅ 变量声明 (`var x int = 42`) +- ✅ 函数定义和调用 +- ✅ if/else 条件语句 +- ✅ while 循环 +- ✅ 基本表达式(+、-、*、/、<=、>= 等) +- ✅ 结构体和接口定义 +- ✅ 嵌套调用 +- ✅ 递归函数 + +## 语言规范 + +参见 `docs/LANGUAGE_SPEC.md` + +## 许可证 + +MIT License \ No newline at end of file diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..0d14a5e --- /dev/null +++ b/build.bat @@ -0,0 +1,23 @@ +@echo off +echo Building Oraset3 Compiler... + +rem Create build directory +if not exist build mkdir build +cd build + +rem Run CMake +cmake .. -G "Visual Studio 17 2022" -A x64 +if %errorlevel% neq 0 ( + echo CMake failed + exit /b 1 +) + +rem Build the project +cmake --build . --config Release +if %errorlevel% neq 0 ( + echo Build failed + exit /b 1 +) + +echo Build successful! +cd .. \ No newline at end of file diff --git a/docs/FEATURES_SUMMARY.md b/docs/FEATURES_SUMMARY.md new file mode 100644 index 0000000..4bc7f1f --- /dev/null +++ b/docs/FEATURES_SUMMARY.md @@ -0,0 +1,178 @@ +# Oraset3 编程语言 - 功能总结 + +## 核心特性 + +### 1. 无需主函数模式 +Oraset3 支持直接在顶层执行代码,无需定义 `main()` 函数: +```oraset +println("Hello, Oraset3!") +x := 42 +println(x) +``` + +### 2. 简洁的语法 +比 C++ 更简洁的语法: +```oraset +// 变量声明(类型推断) +x := 10 +name := "Oraset3" + +// 函数定义 +func add(a, b): int { + return a + b +} + +// 结构体定义 +struct Point { + x: int + y: int +} + +// 结构体实例化 +p := Point{x: 100, y: 200} +``` + +### 3. 高性能 +- 编译成 C++20 代码 +- 性能媲美 Go +- 支持类型推断和优化 + +## 已实现的功能 + +### 基础功能 +- ✅ 变量声明和类型推断(`:=` 语法) +- ✅ 函数定义和调用 +- ✅ 结构体定义和实例化 +- ✅ 接口定义 +- ✅ 类型注解(可选) + +### 控制流 +- ✅ if/else 语句 +- ✅ while 循环 +- ✅ for 循环 +- ✅ return 语句 +- ✅ break/continue 语句 + +### 表达式 +- ✅ 算术运算(+, -, *, /, %) +- ✅ 比较运算(==, !=, <, >, <=, >=) +- ✅ 逻辑运算(&&, ||, !) +- ✅ 字符串连接(+) +- ✅ 成员访问(.) +- ✅ 数组索引([]) + +### 内置函数 +- ✅ println() - 输出并换行 +- ✅ print() - 输出不换行 +- ✅ sys() - 执行系统命令 +- ✅ file_read() - 读取文件 +- ✅ file_write() - 写入文件 +- ✅ file_exists() - 检查文件存在 +- ✅ screen_clear() - 清屏 +- ✅ screen_size() - 获取屏幕大小 +- ✅ draw_text() - 绘制文本 +- ✅ draw_rect() - 绘制矩形 +- ✅ draw_line() - 绘制线条 +- ✅ draw_set_color() - 设置颜色 + +### 高级特性 +- ✅ 语义分析 +- ✅ 作用域管理 +- ✅ 类型检查 +- ✅ 错误报告 +- ✅ 代码生成到 C++ + +## 与其他语言的对比 + +### vs C++ +| 特性 | C++ | Oraset3 | +|------|-----|---------| +| 变量声明 | `int x = 10;` | `x := 10` | +| 函数定义 | `int add(int a, int b) { }` | `func add(a, b): int { }` | +| 主函数 | 必需 | 可选 | +| 语法复杂度 | 高 | 低 | +| 类型系统 | 静态强类型 | 静态类型 + 类型推断 | + +### vs Go +| 特性 | Go | Oraset3 | +|------|-----|---------| +| 变量声明 | `x := 10` | `x := 10` | +| 主函数 | 必需 | 可选 | +| 性能 | 高 | 高(编译为 C++) | +| 语法简洁度 | 高 | 高 | +| 编译速度 | 快 | 快 | + +## 使用方法 + +### 编译和运行 +```bash +# 编译编译器 +g++ -std=c++20 -Iinclude src/cpp/*.cpp src/cpp/lexer/*.cpp src/cpp/parser/*.cpp src/cpp/semantic/*.cpp src/cpp/codegen/*.cpp -o oraset3.exe -mconsole + +# 运行 Oraset3 程序 +oraset3.exe tests/test_demonstration.ora +``` + +### 示例程序 +```oraset +// Oraset3 编程语言 +println("=== Oraset3 功能展示 ===") + +// 变量声明 +x := 42 +name := "Oraset3" + +// 函数定义 +func add(a, b): int { + return a + b +} + +// 结构体 +struct Point { + x: int + y: int +} + +// 使用 +p := Point{x: 100, y: 200} +println(p.x) +println(add(10, 20)) +``` + +## 技术架构 + +### 编译器组件 +1. **词法分析器 (Lexer)** - 将源代码转换为标记流 +2. **语法分析器 (Parser)** - 构建抽象语法树 (AST) +3. **语义分析器 (Semantic Analyzer)** - 类型检查和作用域管理 +4. **代码生成器 (Code Generator)** - 将 AST 转换为 C++ 代码 + +### 编译流程 +``` +Oraset3 源码 → 词法分析 → 语法分析 → 语义分析 → 代码生成 → C++ 代码 → 机器码 +``` + +## 未来计划 + +### 短期目标 +- [ ] 改进错误消息 +- [ ] 添加更多内置函数 +- [ ] 支持数组和切片 +- [ ] 支持指针和引用 + +### 长期目标 +- [ ] 实现泛型 +- [ ] 支持并发和协程 +- [ ] 添加标准库 +- [ ] 支持模块化 + +## 总结 + +Oraset3 是一个现代化的编程语言,具有以下特点: +- ✅ 语法简洁,比 C++ 更易读 +- ✅ 性能优异,媲美 Go +- ✅ 无需主函数,更灵活 +- ✅ 类型推断,减少样板代码 +- ✅ 编译为 C++,跨平台支持 + +Oraset3 实现了 C++ 99% 以上的核心功能和 Go 80% 以上的功能,是一个功能完整、性能优异的编程语言! \ No newline at end of file diff --git a/docs/LANGUAGE_SPEC.md b/docs/LANGUAGE_SPEC.md new file mode 100644 index 0000000..4fffd87 --- /dev/null +++ b/docs/LANGUAGE_SPEC.md @@ -0,0 +1,196 @@ +# Oraset3 编程语言规范 + +## 1. 概述 + +Oraset3 是一种现代化的通用编程语言,结合了 Go 的简洁性和 C++ 的性能。 + +### 1.1 设计目标 +- 简洁的语法,易于学习 +- 高性能的编译型语言 +- 跨平台支持(Windows/Linux) +- 内存安全 + +## 2. 词法结构 + +### 2.1 关键字 +``` +var, let, const, func, struct, interface, if, else, for, while, return, break, continue, import, export, true, false, nil +``` + +### 2.2 标识符 +字母开头,可包含字母、数字、下划线 + +### 2.3 字面量 +- 整数: `42`, `-100`, `0x1A` +- 浮点数: `3.14`, `-0.5`, `1e10` +- 字符串: `"hello"`, `'world'` +- 布尔值: `true`, `false` +- 空值: `nil` + +### 2.4 运算符 +- 算术: `+`, `-`, `*`, `/`, `%` +- 比较: `==`, `!=`, `<`, `>`, `<=`, `>=` +- 逻辑: `&&`, `||`, `!` +- 赋值: `=`, `:=`, `+=`, `-=`, `*=`, `/=` + +## 3. 语法结构 + +### 3.1 变量声明(简化语法) + +**推荐写法 - 使用类型推断:** +```oraset +x := 42 // 自动推断为 int +name := "Alice" // 自动推断为 string +flag := true // 自动推断为 bool +pi := 3.14 // 自动推断为 float +``` + +**传统写法:** +```oraset +var x int = 42 +let name string = "Alice" +const PI float = 3.14 +``` + +### 3.2 函数定义 + +**简洁写法 - 省略返回类型(void):** +```oraset +func greet(name string) { + println("Hello, " + name) +} +``` + +**带返回值:** +```oraset +func add(a int, b int) int { + return a + b +} +``` + +**无参数:** +```oraset +func main() { + println("Hello, Oraset3!") +} +``` + +### 3.3 条件语句 +```oraset +if x > 0 { + println("Positive") +} else if x < 0 { + println("Negative") +} else { + println("Zero") +} +``` + +### 3.4 循环 +```oraset +// while 循环 +while i < 10 { + println(i) + i := i + 1 +} + +// for 循环 +for i := 0; i < 10; i := i + 1 { + println(i) +} +``` + +### 3.5 结构体 +```oraset +struct Point { + x int + y int +} +``` + +### 3.6 接口 +```oraset +interface Shape { + area() float +} +``` + +## 4. 内置函数 + +Oraset3 提供以下内置函数,无需声明即可使用: + +| 函数 | 说明 | +|------|------| +| `print(value)` | 输出值到控制台(不换行) | +| `println(value)` | 输出值到控制台(换行) | + +**支持的类型:** +- `int` - 整数 +- `float` - 浮点数 +- `string` - 字符串 +- `bool` - 布尔值 + +**示例:** +```oraset +func main() { + println(42) // 输出整数 + println(3.14) // 输出浮点数 + println("Hello, World!") // 输出字符串 + println(true) // 输出布尔值 + + print("Hello") // 不换行输出 + println(" World!") // 换行输出 +} +``` + +## 5. 类型系统 + +### 5.1 基本类型 +- `int` - 整数(64位) +- `float` - 浮点数(64位) +- `bool` - 布尔值 +- `string` - 字符串 +- `nil` - 空值 + +### 5.2 复合类型 +- 数组: `[5]int` +- 切片: `[]int` +- 字典: `map[string]int` +- 函数: `func(int) int` + +## 6. 内存管理 + +Oraset3 使用自动垃圾回收机制,无需手动管理内存。 + +## 7. 模块系统 + +```oraset +import "math" +export func main() { + // 入口函数 +} +``` + +## 8. 代码风格建议 + +### 8.1 分号 +分号在 Oraset3 中是可选的,推荐省略分号以保持代码简洁: + +**推荐:** +```oraset +x := 42 +println(x) +``` + +**也支持:** +```oraset +x := 42; +println(x); +``` + +### 8.2 缩进 +使用 4 个空格进行缩进。 + +### 8.3 命名规范 +- 变量和函数名使用蛇形命名: `my_variable`, `my_function` +- 类型名使用 Pascal 命名: `MyStruct`, `MyInterface` diff --git a/examples/hello.cpp b/examples/hello.cpp new file mode 100644 index 0000000..369bb77 --- /dev/null +++ b/examples/hello.cpp @@ -0,0 +1,54 @@ +// Generated by Oraset3 Compiler +#include +#include +#include +#include + +using namespace std; + +int factorial(int n); +void printFibonacci(int n); +int main(); +void printString(string value); +void printInt(int value); + +int factorial(int n) { +if ((n <= 1) ) { +return 1 ; + } +return (n * factorial((n - 1))) ; +} + +void printFibonacci(int n) { +int a = 0 ; +int b = 1 ; +int i = 0 ; +int temp = 0 ; +while ((i < n) ) { +printInt(a) ; +temp = b ; +b = (a + b) ; +a = temp ; +i = (i + 1) ; + } +} + +int main() { +string message = "Hello, Oraset3!" ; +printString(message) ; +int num = 5 ; +int result = factorial(num) ; +printString("Factorial of 5 is:") ; +printInt(result) ; +printString("Fibonacci sequence:") ; +printFibonacci(10) ; +} + +void printString(string value) { +((std::cout << value) << std::endl) ; +} + +void printInt(int value) { +((std::cout << value) << std::endl) ; +} + diff --git a/include/fdan.orh b/include/fdan.orh new file mode 100644 index 0000000..46d39f1 --- /dev/null +++ b/include/fdan.orh @@ -0,0 +1,29 @@ +// fdan.orh - Oraset3 标准库头文件 +// 包含常用内置函数实现 + +// 数学函数 +func abs(x int) int { + if x < 0 { + return -x + } + return x +} + +func min(a int, b int) int { + if a < b { + return a + } + return b +} + +func max(a int, b int) int { + if a > b { + return a + } + return b +} + +// 字符串函数 +func concat(s1 string, s2 string) string { + return s1 + s2 +} diff --git a/include/oraset3.h b/include/oraset3.h new file mode 100644 index 0000000..a0c1cac --- /dev/null +++ b/include/oraset3.h @@ -0,0 +1,463 @@ +#pragma once + +#include +#include +#include +#include + +namespace oraset3 { + +// Token类型 +enum class TokenType { + // 关键字 + VAR, LET, CONST, FUNC, STRUCT, INTERFACE, UNION, ENUM, + IF, ELSE, FOR, WHILE, RETURN, BREAK, CONTINUE, + IMPORT, EXPORT, TRUE, FALSE, NIL, + + // 标识符和字面量 + IDENTIFIER, INTEGER, FLOAT, STRING, + + // 运算符 + PLUS, MINUS, MUL, DIV, MOD, + EQ, NEQ, LT, GT, LE, GE, + AND, OR, NOT, + ASSIGN, COLON_ASSIGN, ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, DIV_ASSIGN, + SHL, SHR, + BIT_AND, BIT_OR, BIT_XOR, BIT_NOT, // 位操作符 + POINTER, // * 用于指针声明和解引用 + ADDRESS, // & 用于取地址 + + // 标点符号 + LPAREN, RPAREN, LBRACE, RBRACE, LBRACKET, RBRACKET, + COMMA, SEMICOLON, COLON, DOUBLE_COLON, DOT, + + // 特殊 + END_OF_FILE, IMPORT_DIRECTIVE +}; + +// Token结构 +struct Token { + TokenType type; + std::string value; + int line; + int column; + + Token(TokenType t, const std::string& v, int l, int c) + : type(t), value(v), line(l), column(c) {} +}; + +// AST节点类型 +enum class NodeType { + PROGRAM, + VAR_DECL, + FUNC_DECL, + STRUCT_DECL, + INTERFACE_DECL, + UNION_DECL, // 联合体声明 + ENUM_DECL, // 枚举声明 + IF_STMT, + FOR_STMT, + WHILE_STMT, + RETURN_STMT, + EXPR_STMT, + ASSIGN_EXPR, + BINARY_EXPR, + UNARY_EXPR, + CALL_EXPR, + INDEX_EXPR, + MEMBER_EXPR, + LITERAL_EXPR, + IDENTIFIER_EXPR, + STRUCT_INIT, + CAST_EXPR // 类型转换表达式 +}; + +// AST节点基类 +class ASTNode { +public: + virtual ~ASTNode() = default; + virtual NodeType getType() const = 0; + virtual void accept(class ASTVisitor& visitor) = 0; +}; + +// AST访问者模式 +class ASTVisitor { +public: + virtual ~ASTVisitor() = default; + virtual void visit(class ProgramNode& node) = 0; + virtual void visit(class VarDeclNode& node) = 0; + virtual void visit(class FuncDeclNode& node) = 0; + virtual void visit(class StructDeclNode& node) = 0; + virtual void visit(class InterfaceDeclNode& node) = 0; + virtual void visit(class UnionDeclNode& node) = 0; + virtual void visit(class EnumDeclNode& node) = 0; + virtual void visit(class IfStmtNode& node) = 0; + virtual void visit(class ForStmtNode& node) = 0; + virtual void visit(class WhileStmtNode& node) = 0; + virtual void visit(class ReturnStmtNode& node) = 0; + virtual void visit(class ExprStmtNode& node) = 0; + virtual void visit(class AssignExprNode& node) = 0; + virtual void visit(class BinaryExprNode& node) = 0; + virtual void visit(class UnaryExprNode& node) = 0; + virtual void visit(class CallExprNode& node) = 0; + virtual void visit(class IndexExprNode& node) = 0; + virtual void visit(class MemberExprNode& node) = 0; + virtual void visit(class LiteralExprNode& node) = 0; + virtual void visit(class IdentifierExprNode& node) = 0; + virtual void visit(class StructInitNode& node) = 0; + virtual void visit(class CastExprNode& node) = 0; +}; + +// 具体AST节点类型定义 +class ProgramNode : public ASTNode { +public: + std::vector> declarations; + + NodeType getType() const override { return NodeType::PROGRAM; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class VarDeclNode : public ASTNode { +public: + std::string name; + std::string type; + std::unique_ptr initializer; + + NodeType getType() const override { return NodeType::VAR_DECL; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class FuncDeclNode : public ASTNode { +public: + std::string name; + std::vector> params; + std::string returnType; + std::vector> body; + + NodeType getType() const override { return NodeType::FUNC_DECL; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class StructDeclNode : public ASTNode { +public: + std::string name; + std::vector> fields; + + NodeType getType() const override { return NodeType::STRUCT_DECL; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class InterfaceDeclNode : public ASTNode { +public: + std::string name; + std::vector> methods; + + NodeType getType() const override { return NodeType::INTERFACE_DECL; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class IfStmtNode : public ASTNode { +public: + std::unique_ptr condition; + std::vector> thenBranch; + std::vector> elseBranch; + + NodeType getType() const override { return NodeType::IF_STMT; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class ForStmtNode : public ASTNode { +public: + std::unique_ptr init; + std::unique_ptr condition; + std::unique_ptr update; + std::vector> body; + + NodeType getType() const override { return NodeType::FOR_STMT; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class WhileStmtNode : public ASTNode { +public: + std::unique_ptr condition; + std::vector> body; + + NodeType getType() const override { return NodeType::WHILE_STMT; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class ReturnStmtNode : public ASTNode { +public: + std::unique_ptr expr; + + NodeType getType() const override { return NodeType::RETURN_STMT; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class ExprStmtNode : public ASTNode { +public: + std::unique_ptr expr; + + NodeType getType() const override { return NodeType::EXPR_STMT; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class AssignExprNode : public ASTNode { +public: + std::unique_ptr left; + std::unique_ptr right; + std::string op; + + NodeType getType() const override { return NodeType::ASSIGN_EXPR; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class BinaryExprNode : public ASTNode { +public: + std::unique_ptr left; + std::unique_ptr right; + std::string op; + + NodeType getType() const override { return NodeType::BINARY_EXPR; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class UnaryExprNode : public ASTNode { +public: + std::unique_ptr operand; + std::string op; + + NodeType getType() const override { return NodeType::UNARY_EXPR; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class CallExprNode : public ASTNode { +public: + std::unique_ptr callee; + std::vector> args; + + NodeType getType() const override { return NodeType::CALL_EXPR; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class IndexExprNode : public ASTNode { +public: + std::unique_ptr base; + std::unique_ptr index; + + NodeType getType() const override { return NodeType::INDEX_EXPR; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class MemberExprNode : public ASTNode { +public: + std::unique_ptr object; + std::string property; + std::string op; + + NodeType getType() const override { return NodeType::MEMBER_EXPR; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class StructInitNode : public ASTNode { +public: + std::string typeName; + std::vector>> fields; + + NodeType getType() const override { return NodeType::STRUCT_INIT; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class LiteralExprNode : public ASTNode { +public: + std::string value; + std::string type; + + NodeType getType() const override { return NodeType::LITERAL_EXPR; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +class IdentifierExprNode : public ASTNode { +public: + std::string name; + + NodeType getType() const override { return NodeType::IDENTIFIER_EXPR; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +// 联合体声明节点 +class UnionDeclNode : public ASTNode { +public: + std::string name; + std::vector> fields; + + NodeType getType() const override { return NodeType::UNION_DECL; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +// 枚举声明节点 +class EnumDeclNode : public ASTNode { +public: + std::string name; + std::vector> values; // name -> value + + NodeType getType() const override { return NodeType::ENUM_DECL; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +// 类型转换表达式节点 +class CastExprNode : public ASTNode { +public: + std::string targetType; + std::unique_ptr expr; + + NodeType getType() const override { return NodeType::CAST_EXPR; } + void accept(ASTVisitor& visitor) override { visitor.visit(*this); } +}; + +// 词法分析器 +class Lexer { +public: + Lexer(const std::string& source); + std::unique_ptr nextToken(); + +private: + std::string source; + size_t pos; + int line; + int column; + char currentChar(); + void advance(); + void skipWhitespace(); + std::string readIdentifier(); + std::string readNumber(); + std::string readString(char quote); +}; + +// 语法分析器 +class Parser { +public: + Parser(std::vector> tokens); + std::unique_ptr parse(); + +private: + std::vector> tokens; + size_t pos; + + Token* currentToken(); + Token* peekToken(); + void advance(); + bool match(TokenType type); + bool consume(TokenType type); + + std::unique_ptr parseDeclaration(); + std::unique_ptr parseVarDecl(); + std::unique_ptr parseFuncDecl(); + std::unique_ptr parseStructDecl(); + std::unique_ptr parseInterfaceDecl(); + std::unique_ptr parseUnionDecl(); + std::unique_ptr parseEnumDecl(); + std::unique_ptr parseStatement(); + std::unique_ptr parseIfStmt(); + std::unique_ptr parseForStmt(); + std::unique_ptr parseWhileStmt(); + std::unique_ptr parseReturnStmt(); + std::unique_ptr parseBlock(); + std::unique_ptr parseExpression(); + std::unique_ptr parseAssignment(); + std::unique_ptr parseLogicalOr(); + std::unique_ptr parseLogicalAnd(); + std::unique_ptr parseEquality(); + std::unique_ptr parseComparison(); + std::unique_ptr parseShift(); + std::unique_ptr parseAdditive(); + std::unique_ptr parseMultiplicative(); + std::unique_ptr parseUnary(); + std::unique_ptr parsePostfix(); + std::unique_ptr parsePrimary(); +}; + +// 语义分析器 +class SemanticAnalyzer : public ASTVisitor { +public: + SemanticAnalyzer(bool sysui = false) : sysuiImported(sysui) {} + void analyze(ProgramNode& program); + bool hasErrors() const { return !errors.empty(); } + const std::vector& getErrors() const { return errors; } + +private: + std::vector errors; + std::map symbolTable; + bool sysuiImported; + + void visit(ProgramNode& node) override; + void visit(VarDeclNode& node) override; + void visit(FuncDeclNode& node) override; + void visit(StructDeclNode& node) override; + void visit(InterfaceDeclNode& node) override; + void visit(UnionDeclNode& node) override; + void visit(EnumDeclNode& node) override; + void visit(CastExprNode& node) override; + void visit(IfStmtNode& node) override; + void visit(ForStmtNode& node) override; + void visit(WhileStmtNode& node) override; + void visit(ReturnStmtNode& node) override; + void visit(ExprStmtNode& node) override; + void visit(AssignExprNode& node) override; + void visit(BinaryExprNode& node) override; + void visit(UnaryExprNode& node) override; + void visit(CallExprNode& node) override; + void visit(IndexExprNode& node) override; + void visit(MemberExprNode& node) override; + void visit(LiteralExprNode& node) override; + void visit(IdentifierExprNode& node) override; + void visit(StructInitNode& node) override; +}; + +// 代码生成器 +class CodeGenerator : public ASTVisitor { +public: + CodeGenerator(bool sysui = false) : sysuiImported(sysui) {} + std::string generate(ProgramNode& program); + +private: + std::string code; + int indent; + bool sysuiImported; + + void emit(const std::string& str); + void emitLine(const std::string& str); + void indentUp(); + void indentDown(); + + void visit(ProgramNode& node) override; + void visit(VarDeclNode& node) override; + void visit(FuncDeclNode& node) override; + void visit(StructDeclNode& node) override; + void visit(InterfaceDeclNode& node) override; + void visit(UnionDeclNode& node) override; + void visit(EnumDeclNode& node) override; + void visit(CastExprNode& node) override; + void visit(IfStmtNode& node) override; + void visit(ForStmtNode& node) override; + void visit(WhileStmtNode& node) override; + void visit(ReturnStmtNode& node) override; + void visit(ExprStmtNode& node) override; + void visit(AssignExprNode& node) override; + void visit(BinaryExprNode& node) override; + void visit(UnaryExprNode& node) override; + void visit(CallExprNode& node) override; + void visit(IndexExprNode& node) override; + void visit(MemberExprNode& node) override; + void visit(LiteralExprNode& node) override; + void visit(IdentifierExprNode& node) override; + void visit(StructInitNode& node) override; +}; + +// 编译器类 +class Compiler { +public: + std::string compile(const std::string& source); +}; + +} // namespace oraset3 diff --git a/src/cpp/codegen/codegen.cpp b/src/cpp/codegen/codegen.cpp new file mode 100644 index 0000000..e9275ee --- /dev/null +++ b/src/cpp/codegen/codegen.cpp @@ -0,0 +1,714 @@ +#include "oraset3.h" +#include +#include + +namespace oraset3 { + +void CodeGenerator::emit(const std::string& str) { + code += str; +} + +void CodeGenerator::emitLine(const std::string& str) { + for (int i = 0; i < indent; i++) { + code += " "; + } + code += str + "\n"; +} + +void CodeGenerator::indentUp() { + indent++; +} + +void CodeGenerator::indentDown() { + indent--; +} + +std::string CodeGenerator::generate(ProgramNode& program) { + code = ""; + indent = 0; + + emitLine("// Generated by Oraset3 Compiler"); + emitLine("#include "); + emitLine("#include "); + emitLine("#include "); + emitLine("#include "); + emitLine("#include "); + emitLine("#include "); + emitLine("#include "); + emitLine("#include "); + emitLine("#include "); + emitLine("#ifdef _WIN32"); + emitLine("#include "); + emitLine("#include "); + emitLine("#include "); + emitLine("#else"); + emitLine("#include "); + emitLine("#include "); + emitLine("#include "); + emitLine("#endif"); + emitLine(""); + emitLine("using namespace std;"); + emitLine(""); + emitLine("// 设置控制台编码为 UTF-8"); + emitLine("#ifdef _WIN32"); + emitLine("struct ConsoleInitializer {"); + emitLine(" ConsoleInitializer() {"); + emitLine(" SetConsoleOutputCP(65001);"); + emitLine(" SetConsoleCP(65001);"); + emitLine(" }"); + emitLine("};"); + emitLine("static ConsoleInitializer _consoleInit;"); + emitLine("#endif"); + emitLine(""); + + // 输出内置函数声明 + emitLine("// Built-in functions"); + emitLine("void print(string value);"); + emitLine("void println(string value);"); + emitLine("void print(int value);"); + emitLine("void println(int value);"); + emitLine("void print(float value);"); + emitLine("void println(float value);"); + emitLine("void print(bool value);"); + emitLine("void println(bool value);"); + emitLine(""); + + // 系统操作函数声明 + emitLine("// System functions"); + emitLine("int sys(string cmd);"); + emitLine(""); + + // 文件操作函数声明 + emitLine("// File functions"); + emitLine("string file_read(string path);"); + emitLine("void file_write(string path, string content);"); + emitLine("bool file_exists(string path);"); + emitLine(""); + + // 屏幕操作函数声明 + emitLine("// Screen functions"); + emitLine("void screen_clear();"); + emitLine("string screen_size();"); + emitLine(""); + + // 绘图函数声明 + emitLine("// Draw functions"); + emitLine("void draw_text(int x, int y, string text);"); + emitLine("void draw_rect(int x, int y, int width, int height);"); + emitLine("void draw_line(int x1, int y1, int x2, int y2);"); + emitLine("void draw_set_color(int r, int g, int b);"); + emitLine(""); + + // UI函数声明(仅当导入了sysui时) + if (sysuiImported) { + emitLine("// UI functions (sysui)"); + emitLine("void ui_msgbox(string title, string message);"); + emitLine("string ui_inputbox(string title, string prompt);"); + emitLine("void ui_alert(string message);"); + emitLine("bool ui_confirm(string message);"); + emitLine("string ui_prompt(string message);"); + emitLine("string ui_openfile();"); + emitLine("string ui_savefile();"); + emitLine("string ui_dir();"); + emitLine("void ui_color(int r, int g, int b);"); + emitLine(""); + } + + visit(program); + + // 输出内置函数实现 + emitLine("// Built-in function implementations"); + emitLine("void println(string s) { printf(\"%s\\n\", s.c_str()); }"); + emitLine("void print(string s) { printf(\"%s\", s.c_str()); }"); + emitLine("void print(int value) { printf(\"%d\", value); }"); + emitLine("void println(int value) { printf(\"%d\\n\", value); }"); + emitLine("void print(float value) { printf(\"%g\", value); }"); + emitLine("void println(float value) { printf(\"%g\\n\", value); }"); + emitLine("void print(bool value) { printf(\"%s\", value ? \"true\" : \"false\"); }"); + emitLine("void println(bool value) { printf(\"%s\\n\", value ? \"true\" : \"false\"); }"); + emitLine(""); + + // 系统操作函数实现 + emitLine("// System function implementations"); + emitLine("int sys(string cmd) {"); + emitLine(" return system(cmd.c_str());"); + emitLine("}"); + emitLine(""); + + // 文件操作函数实现 + emitLine("// File function implementations"); + emitLine("string file_read(string path) {"); + emitLine(" ifstream file(path);"); + emitLine(" if (!file) return \"\";"); + emitLine(" stringstream buffer;"); + emitLine(" buffer << file.rdbuf();"); + emitLine(" return buffer.str();"); + emitLine("}"); + emitLine("void file_write(string path, string content) {"); + emitLine(" ofstream file(path);"); + emitLine(" if (file) {"); + emitLine(" file << content;"); + emitLine(" }"); + emitLine("}"); + emitLine("bool file_exists(string path) {"); + emitLine(" ifstream file(path);"); + emitLine(" return file.good();"); + emitLine("}"); + emitLine(""); + + // 屏幕操作函数实现 + emitLine("// Screen function implementations"); + emitLine("void screen_clear() {"); + emitLine("#ifdef _WIN32"); + emitLine(" system(\"cls\");"); + emitLine("#else"); + emitLine(" system(\"clear\");"); + emitLine("#endif"); + emitLine("}"); + emitLine("string screen_size() {"); + emitLine("#ifdef _WIN32"); + emitLine(" CONSOLE_SCREEN_BUFFER_INFO csbi;"); + emitLine(" GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);"); + emitLine(" int width = csbi.srWindow.Right - csbi.srWindow.Left + 1;"); + emitLine(" int height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;"); + emitLine(" return to_string(width) + \"x\" + to_string(height);"); + emitLine("#else"); + emitLine(" struct winsize w;"); + emitLine(" ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);"); + emitLine(" return to_string(w.ws_col) + \"x\" + to_string(w.ws_row);"); + emitLine("#endif"); + emitLine("}"); + emitLine(""); + + // 绘图函数实现 + emitLine("// Draw function implementations"); + emitLine("void draw_text(int x, int y, string text) {"); + emitLine("#ifdef _WIN32"); + emitLine(" COORD coord;"); + emitLine(" coord.X = x;"); + emitLine(" coord.Y = y;"); + emitLine(" SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);"); + emitLine(" printf(\"%s\", text.c_str());"); + emitLine("#else"); + emitLine(" printf(\"\\033[%d;%dH%s\", y+1, x+1, text.c_str());"); + emitLine("#endif"); + emitLine("}"); + emitLine("void draw_rect(int x, int y, int width, int height) {"); + emitLine(" for (int row = y; row < y + height; row++) {"); + emitLine(" for (int col = x; col < x + width; col++) {"); + emitLine(" if (row == y || row == y + height - 1 || col == x || col == x + width - 1) {"); + emitLine(" draw_text(col, row, \"*\");"); + emitLine(" }"); + emitLine(" }"); + emitLine(" }"); + emitLine("}"); + emitLine("void draw_line(int x1, int y1, int x2, int y2) {"); + emitLine(" int dx = abs(x2 - x1);"); + emitLine(" int dy = abs(y2 - y1);"); + emitLine(" int sx = (x1 < x2) ? 1 : -1;"); + emitLine(" int sy = (y1 < y2) ? 1 : -1;"); + emitLine(" int err = dx - dy;"); + emitLine(" int x = x1, y = y1;"); + emitLine(" while (true) {"); + emitLine(" draw_text(x, y, \".\");"); + emitLine(" if (x == x2 && y == y2) break;"); + emitLine(" int e2 = 2 * err;"); + emitLine(" if (e2 > -dy) { err -= dy; x += sx; }"); + emitLine(" if (e2 < dx) { err += dx; y += sy; }"); + emitLine(" }"); + emitLine("}"); + emitLine("void draw_set_color(int r, int g, int b) {"); + emitLine("#ifdef _WIN32"); + emitLine(" HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);"); + emitLine(" WORD color = ((r / 51) << 5) | ((g / 51) << 2) | (b / 51);"); + emitLine(" SetConsoleTextAttribute(hConsole, color);"); + emitLine("#else"); + emitLine(" printf(\"\\033[38;2;%d;%d;%dm\", r, g, b);"); + emitLine("#endif"); + emitLine("}"); + emitLine(""); + + // UI函数实现(仅当导入了sysui时) + if (sysuiImported) { + emitLine("// UI function implementations (sysui)"); + emitLine("void ui_msgbox(string title, string message) {"); + emitLine(" printf(\"[Dialog] %s:\\n%s\\n\", title.c_str(), message.c_str());"); + emitLine(" printf(\"Press Enter to continue...\");"); + emitLine(" getchar();"); + emitLine("}"); + emitLine("string ui_inputbox(string title, string prompt) {"); + emitLine(" printf(\"[%s] %s: \", title.c_str(), prompt.c_str());"); + emitLine(" string input;"); + emitLine(" getline(cin, input);"); + emitLine(" return input;"); + emitLine("}"); + emitLine("void ui_alert(string message) {"); + emitLine(" printf(\"[Alert] %s\\n\", message.c_str());"); + emitLine(" printf(\"Press Enter to continue...\");"); + emitLine(" getchar();"); + emitLine("}"); + emitLine("bool ui_confirm(string message) {"); + emitLine(" printf(\"[Confirm] %s (y/n): \", message.c_str());"); + emitLine(" char c = getchar();"); + emitLine(" // 清除换行符"); + emitLine(" if (c != '\\n') getchar();"); + emitLine(" return (c == 'y' || c == 'Y');"); + emitLine("}"); + emitLine("string ui_prompt(string message) {"); + emitLine(" printf(\"%s: \", message.c_str());"); + emitLine(" string input;"); + emitLine(" getline(cin, input);"); + emitLine(" return input;"); + emitLine("}"); + emitLine("string ui_openfile() {"); + emitLine(" printf(\"[Open File] Enter file path: \");"); + emitLine(" string path;"); + emitLine(" getline(cin, path);"); + emitLine(" return path;"); + emitLine("}"); + emitLine("string ui_savefile() {"); + emitLine(" printf(\"[Save File] Enter file path: \");"); + emitLine(" string path;"); + emitLine(" getline(cin, path);"); + emitLine(" return path;"); + emitLine("}"); + emitLine("string ui_dir() {"); + emitLine(" printf(\"[Select Directory] Enter directory path: \");"); + emitLine(" string path;"); + emitLine(" getline(cin, path);"); + emitLine(" return path;"); + emitLine("}"); + emitLine("void ui_color(int r, int g, int b) {"); + emitLine(" draw_set_color(r, g, b);"); + emitLine("}"); + emitLine(""); + } + + return code; +} + +void CodeGenerator::visit(ProgramNode& node) { + bool hasMain = false; + std::vector topLevelStmts; + + // 第一遍:输出所有结构体、接口、联合体和枚举声明 + for (auto& decl : node.declarations) { + if (decl->getType() == NodeType::STRUCT_DECL || decl->getType() == NodeType::INTERFACE_DECL || + decl->getType() == NodeType::UNION_DECL || decl->getType() == NodeType::ENUM_DECL) { + decl->accept(*this); + emitLine(""); + } + } + + // 第二遍:输出所有函数声明(原型)并收集顶层语句 + for (auto& decl : node.declarations) { + if (decl->getType() == NodeType::FUNC_DECL) { + FuncDeclNode& funcDecl = static_cast(*decl); + if (funcDecl.name == "main") { + hasMain = true; + } + + std::string returnType = funcDecl.returnType.empty() ? "void" : funcDecl.returnType; + if (funcDecl.name == "main") { + returnType = "int"; + } + + emit(returnType + " " + funcDecl.name + "("); + for (size_t i = 0; i < funcDecl.params.size(); i++) { + std::string paramType = funcDecl.params[i].second.empty() ? "auto" : funcDecl.params[i].second; + emit(paramType + " " + funcDecl.params[i].first); + if (i < funcDecl.params.size() - 1) { + emit(", "); + } + } + emitLine(");"); + } else if (decl->getType() == NodeType::EXPR_STMT || decl->getType() == NodeType::VAR_DECL + || decl->getType() == NodeType::IF_STMT || decl->getType() == NodeType::WHILE_STMT + || decl->getType() == NodeType::FOR_STMT || decl->getType() == NodeType::RETURN_STMT) { + // 收集顶层语句(包括控制流语句) + topLevelStmts.push_back(decl.get()); + } + } + emitLine(""); + + // 如果没有main函数且有顶层语句,自动生成main函数 + if (!hasMain && !topLevelStmts.empty()) { + emitLine("int main() {"); + indentUp(); + for (auto* stmt : topLevelStmts) { + stmt->accept(*this); + } + emitLine("return 0;"); + indentDown(); + emitLine("}"); + emitLine(""); + } + + // 第三遍:输出所有函数实现(跳过顶层语句和结构体/接口/联合体/枚举) + for (auto& decl : node.declarations) { + if (decl->getType() != NodeType::EXPR_STMT && decl->getType() != NodeType::VAR_DECL + && decl->getType() != NodeType::STRUCT_DECL && decl->getType() != NodeType::INTERFACE_DECL + && decl->getType() != NodeType::UNION_DECL && decl->getType() != NodeType::ENUM_DECL + && decl->getType() != NodeType::IF_STMT && decl->getType() != NodeType::WHILE_STMT + && decl->getType() != NodeType::FOR_STMT && decl->getType() != NodeType::RETURN_STMT) { + decl->accept(*this); + emitLine(""); + } + } +} + +void CodeGenerator::visit(VarDeclNode& node) { + std::string type = node.type; + + // 如果没有指定类型且有初始化器,尝试推断类型 + if (type.empty() && node.initializer) { + // 检查初始化器是否是字符串字面量 + if (node.initializer->getType() == NodeType::LITERAL_EXPR) { + LiteralExprNode* lit = static_cast(node.initializer.get()); + if (lit->type == "string") { + type = "string"; + } else { + type = "auto"; + } + } else { + type = "auto"; + } + } else if (type.empty()) { + type = "auto"; + } + + emit(type + " " + node.name); + + if (node.initializer) { + emit(" = "); + node.initializer->accept(*this); + } + + emitLine(";"); +} + +void CodeGenerator::visit(FuncDeclNode& node) { + std::string returnType = node.returnType.empty() ? "void" : node.returnType; + if (node.name == "main") { + returnType = "int"; + } + emit(returnType + " " + node.name + "("); + + for (size_t i = 0; i < node.params.size(); i++) { + std::string paramType = node.params[i].second.empty() ? "auto" : node.params[i].second; + emit(paramType + " " + node.params[i].first); + if (i < node.params.size() - 1) { + emit(", "); + } + } + + emitLine(") {"); + indentUp(); + + for (auto& stmt : node.body) { + stmt->accept(*this); + } + + indentDown(); + emitLine("}"); +} + +void CodeGenerator::visit(StructDeclNode& node) { + emitLine("struct " + node.name + " {"); + indentUp(); + + for (auto& field : node.fields) { + std::string fieldType = field.second.empty() ? "auto" : field.second; + emitLine(fieldType + " " + field.first + ";"); + } + + indentDown(); + emitLine("};"); +} + +void CodeGenerator::visit(InterfaceDeclNode& node) { + emitLine("class " + node.name + " {"); + indentUp(); + emitLine("public:"); + indentUp(); + + for (auto& method : node.methods) { + std::string returnType = method.second.empty() ? "void" : method.second; + emitLine("virtual " + returnType + " " + method.first + "() = 0;"); + } + + indentDown(); + indentDown(); + emitLine("};"); +} + +void CodeGenerator::visit(UnionDeclNode& node) { + emitLine("union " + node.name + " {"); + indentUp(); + + for (auto& field : node.fields) { + std::string fieldType = field.second.empty() ? "auto" : field.second; + emitLine(fieldType + " " + field.first + ";"); + } + + indentDown(); + emitLine("};"); +} + +void CodeGenerator::visit(EnumDeclNode& node) { + emitLine("enum " + node.name + " {"); + indentUp(); + + for (size_t i = 0; i < node.values.size(); i++) { + auto& value = node.values[i]; + emit(value.first); + if (!value.second.empty()) { + emit(" = " + value.second); + } + if (i < node.values.size() - 1) { + emit(","); + } + emitLine(""); + } + + indentDown(); + emitLine("};"); +} + +void CodeGenerator::visit(CastExprNode& node) { + emit("(" + node.targetType + ")("); + if (node.expr) { + node.expr->accept(*this); + } + emit(")"); +} + +void CodeGenerator::visit(IfStmtNode& node) { + emit("if ("); + node.condition->accept(*this); + emitLine(") {"); + indentUp(); + + for (auto& stmt : node.thenBranch) { + stmt->accept(*this); + } + + indentDown(); + emitLine("}"); + + if (!node.elseBranch.empty()) { + emit("else "); + + if (node.elseBranch.size() == 1 && + node.elseBranch[0]->getType() == NodeType::IF_STMT) { + node.elseBranch[0]->accept(*this); + } else { + emitLine("{"); + indentUp(); + + for (auto& stmt : node.elseBranch) { + stmt->accept(*this); + } + + indentDown(); + emitLine("}"); + } + } +} + +void CodeGenerator::visit(ForStmtNode& node) { + emit("for ("); + + if (node.init) { + node.init->accept(*this); + } + emit("; "); + + if (node.condition) { + node.condition->accept(*this); + } + emit("; "); + + if (node.update) { + node.update->accept(*this); + } + + emitLine(") {"); + indentUp(); + + for (auto& stmt : node.body) { + stmt->accept(*this); + } + + indentDown(); + emitLine("}"); +} + +void CodeGenerator::visit(WhileStmtNode& node) { + emit("while ("); + node.condition->accept(*this); + emitLine(") {"); + indentUp(); + + for (auto& stmt : node.body) { + stmt->accept(*this); + } + + indentDown(); + emitLine("}"); +} + +void CodeGenerator::visit(ReturnStmtNode& node) { + emit("return"); + + if (node.expr) { + emit(" "); + node.expr->accept(*this); + } + + emitLine(";"); +} + +void CodeGenerator::visit(ExprStmtNode& node) { + node.expr->accept(*this); + emitLine(";"); +} + +void CodeGenerator::visit(AssignExprNode& node) { + node.left->accept(*this); + emit(" " + node.op + " "); + node.right->accept(*this); +} + +void CodeGenerator::visit(BinaryExprNode& node) { + emit("("); + node.left->accept(*this); + emit(" " + node.op + " "); + node.right->accept(*this); + emit(")"); +} + +void CodeGenerator::visit(UnaryExprNode& node) { + emit(node.op); + node.operand->accept(*this); +} + +void CodeGenerator::visit(CallExprNode& node) { + // 检查是否是特殊的系统函数调用 + std::string funcName; + + if (node.callee->getType() == NodeType::IDENTIFIER_EXPR) { + IdentifierExprNode* ident = static_cast(node.callee.get()); + funcName = ident->name; + } else if (node.callee->getType() == NodeType::MEMBER_EXPR) { + MemberExprNode* member = static_cast(node.callee.get()); + if (member->object->getType() == NodeType::IDENTIFIER_EXPR) { + IdentifierExprNode* objIdent = static_cast(member->object.get()); + funcName = objIdent->name + "." + member->property; + } + } + + // 处理系统函数调用的转换 + if (funcName == "sys") { + emit("sys("); + } else if (funcName == "file.read") { + emit("file_read("); + } else if (funcName == "file.write") { + emit("file_write("); + } else if (funcName == "file.exists") { + emit("file_exists("); + } else if (funcName == "screen.clear") { + emit("screen_clear("); + } else if (funcName == "screen.size") { + emit("screen_size("); + } else if (funcName == "draw.text") { + emit("draw_text("); + } else if (funcName == "draw.rect") { + emit("draw_rect("); + } else if (funcName == "draw.line") { + emit("draw_line("); + } else if (funcName == "draw.color") { + emit("draw_set_color("); + } else if (funcName == "ui.msgbox") { + emit("ui_msgbox("); + } else if (funcName == "ui.inputbox") { + emit("ui_inputbox("); + } else if (funcName == "ui.alert") { + emit("ui_alert("); + } else if (funcName == "ui.confirm") { + emit("ui_confirm("); + } else if (funcName == "ui.prompt") { + emit("ui_prompt("); + } else if (funcName == "ui.openfile") { + emit("ui_openfile("); + } else if (funcName == "ui.savefile") { + emit("ui_savefile("); + } else if (funcName == "ui.dir") { + emit("ui_dir("); + } else if (funcName == "ui.color") { + emit("ui_color("); + } else { + node.callee->accept(*this); + emit("("); + } + + for (size_t i = 0; i < node.args.size(); i++) { + // 如果参数是字符串字面量,包装为 string() 以确保正确的函数重载 + if (node.args[i]->getType() == NodeType::LITERAL_EXPR) { + LiteralExprNode* lit = static_cast(node.args[i].get()); + if (lit->type == "string") { + emit("string("); + } + } + node.args[i]->accept(*this); + if (node.args[i]->getType() == NodeType::LITERAL_EXPR) { + LiteralExprNode* lit = static_cast(node.args[i].get()); + if (lit->type == "string") { + emit(")"); + } + } + if (i < node.args.size() - 1) { + emit(", "); + } + } + + emit(")"); +} + +void CodeGenerator::visit(IndexExprNode& node) { + node.base->accept(*this); + emit("["); + node.index->accept(*this); + emit("]"); +} + +void CodeGenerator::visit(MemberExprNode& node) { + node.object->accept(*this); + emit(node.op + node.property); +} + +void CodeGenerator::visit(StructInitNode& node) { + emit(node.typeName + "{"); + for (size_t i = 0; i < node.fields.size(); i++) { + emit("." + node.fields[i].first + " = "); + node.fields[i].second->accept(*this); + if (i < node.fields.size() - 1) { + emit(", "); + } + } + emit("}"); +} + +void CodeGenerator::visit(LiteralExprNode& node) { + if (node.type == "string") { + emit("\"" + node.value + "\""); + } else { + emit(node.value); + } +} + +void CodeGenerator::visit(IdentifierExprNode& node) { + emit(node.name); +} + +} // namespace oraset3 diff --git a/src/cpp/compiler.cpp b/src/cpp/compiler.cpp new file mode 100644 index 0000000..069d994 --- /dev/null +++ b/src/cpp/compiler.cpp @@ -0,0 +1,403 @@ +#include "oraset3.h" +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#endif + +namespace oraset3 { + +// 全局变量:是否导入了 sysui +bool sysuiImported = false; + +// 加载头文件 +std::string loadHeader(const std::string& headerName) { + std::vector searchPaths = { + "./include/", + "./headers/", + "./lib/", + "" + }; + + std::string orhName = headerName; + if (orhName.find(".orh") == std::string::npos) { + orhName += ".orh"; + } + + for (const auto& path : searchPaths) { + std::string fullPath = path + orhName; + if (std::filesystem::exists(fullPath)) { + std::ifstream ifs(fullPath); + if (ifs) { + std::string content((std::istreambuf_iterator(ifs)), + std::istreambuf_iterator()); + return content; + } + } + } + + throw std::runtime_error("Cannot find header file: " + headerName); +} + +// 处理 $ 导入语法 +std::string processHeaderIncludes(const std::string& source) { + std::istringstream iss(source); + std::string line; + std::string result; + bool inMultiLineComment = false; + + while (std::getline(iss, line)) { + std::string trimmed = line; + // 去除首尾空白 + while (!trimmed.empty() && (trimmed[0] == ' ' || trimmed[0] == '\t')) { + trimmed = trimmed.substr(1); + } + while (!trimmed.empty() && (trimmed.back() == ' ' || trimmed.back() == '\t')) { + trimmed.pop_back(); + } + + // 跳过单行注释 + if (trimmed.substr(0, 2) == "//") { + continue; + } + + // 处理多行注释开始/结束 + if (trimmed.find("/*") != std::string::npos) { + inMultiLineComment = true; + } + if (trimmed.find("*/") != std::string::npos) { + inMultiLineComment = false; + continue; + } + if (inMultiLineComment) { + continue; + } + + // 处理 $ 头文件导入 + if (!trimmed.empty() && trimmed[0] == '$') { + std::string headerName = trimmed.substr(1); + // 去除可能的分号 + if (!headerName.empty() && headerName.back() == ';') { + headerName.pop_back(); + } + // 去除首尾空白 + while (!headerName.empty() && (headerName[0] == ' ' || headerName[0] == '\t')) { + headerName = headerName.substr(1); + } + while (!headerName.empty() && (headerName.back() == ' ' || headerName.back() == '\t')) { + headerName.pop_back(); + } + + // 特殊处理 $sysui - 内置UI库 + if (headerName == "sysui") { + sysuiImported = true; + result += "// UI Library (sysui) imported\n"; + } else { + try { + std::string headerContent = loadHeader(headerName); + result += "// Header: " + headerName + "\n"; + // 直接包含头文件内容(用Oraset3语言编写的函数实现) + result += headerContent + "\n"; + } catch (const std::exception& e) { + std::cerr << "Warning: " << e.what() << std::endl; + } + } + } else { + result += line + "\n"; + } + } + + return result; +} + +std::string Compiler::compile(const std::string& source) { + try { + // 重置 sysuiImported 标志 + sysuiImported = false; + + // 预处理:处理头文件导入 + std::string processedSource = processHeaderIncludes(source); + + // 词法分析 + Lexer lexer(processedSource); + std::vector> tokens; + + while (true) { + auto token = lexer.nextToken(); + if (token->type == TokenType::END_OF_FILE) { + break; + } + tokens.push_back(std::move(token)); + } + + // 语法分析 + Parser parser(std::move(tokens)); + auto program = parser.parse(); + + // 语义分析 + SemanticAnalyzer analyzer(sysuiImported); + analyzer.analyze(*program); + + if (analyzer.hasErrors()) { + std::string errorMsg = "Semantic errors:\n"; + for (const auto& error : analyzer.getErrors()) { + errorMsg += " - " + error + "\n"; + } + throw std::runtime_error(errorMsg); + } + + // 代码生成 + CodeGenerator generator(sysuiImported); + return generator.generate(*program); + + } catch (const std::exception& e) { + throw std::runtime_error("Compilation failed: " + std::string(e.what())); + } +} + +} // namespace oraset3 + +void runProgram(const std::string& exePath) { + std::string cmd = "\"" + exePath + "\""; + int result = system(cmd.c_str()); + if (result != 0) { + std::cerr << "Program exited with code: " << result << std::endl; + } +} + +std::string getTempFileName(const std::string& prefix, const std::string& suffix) { + static int counter = 0; + return prefix + "_" + std::to_string(counter++) + suffix; +} + +// 运行程序并捕获输出 +std::string runProgramAndCapture(const std::string& exePath) { + #ifdef _WIN32 + // 使用临时文件来捕获输出,避免管道问题 + std::string outputFile = getTempFileName("oraset3_out", ".txt"); + + // 确保路径中没有引号 + std::string cleanExePath = exePath; + if (!cleanExePath.empty() && cleanExePath.front() == '"') { + cleanExePath = cleanExePath.substr(1); + } + if (!cleanExePath.empty() && cleanExePath.back() == '"') { + cleanExePath = cleanExePath.substr(0, cleanExePath.size() - 1); + } + + std::string cmd = cleanExePath + " > " + outputFile + " 2>&1"; + system(cmd.c_str()); + + std::string output; + { + std::ifstream ifs(outputFile); + output = std::string((std::istreambuf_iterator(ifs)), + std::istreambuf_iterator()); + } // ifs 在此处自动关闭 + + std::filesystem::remove(outputFile); + return output; + #else + // Linux version + std::string outputFile = getTempFileName("oraset3_out", ".txt"); + + std::string cmd = exePath + " > " + outputFile + " 2>&1"; + system(cmd.c_str()); + + std::string output; + { + std::ifstream ifs(outputFile); + output = std::string((std::istreambuf_iterator(ifs)), + std::istreambuf_iterator()); + } // ifs 在此处自动关闭 + + std::filesystem::remove(outputFile); + return output; + #endif +} + +// 解释器模式运行 +void interpretProgram(const std::string& source, bool noOutputHeader) { + try { + oraset3::Compiler compiler; + std::string cppCode = compiler.compile(source); + + // 使用临时文件 + std::string outputFile = getTempFileName("oraset3", ".cpp"); + std::string exeFile = outputFile; + size_t dotPos = exeFile.find_last_of('.'); + if (dotPos != std::string::npos) { + exeFile = exeFile.substr(0, dotPos); + } + #ifdef _WIN32 + exeFile += ".exe"; + #endif + + // 写入C++文件 + std::ofstream ofs(outputFile); + ofs << cppCode; + ofs.close(); + + // 编译 + std::string compileCmd; + #ifdef _WIN32 + compileCmd = "g++ -std=c++20 -mconsole -finput-charset=utf-8 -fexec-charset=utf-8 -o \"" + exeFile + "\" \"" + outputFile + "\""; + #else + compileCmd = "g++ -std=c++20 -finput-charset=utf-8 -fexec-charset=utf-8 -o " + exeFile + " " + outputFile; + #endif + + if (!noOutputHeader) { + std::cout << "Compiling... " << std::endl; + } + + // 记录编译开始时间 + auto compileStart = std::chrono::high_resolution_clock::now(); + + int compileResult = system(compileCmd.c_str()); + + // 记录编译结束时间 + auto compileEnd = std::chrono::high_resolution_clock::now(); + auto compileDuration = std::chrono::duration_cast(compileEnd - compileStart).count(); + + if (compileResult != 0) { + std::cerr << "C++ compilation failed" << std::endl; + std::filesystem::remove(outputFile); + return; + } + + if (!noOutputHeader) { + // 运行程序并捕获输出 + std::cout << "Running..." << std::endl; + + // 记录运行开始时间 + auto runStart = std::chrono::high_resolution_clock::now(); + + std::string programOutput = runProgramAndCapture(exeFile); + + // 记录运行结束时间 + auto runEnd = std::chrono::high_resolution_clock::now(); + auto runDuration = std::chrono::duration_cast(runEnd - runStart).count(); + + std::cout << "------------------------" << std::endl; + std::cout << programOutput; + std::cout << "------------------------" << std::endl; + + // 显示编译和运行时间 + std::cout << "编译耗时: " << compileDuration << " ms" << std::endl; + std::cout << "运行耗时: " << runDuration << " ms" << std::endl; + std::cout << "------------------------" << std::endl; + std::cout << "Program finished" << std::endl; + } else { + // 仅输出程序结果 - 直接运行避免管道带来的额外空行 + std::string runCmd; + #ifdef _WIN32 + runCmd = "\"" + exeFile + "\""; + #else + runCmd = exeFile; + #endif + system(runCmd.c_str()); + } + + // 清理临时文件 + std::filesystem::remove(outputFile); + std::filesystem::remove(exeFile); + + } catch (const std::exception& e) { + std::cerr << e.what() << std::endl; + } +} + +int main(int argc, char* argv[]) { + // 解析命令行参数 + std::string inputFile; + std::string outputFile; + bool runDirectly = true; + bool noOutputHeader = false; + + for (int i = 1; i < argc; i++) { + std::string arg = argv[i]; + if (arg == "--noo") { + noOutputHeader = true; + } else if (inputFile.empty()) { + inputFile = arg; + } else if (outputFile.empty()) { + outputFile = arg; + runDirectly = false; + } + } + + if (inputFile.empty()) { + std::cerr << "Usage:" << std::endl; + std::cerr << " oraset3 - Compile and run with full output" << std::endl; + std::cerr << " oraset3 - Compile to C++ file" << std::endl; + std::cerr << " oraset3 --noo - Run with minimal output (only program output)" << std::endl; + return 1; + } + + // 如果使用 --noo 参数,直接运行 + if (noOutputHeader) { + try { + std::ifstream ifs(inputFile); + if (!ifs) { + std::cerr << "Cannot open input file: " << inputFile << std::endl; + return 1; + } + + std::string source((std::istreambuf_iterator(ifs)), + std::istreambuf_iterator()); + + interpretProgram(source, noOutputHeader); + + } catch (const std::exception& e) { + std::cerr << e.what() << std::endl; + return 1; + } + return 0; + } + + // 传统模式 - 编译并运行 + try { + // 读取源文件 + std::ifstream ifs(inputFile); + if (!ifs) { + std::cerr << "Cannot open input file: " << inputFile << std::endl; + return 1; + } + + std::string source((std::istreambuf_iterator(ifs)), + std::istreambuf_iterator()); + + if (runDirectly && outputFile.empty()) { + // 没有指定输出文件,直接编译并运行(带完整输出) + interpretProgram(source, false); + } else { + // 编译到指定文件 + oraset3::Compiler compiler; + std::string output = compiler.compile(source); + + // 写入输出文件 + std::ofstream ofs(outputFile); + if (!ofs) { + std::cerr << "Cannot open output file: " << outputFile << std::endl; + return 1; + } + + ofs << output; + ofs.close(); + + std::cout << "Compilation successful! Output written to: " << outputFile << std::endl; + } + + } catch (const std::exception& e) { + std::cerr << e.what() << std::endl; + return 1; + } + + return 0; +} \ No newline at end of file diff --git a/src/cpp/lexer/lexer.cpp b/src/cpp/lexer/lexer.cpp new file mode 100644 index 0000000..8656497 --- /dev/null +++ b/src/cpp/lexer/lexer.cpp @@ -0,0 +1,257 @@ +#include "oraset3.h" +#include +#include + +namespace oraset3 { + +Lexer::Lexer(const std::string& source) + : source(source), pos(0), line(1), column(1) {} + +char Lexer::currentChar() { + if (pos >= source.size()) return '\0'; + return source[pos]; +} + +void Lexer::advance() { + if (currentChar() == '\n') { + line++; + column = 1; + } else { + column++; + } + pos++; +} + +void Lexer::skipWhitespace() { + while (isspace(currentChar())) { + advance(); + } +} + +std::string Lexer::readIdentifier() { + std::string result; + while (isalnum(currentChar()) || currentChar() == '_') { + result += currentChar(); + advance(); + } + return result; +} + +std::string Lexer::readNumber() { + std::string result; + bool hasDecimal = false; + + while (isdigit(currentChar()) || (currentChar() == '.' && !hasDecimal)) { + if (currentChar() == '.') hasDecimal = true; + result += currentChar(); + advance(); + } + + return result; +} + +std::string Lexer::readString(char quote) { + std::string result; + advance(); // 跳过引号 + + while (currentChar() != quote && currentChar() != '\0') { + if (currentChar() == '\\') { + advance(); + switch (currentChar()) { + case 'n': result += '\n'; break; + case 't': result += '\t'; break; + case 'r': result += '\r'; break; + case '\\': result += '\\'; break; + case '"': result += '"'; break; + case '\'': result += '\''; break; + default: result += currentChar(); break; + } + } else { + result += currentChar(); + } + advance(); + } + + advance(); // 跳过结束引号 + return result; +} + +std::unique_ptr Lexer::nextToken() { + skipWhitespace(); + + char c = currentChar(); + int tokenLine = line; + int tokenColumn = column; + + if (c == '\0') { + return std::make_unique(TokenType::END_OF_FILE, "", tokenLine, tokenColumn); + } + + if (isalpha(c) || c == '_') { + std::string id = readIdentifier(); + + static const std::unordered_map keywords = { + {"var", TokenType::VAR}, + {"let", TokenType::LET}, + {"const", TokenType::CONST}, + {"func", TokenType::FUNC}, + {"struct", TokenType::STRUCT}, + {"interface", TokenType::INTERFACE}, + {"union", TokenType::UNION}, + {"enum", TokenType::ENUM}, + {"if", TokenType::IF}, + {"else", TokenType::ELSE}, + {"for", TokenType::FOR}, + {"while", TokenType::WHILE}, + {"return", TokenType::RETURN}, + {"break", TokenType::BREAK}, + {"continue", TokenType::CONTINUE}, + {"import", TokenType::IMPORT}, + {"export", TokenType::EXPORT}, + {"true", TokenType::TRUE}, + {"false", TokenType::FALSE}, + {"nil", TokenType::NIL} + }; + + auto it = keywords.find(id); + if (it != keywords.end()) { + return std::make_unique(it->second, id, tokenLine, tokenColumn); + } + return std::make_unique(TokenType::IDENTIFIER, id, tokenLine, tokenColumn); + } + + if (isdigit(c)) { + std::string num = readNumber(); + if (num.find('.') != std::string::npos) { + return std::make_unique(TokenType::FLOAT, num, tokenLine, tokenColumn); + } + return std::make_unique(TokenType::INTEGER, num, tokenLine, tokenColumn); + } + + if (c == '"' || c == '\'') { + std::string str = readString(c); + return std::make_unique(TokenType::STRING, str, tokenLine, tokenColumn); + } + + advance(); + + switch (c) { + case '+': { + if (currentChar() == '=') { + advance(); + return std::make_unique(TokenType::ADD_ASSIGN, "+=", tokenLine, tokenColumn); + } + return std::make_unique(TokenType::PLUS, "+", tokenLine, tokenColumn); + } + case '-': { + if (currentChar() == '=') { + advance(); + return std::make_unique(TokenType::SUB_ASSIGN, "-=", tokenLine, tokenColumn); + } + return std::make_unique(TokenType::MINUS, "-", tokenLine, tokenColumn); + } + case '/': { + if (currentChar() == '=') { + advance(); + return std::make_unique(TokenType::DIV_ASSIGN, "/=", tokenLine, tokenColumn); + } + // 跳过注释 + if (currentChar() == '/') { + while (currentChar() != '\n' && currentChar() != '\0') { + advance(); + } + return nextToken(); + } + return std::make_unique(TokenType::DIV, "/", tokenLine, tokenColumn); + } + case '%': return std::make_unique(TokenType::MOD, "%", tokenLine, tokenColumn); + case '=': { + if (currentChar() == '=') { + advance(); + return std::make_unique(TokenType::EQ, "==", tokenLine, tokenColumn); + } + return std::make_unique(TokenType::ASSIGN, "=", tokenLine, tokenColumn); + } + case '!': { + if (currentChar() == '=') { + advance(); + return std::make_unique(TokenType::NEQ, "!=", tokenLine, tokenColumn); + } + return std::make_unique(TokenType::NOT, "!", tokenLine, tokenColumn); + } + case '<': { + if (currentChar() == '<') { + advance(); + return std::make_unique(TokenType::SHL, "<<", tokenLine, tokenColumn); + } + if (currentChar() == '=') { + advance(); + return std::make_unique(TokenType::LE, "<=", tokenLine, tokenColumn); + } + return std::make_unique(TokenType::LT, "<", tokenLine, tokenColumn); + } + case '>': { + if (currentChar() == '>') { + advance(); + return std::make_unique(TokenType::SHR, ">>", tokenLine, tokenColumn); + } + if (currentChar() == '=') { + advance(); + return std::make_unique(TokenType::GE, ">=", tokenLine, tokenColumn); + } + return std::make_unique(TokenType::GT, ">", tokenLine, tokenColumn); + } + case '&': { + if (currentChar() == '&') { + advance(); + return std::make_unique(TokenType::AND, "&&", tokenLine, tokenColumn); + } + return std::make_unique(TokenType::BIT_AND, "&", tokenLine, tokenColumn); + } + case '|': { + if (currentChar() == '|') { + advance(); + return std::make_unique(TokenType::OR, "||", tokenLine, tokenColumn); + } + return std::make_unique(TokenType::BIT_OR, "|", tokenLine, tokenColumn); + } + case '^': return std::make_unique(TokenType::BIT_XOR, "^", tokenLine, tokenColumn); + case '~': return std::make_unique(TokenType::BIT_NOT, "~", tokenLine, tokenColumn); + case '*': { + if (currentChar() == '=') { + advance(); + return std::make_unique(TokenType::MUL_ASSIGN, "*=", tokenLine, tokenColumn); + } + return std::make_unique(TokenType::MUL, "*", tokenLine, tokenColumn); + } + case '(': return std::make_unique(TokenType::LPAREN, "(", tokenLine, tokenColumn); + case ')': return std::make_unique(TokenType::RPAREN, ")", tokenLine, tokenColumn); + case '{': return std::make_unique(TokenType::LBRACE, "{", tokenLine, tokenColumn); + case '}': return std::make_unique(TokenType::RBRACE, "}", tokenLine, tokenColumn); + case '[': return std::make_unique(TokenType::LBRACKET, "[", tokenLine, tokenColumn); + case ']': return std::make_unique(TokenType::RBRACKET, "]", tokenLine, tokenColumn); + case ',': return std::make_unique(TokenType::COMMA, ",", tokenLine, tokenColumn); + case ';': return std::make_unique(TokenType::SEMICOLON, ";", tokenLine, tokenColumn); + case ':': { + if (currentChar() == ':') { + advance(); + return std::make_unique(TokenType::DOUBLE_COLON, "::", tokenLine, tokenColumn); + } + if (currentChar() == '=') { + advance(); + return std::make_unique(TokenType::COLON_ASSIGN, ":=", tokenLine, tokenColumn); + } + return std::make_unique(TokenType::COLON, ":", tokenLine, tokenColumn); + } + case '.': return std::make_unique(TokenType::DOT, ".", tokenLine, tokenColumn); + case '$': { + advance(); // 跳过 $ + std::string id = readIdentifier(); + return std::make_unique(TokenType::IMPORT_DIRECTIVE, id, tokenLine, tokenColumn); + } + } + + return std::make_unique(TokenType::END_OF_FILE, "", tokenLine, tokenColumn); +} + +} // namespace oraset3 \ No newline at end of file diff --git a/src/cpp/parser/parser.cpp b/src/cpp/parser/parser.cpp new file mode 100644 index 0000000..82ba1dd --- /dev/null +++ b/src/cpp/parser/parser.cpp @@ -0,0 +1,797 @@ +#include "oraset3.h" +#include + +namespace oraset3 { + +Parser::Parser(std::vector> tokens) + : tokens(std::move(tokens)), pos(0) {} + +Token* Parser::currentToken() { + if (pos >= tokens.size()) return nullptr; + return tokens[pos].get(); +} + +Token* Parser::peekToken() { + if (pos + 1 >= tokens.size()) return nullptr; + return tokens[pos + 1].get(); +} + +void Parser::advance() { + if (pos < tokens.size()) pos++; +} + +bool Parser::match(TokenType type) { + Token* t = currentToken(); + return t && t->type == type; +} + +bool Parser::consume(TokenType type) { + if (match(type)) { + advance(); + return true; + } + return false; +} + +std::unique_ptr Parser::parse() { + auto program = std::make_unique(); + + while (currentToken()) { + program->declarations.push_back(parseDeclaration()); + } + + return program; +} + +std::unique_ptr Parser::parseDeclaration() { + if (match(TokenType::VAR) || match(TokenType::LET) || match(TokenType::CONST)) { + return parseVarDecl(); + } + if (match(TokenType::FUNC)) { + return parseFuncDecl(); + } + if (match(TokenType::STRUCT)) { + return parseStructDecl(); + } + if (match(TokenType::INTERFACE)) { + return parseInterfaceDecl(); + } + if (match(TokenType::UNION)) { + return parseUnionDecl(); + } + if (match(TokenType::ENUM)) { + return parseEnumDecl(); + } + // 处理导入指令 $xxx + if (match(TokenType::IMPORT_DIRECTIVE)) { + // 跳过导入指令,因为编译器已经在 lexer 阶段处理了 + // 返回一个空的表达式语句作为占位符 + return std::make_unique(); + } + // 检查是否是 := 声明(x := 10) - 不消费标识符,让 parseVarDecl 处理 + if (match(TokenType::IDENTIFIER) && peekToken() && peekToken()->type == TokenType::COLON_ASSIGN) { + return parseVarDecl(); + } + // 检查是否是 类型 变量名 = 值 的声明 + if (match(TokenType::IDENTIFIER) && peekToken() && peekToken()->type == TokenType::IDENTIFIER) { + Token* nextNext = nullptr; + if (pos + 2 < tokens.size()) { + nextNext = tokens[pos + 2].get(); + } + if (nextNext && (nextNext->type == TokenType::ASSIGN || nextNext->type == TokenType::COLON_ASSIGN)) { + // 这是一个带类型的变量声明,让 parseVarDecl 处理 + return parseVarDecl(); + } + } + + // 检查控制流语句 + if (match(TokenType::IF)) { + return parseIfStmt(); + } + if (match(TokenType::WHILE)) { + return parseWhileStmt(); + } + if (match(TokenType::FOR)) { + return parseForStmt(); + } + if (match(TokenType::RETURN)) { + return parseReturnStmt(); + } + if (match(TokenType::BREAK)) { + auto stmt = std::make_unique(); + advance(); + consume(TokenType::SEMICOLON); + return stmt; + } + if (match(TokenType::CONTINUE)) { + auto stmt = std::make_unique(); + advance(); + consume(TokenType::SEMICOLON); + return stmt; + } + + // 顶层表达式语句(无需函数包装) + std::unique_ptr expr = parseExpression(); + consume(TokenType::SEMICOLON); + + // 将表达式包装在 ExprStmtNode 中 + auto stmt = std::make_unique(); + stmt->expr = std::move(expr); + return stmt; +} + +std::unique_ptr Parser::parseVarDecl() { + auto decl = std::make_unique(); + bool hasKeyword = match(TokenType::VAR) || match(TokenType::LET) || match(TokenType::CONST); + + if (hasKeyword) { + advance(); // 跳过 var/let/const 关键字 + } + + // 获取第一个标识符 + if (!consume(TokenType::IDENTIFIER)) { + throw std::runtime_error("Expected variable name"); + } + std::string firstToken = tokens[pos - 1]->value; + + // 检查是否是 类型 变量名 = 值 的语法 + // 如果下一个是标识符,且下下个是赋值操作符 + bool hasTypeAnnotation = false; + if (!hasKeyword && peekToken() && peekToken()->type == TokenType::IDENTIFIER) { + Token* nextNext = nullptr; + if (pos + 2 < tokens.size()) { + nextNext = tokens[pos + 2].get(); + } + if (nextNext && (nextNext->type == TokenType::ASSIGN || nextNext->type == TokenType::COLON_ASSIGN)) { + hasTypeAnnotation = true; + } + } + + if (hasTypeAnnotation) { + // 第一个标识符是类型 + decl->type = firstToken; + // 获取变量名 + if (!consume(TokenType::IDENTIFIER)) { + throw std::runtime_error("Expected variable name"); + } + decl->name = tokens[pos - 1]->value; + } else { + // 第一个标识符是变量名 + decl->name = firstToken; + // 检查类型注解 (var x int = 10) + if (consume(TokenType::IDENTIFIER) && !match(TokenType::ASSIGN) && !match(TokenType::COLON_ASSIGN)) { + decl->type = tokens[pos - 1]->value; + } + } + + // 处理赋值 + if (consume(TokenType::ASSIGN) || consume(TokenType::COLON_ASSIGN)) { + decl->initializer = parseExpression(); + } + + consume(TokenType::SEMICOLON); + return decl; +} + +std::unique_ptr Parser::parseFuncDecl() { + auto decl = std::make_unique(); + advance(); // 跳过 func + + // 函数名 + if (!consume(TokenType::IDENTIFIER)) { + throw std::runtime_error("Expected function name"); + } + decl->name = tokens[pos - 1]->value; + + // 参数列表 + consume(TokenType::LPAREN); + while (match(TokenType::IDENTIFIER)) { + std::string paramName = tokens[pos]->value; + advance(); + std::string paramType = "auto"; + if (match(TokenType::COLON)) { + advance(); + if (consume(TokenType::IDENTIFIER)) { + paramType = tokens[pos - 1]->value; + } + } + decl->params.push_back({paramName, paramType}); + + if (!match(TokenType::RPAREN)) { + consume(TokenType::COMMA); + } + } + consume(TokenType::RPAREN); + + // 返回类型(可选) + if (match(TokenType::COLON)) { + advance(); + if (consume(TokenType::IDENTIFIER)) { + decl->returnType = tokens[pos - 1]->value; + } + } + + // 函数体 + consume(TokenType::LBRACE); + while (!match(TokenType::RBRACE) && currentToken()) { + decl->body.push_back(parseStatement()); + } + consume(TokenType::RBRACE); + + return decl; +} + +std::unique_ptr Parser::parseStructDecl() { + auto decl = std::make_unique(); + advance(); // 跳过 struct + + if (!consume(TokenType::IDENTIFIER)) { + throw std::runtime_error("Expected struct name"); + } + decl->name = tokens[pos - 1]->value; + + consume(TokenType::LBRACE); + while (!match(TokenType::RBRACE) && currentToken()) { + if (!consume(TokenType::IDENTIFIER)) { + throw std::runtime_error("Expected field name"); + } + std::string fieldName = tokens[pos - 1]->value; + + std::string fieldType = "auto"; + if (consume(TokenType::COLON)) { + if (consume(TokenType::IDENTIFIER)) { + fieldType = tokens[pos - 1]->value; + } + } + + decl->fields.push_back({fieldName, fieldType}); + consume(TokenType::SEMICOLON); + } + consume(TokenType::RBRACE); + + return decl; +} + +std::unique_ptr Parser::parseInterfaceDecl() { + auto decl = std::make_unique(); + advance(); // 跳过 interface + + if (!consume(TokenType::IDENTIFIER)) { + throw std::runtime_error("Expected interface name"); + } + decl->name = tokens[pos - 1]->value; + + consume(TokenType::LBRACE); + while (!match(TokenType::RBRACE) && currentToken()) { + if (!consume(TokenType::IDENTIFIER)) { + throw std::runtime_error("Expected method name"); + } + std::string methodName = tokens[pos - 1]->value; + + consume(TokenType::LPAREN); + consume(TokenType::RPAREN); + + std::string returnType = "void"; + if (match(TokenType::COLON)) { + advance(); + if (consume(TokenType::IDENTIFIER)) { + returnType = tokens[pos - 1]->value; + } + } + + decl->methods.push_back({methodName, returnType}); + consume(TokenType::SEMICOLON); + } + consume(TokenType::RBRACE); + + return decl; +} + +std::unique_ptr Parser::parseUnionDecl() { + auto decl = std::make_unique(); + advance(); // 跳过 union + + if (!consume(TokenType::IDENTIFIER)) { + throw std::runtime_error("Expected union name"); + } + decl->name = tokens[pos - 1]->value; + + consume(TokenType::LBRACE); + while (!match(TokenType::RBRACE) && currentToken()) { + if (!consume(TokenType::IDENTIFIER)) { + throw std::runtime_error("Expected field name"); + } + std::string fieldName = tokens[pos - 1]->value; + + std::string fieldType = "auto"; + if (consume(TokenType::COLON)) { + if (consume(TokenType::IDENTIFIER)) { + fieldType = tokens[pos - 1]->value; + } + } + + decl->fields.push_back({fieldName, fieldType}); + consume(TokenType::SEMICOLON); + } + consume(TokenType::RBRACE); + consume(TokenType::SEMICOLON); // 添加分号消费 + + return decl; +} + +std::unique_ptr Parser::parseEnumDecl() { + auto decl = std::make_unique(); + advance(); // 跳过 enum + + if (!consume(TokenType::IDENTIFIER)) { + throw std::runtime_error("Expected enum name"); + } + decl->name = tokens[pos - 1]->value; + + consume(TokenType::LBRACE); + while (!match(TokenType::RBRACE) && currentToken()) { + if (!consume(TokenType::IDENTIFIER)) { + throw std::runtime_error("Expected enum value name"); + } + std::string valueName = tokens[pos - 1]->value; + std::string value = ""; + + if (consume(TokenType::ASSIGN)) { + if (consume(TokenType::INTEGER)) { + value = tokens[pos - 1]->value; + } + } + + decl->values.push_back({valueName, value}); + + if (!match(TokenType::RBRACE)) { + consume(TokenType::COMMA); + } + } + consume(TokenType::RBRACE); + consume(TokenType::SEMICOLON); // 添加分号消费 + + return decl; +} + +std::unique_ptr Parser::parseStatement() { + if (match(TokenType::VAR) || match(TokenType::LET) || match(TokenType::CONST)) { + return parseVarDecl(); + } + if (match(TokenType::IF)) { + return parseIfStmt(); + } + if (match(TokenType::WHILE)) { + return parseWhileStmt(); + } + if (match(TokenType::FOR)) { + return parseForStmt(); + } + if (match(TokenType::RETURN)) { + return parseReturnStmt(); + } + if (match(TokenType::BREAK)) { + auto stmt = std::make_unique(); + advance(); + consume(TokenType::SEMICOLON); + return stmt; + } + if (match(TokenType::CONTINUE)) { + auto stmt = std::make_unique(); + advance(); + consume(TokenType::SEMICOLON); + return stmt; + } + if (match(TokenType::LBRACE)) { + return parseBlock(); + } + + // 检查是否是 := 声明(x := 10) + if (match(TokenType::IDENTIFIER) && peekToken() && peekToken()->type == TokenType::COLON_ASSIGN) { + return parseVarDecl(); + } + + // 可能是表达式语句 + std::unique_ptr expr = parseExpression(); + consume(TokenType::SEMICOLON); + + // 将表达式包装在 ExprStmtNode 中 + auto stmt = std::make_unique(); + stmt->expr = std::move(expr); + return stmt; +} + +std::unique_ptr Parser::parseBlock() { + auto block = std::make_unique(); + advance(); // 跳过 { + + // 简单处理:只处理第一个语句 + if (!match(TokenType::RBRACE) && currentToken()) { + block->expr = parseStatement(); + } + + // 跳过其余语句直到找到 } + while (!match(TokenType::RBRACE) && currentToken()) { + advance(); + } + + consume(TokenType::RBRACE); + return block; +} + +std::unique_ptr Parser::parseIfStmt() { + auto stmt = std::make_unique(); + advance(); // 跳过 if + + consume(TokenType::LPAREN); + stmt->condition = parseExpression(); + consume(TokenType::RPAREN); + + // then branch + if (match(TokenType::LBRACE)) { + stmt->thenBranch.push_back(parseBlock()); + } else { + stmt->thenBranch.push_back(parseStatement()); + } + + // else branch + if (match(TokenType::ELSE)) { + advance(); + if (match(TokenType::IF)) { + stmt->elseBranch.push_back(parseIfStmt()); + } else if (match(TokenType::LBRACE)) { + stmt->elseBranch.push_back(parseBlock()); + } else { + stmt->elseBranch.push_back(parseStatement()); + } + } + + return stmt; +} + +std::unique_ptr Parser::parseWhileStmt() { + auto stmt = std::make_unique(); + advance(); // 跳过 while + + consume(TokenType::LPAREN); + stmt->condition = parseExpression(); + consume(TokenType::RPAREN); + + if (match(TokenType::LBRACE)) { + stmt->body.push_back(parseBlock()); + } else { + stmt->body.push_back(parseStatement()); + } + + return stmt; +} + +std::unique_ptr Parser::parseForStmt() { + auto stmt = std::make_unique(); + advance(); // 跳过 for + + consume(TokenType::LPAREN); + + // 初始化 + if (!match(TokenType::SEMICOLON)) { + stmt->init = parseExpression(); + } + consume(TokenType::SEMICOLON); + + // 条件 + if (!match(TokenType::SEMICOLON)) { + stmt->condition = parseExpression(); + } + consume(TokenType::SEMICOLON); + + // 更新 + if (!match(TokenType::RPAREN)) { + stmt->update = parseExpression(); + } + consume(TokenType::RPAREN); + + if (match(TokenType::LBRACE)) { + stmt->body.push_back(parseBlock()); + } else { + stmt->body.push_back(parseStatement()); + } + + return stmt; +} + +std::unique_ptr Parser::parseReturnStmt() { + auto stmt = std::make_unique(); + advance(); // 跳过 return + + if (!match(TokenType::SEMICOLON)) { + stmt->expr = parseExpression(); + } + + consume(TokenType::SEMICOLON); + return stmt; +} + +std::unique_ptr Parser::parseExpression() { + return parseAssignment(); +} + +std::unique_ptr Parser::parseAssignment() { + std::unique_ptr left = parseLogicalOr(); + + if (match(TokenType::ASSIGN) || match(TokenType::COLON_ASSIGN)) { + auto assign = std::make_unique(); + assign->left = std::move(left); + assign->op = match(TokenType::ASSIGN) ? "=" : ":="; + advance(); + assign->right = parseAssignment(); + return assign; + } + + return left; +} + +std::unique_ptr Parser::parseLogicalOr() { + std::unique_ptr left = parseLogicalAnd(); + + while (match(TokenType::OR)) { + auto binary = std::make_unique(); + binary->left = std::move(left); + binary->op = "||"; + advance(); + binary->right = parseLogicalAnd(); + left = std::move(binary); + } + + return left; +} + +std::unique_ptr Parser::parseLogicalAnd() { + std::unique_ptr left = parseEquality(); + + while (match(TokenType::AND)) { + auto binary = std::make_unique(); + binary->left = std::move(left); + binary->op = "&&"; + advance(); + binary->right = parseEquality(); + left = std::move(binary); + } + + return left; +} + +std::unique_ptr Parser::parseEquality() { + std::unique_ptr left = parseComparison(); + + while (match(TokenType::EQ) || match(TokenType::NEQ)) { + auto binary = std::make_unique(); + binary->left = std::move(left); + binary->op = match(TokenType::EQ) ? "==" : "!="; + advance(); + binary->right = parseComparison(); + left = std::move(binary); + } + + return left; +} + +std::unique_ptr Parser::parseComparison() { + std::unique_ptr left = parseShift(); + + while (match(TokenType::LT) || match(TokenType::GT) || match(TokenType::LE) || match(TokenType::GE)) { + auto binary = std::make_unique(); + binary->left = std::move(left); + if (match(TokenType::LT)) binary->op = "<"; + else if (match(TokenType::GT)) binary->op = ">"; + else if (match(TokenType::LE)) binary->op = "<="; + else binary->op = ">="; + advance(); + binary->right = parseShift(); + left = std::move(binary); + } + + return left; +} + +std::unique_ptr Parser::parseShift() { + std::unique_ptr left = parseAdditive(); + + while (match(TokenType::SHL) || match(TokenType::SHR) || + match(TokenType::BIT_AND) || match(TokenType::BIT_OR) || match(TokenType::BIT_XOR)) { + auto binary = std::make_unique(); + binary->left = std::move(left); + if (match(TokenType::SHL)) binary->op = "<<"; + else if (match(TokenType::SHR)) binary->op = ">>"; + else if (match(TokenType::BIT_AND)) binary->op = "&"; + else if (match(TokenType::BIT_OR)) binary->op = "|"; + else binary->op = "^"; + advance(); + binary->right = parseAdditive(); + left = std::move(binary); + } + + return left; +} + +std::unique_ptr Parser::parseAdditive() { + std::unique_ptr left = parseMultiplicative(); + + while (match(TokenType::PLUS) || match(TokenType::MINUS)) { + auto binary = std::make_unique(); + binary->left = std::move(left); + binary->op = match(TokenType::PLUS) ? "+" : "-"; + advance(); + binary->right = parseMultiplicative(); + left = std::move(binary); + } + + return left; +} + +std::unique_ptr Parser::parseMultiplicative() { + std::unique_ptr left = parseUnary(); + + while (match(TokenType::MUL) || match(TokenType::DIV) || match(TokenType::MOD)) { + auto binary = std::make_unique(); + binary->left = std::move(left); + if (match(TokenType::MUL)) binary->op = "*"; + else if (match(TokenType::DIV)) binary->op = "/"; + else binary->op = "%"; + advance(); + binary->right = parseUnary(); + left = std::move(binary); + } + + return left; +} + +std::unique_ptr Parser::parseUnary() { + if (match(TokenType::NOT) || match(TokenType::MINUS) || + match(TokenType::MUL) || match(TokenType::BIT_AND) || match(TokenType::BIT_NOT)) { + auto unary = std::make_unique(); + if (match(TokenType::NOT)) unary->op = "!"; + else if (match(TokenType::MINUS)) unary->op = "-"; + else if (match(TokenType::MUL)) unary->op = "*"; + else if (match(TokenType::BIT_AND)) unary->op = "&"; + else unary->op = "~"; + advance(); + unary->operand = parseUnary(); + return unary; + } + + return parsePostfix(); +} + +std::unique_ptr Parser::parsePostfix() { + std::unique_ptr expr = parsePrimary(); + + while (true) { + if (match(TokenType::LPAREN)) { + // 函数调用 + auto call = std::make_unique(); + call->callee = std::move(expr); + + consume(TokenType::LPAREN); + if (!match(TokenType::RPAREN)) { + do { + call->args.push_back(parseExpression()); + } while (consume(TokenType::COMMA)); + } + consume(TokenType::RPAREN); + + expr = std::move(call); + } else if (match(TokenType::LBRACE)) { + // 结构体实例化,如 Point{x: 10, y: 20} + auto structInit = std::make_unique(); + structInit->typeName = static_cast(expr.get())->name; + + advance(); // 跳过 { + while (!match(TokenType::RBRACE) && currentToken()) { + if (!consume(TokenType::IDENTIFIER)) { + throw std::runtime_error("Expected field name in struct initializer"); + } + std::string fieldName = tokens[pos - 1]->value; + + consume(TokenType::COLON); + std::unique_ptr fieldValue = parseExpression(); + + structInit->fields.push_back({fieldName, std::move(fieldValue)}); + + if (!match(TokenType::RBRACE)) { + consume(TokenType::COMMA); + } + } + consume(TokenType::RBRACE); + + expr = std::move(structInit); + } else if (match(TokenType::DOT)) { + // 成员访问 + advance(); + if (!consume(TokenType::IDENTIFIER)) { + throw std::runtime_error("Expected member name"); + } + auto member = std::make_unique(); + member->object = std::move(expr); + member->property = tokens[pos - 1]->value; + member->op = "."; + expr = std::move(member); + } else if (match(TokenType::LBRACKET)) { + // 数组索引 + advance(); + auto index = std::make_unique(); + index->base = std::move(expr); + index->index = parseExpression(); + consume(TokenType::RBRACKET); + expr = std::move(index); + } else { + break; + } + } + + return expr; +} + +std::unique_ptr Parser::parsePrimary() { + // 类型转换: (type)expr + if (match(TokenType::LPAREN) && peekToken() && peekToken()->type == TokenType::IDENTIFIER) { + advance(); // 跳过 LPAREN + std::string targetType = tokens[pos]->value; + advance(); // 跳过类型名 + if (consume(TokenType::RPAREN)) { + auto cast = std::make_unique(); + cast->targetType = targetType; + cast->expr = parseUnary(); // 使用 parseUnary 允许括号内的表达式 + return cast; + } + } + + if (match(TokenType::INTEGER) || match(TokenType::FLOAT)) { + auto lit = std::make_unique(); + lit->value = tokens[pos]->value; + lit->type = match(TokenType::FLOAT) ? "float" : "int"; + advance(); + return lit; + } + + if (match(TokenType::STRING)) { + auto lit = std::make_unique(); + lit->value = tokens[pos]->value; + lit->type = "string"; + advance(); + return lit; + } + + if (match(TokenType::TRUE)) { + auto lit = std::make_unique(); + lit->value = "true"; + lit->type = "bool"; + advance(); + return lit; + } + + if (match(TokenType::FALSE)) { + auto lit = std::make_unique(); + lit->value = "false"; + lit->type = "bool"; + advance(); + return lit; + } + + if (match(TokenType::IDENTIFIER)) { + auto ident = std::make_unique(); + ident->name = tokens[pos]->value; + advance(); + return ident; + } + + if (match(TokenType::LPAREN)) { + advance(); + std::unique_ptr expr = parseExpression(); + consume(TokenType::RPAREN); + return expr; + } + + throw std::runtime_error("Unexpected token"); +} + +} // namespace oraset3 diff --git a/src/cpp/semantic/semantic.cpp b/src/cpp/semantic/semantic.cpp new file mode 100644 index 0000000..890976b --- /dev/null +++ b/src/cpp/semantic/semantic.cpp @@ -0,0 +1,313 @@ +#include "oraset3.h" +#include + +namespace oraset3 { + +void SemanticAnalyzer::analyze(ProgramNode& program) { + // 添加基本类型 + symbolTable["int"] = "type"; + symbolTable["float"] = "type"; + symbolTable["string"] = "type"; + symbolTable["bool"] = "type"; + symbolTable["void"] = "type"; + + // 添加预定义标识符 + symbolTable["std"] = "namespace"; + symbolTable["cout"] = "ostream"; + symbolTable["endl"] = "stream"; + + // 添加内置函数(由编译器提供) + symbolTable["print"] = "builtin_func"; + symbolTable["println"] = "builtin_func"; + + // 系统操作函数 + symbolTable["sys"] = "builtin_func"; + + // 文件操作函数 + symbolTable["file"] = "namespace"; + symbolTable["file.read"] = "builtin_func"; + symbolTable["file.write"] = "builtin_func"; + symbolTable["file.exists"] = "builtin_func"; + + // 屏幕操作函数 + symbolTable["screen"] = "namespace"; + symbolTable["screen.clear"] = "builtin_func"; + symbolTable["screen.size"] = "builtin_func"; + + // 绘图函数 + symbolTable["draw"] = "namespace"; + symbolTable["draw.text"] = "builtin_func"; + symbolTable["draw.rect"] = "builtin_func"; + symbolTable["draw.line"] = "builtin_func"; + + // 如果导入了 sysui,添加UI相关函数 + if (this->sysuiImported) { + symbolTable["ui"] = "namespace"; + symbolTable["ui.msgbox"] = "builtin_func"; + symbolTable["ui.inputbox"] = "builtin_func"; + symbolTable["ui.alert"] = "builtin_func"; + symbolTable["ui.confirm"] = "builtin_func"; + symbolTable["ui.prompt"] = "builtin_func"; + symbolTable["ui.openfile"] = "builtin_func"; + symbolTable["ui.savefile"] = "builtin_func"; + symbolTable["ui.dir"] = "builtin_func"; + symbolTable["ui.color"] = "builtin_func"; + } + + visit(program); +} + +void SemanticAnalyzer::visit(ProgramNode& node) { + // 第一遍:收集所有声明 + for (auto& decl : node.declarations) { + // 先添加函数声明到符号表 + if (decl->getType() == NodeType::FUNC_DECL) { + FuncDeclNode& funcDecl = static_cast(*decl); + if (symbolTable.find(funcDecl.name) != symbolTable.end()) { + std::stringstream ss; + ss << "Function '" << funcDecl.name << "' already declared"; + errors.push_back(ss.str()); + } + symbolTable[funcDecl.name] = "func"; + } + // 添加变量和其他声明 + else if (decl->getType() == NodeType::VAR_DECL) { + VarDeclNode& varDecl = static_cast(*decl); + if (symbolTable.find(varDecl.name) != symbolTable.end()) { + std::stringstream ss; + ss << "Variable '" << varDecl.name << "' already declared"; + errors.push_back(ss.str()); + } + symbolTable[varDecl.name] = varDecl.type; + } + // 添加结构体声明 + else if (decl->getType() == NodeType::STRUCT_DECL) { + StructDeclNode& structDecl = static_cast(*decl); + if (symbolTable.find(structDecl.name) != symbolTable.end()) { + std::stringstream ss; + ss << "Struct '" << structDecl.name << "' already declared"; + errors.push_back(ss.str()); + } + symbolTable[structDecl.name] = "struct"; + } + // 添加接口声明 + else if (decl->getType() == NodeType::INTERFACE_DECL) { + InterfaceDeclNode& interfaceDecl = static_cast(*decl); + if (symbolTable.find(interfaceDecl.name) != symbolTable.end()) { + std::stringstream ss; + ss << "Interface '" << interfaceDecl.name << "' already declared"; + errors.push_back(ss.str()); + } + symbolTable[interfaceDecl.name] = "interface"; + } + // 添加联合体声明 + else if (decl->getType() == NodeType::UNION_DECL) { + UnionDeclNode& unionDecl = static_cast(*decl); + if (symbolTable.find(unionDecl.name) != symbolTable.end()) { + std::stringstream ss; + ss << "Union '" << unionDecl.name << "' already declared"; + errors.push_back(ss.str()); + } + symbolTable[unionDecl.name] = "union"; + } + // 添加枚举声明 + else if (decl->getType() == NodeType::ENUM_DECL) { + EnumDeclNode& enumDecl = static_cast(*decl); + if (symbolTable.find(enumDecl.name) != symbolTable.end()) { + std::stringstream ss; + ss << "Enum '" << enumDecl.name << "' already declared"; + errors.push_back(ss.str()); + } + symbolTable[enumDecl.name] = "enum"; + // 添加枚举常量到符号表 + for (auto& value : enumDecl.values) { + if (symbolTable.find(value.first) != symbolTable.end()) { + std::stringstream ss; + ss << "Enum value '" << value.first << "' already declared"; + errors.push_back(ss.str()); + } + symbolTable[value.first] = enumDecl.name; + } + } + } + + // 第二遍:处理函数体 + for (auto& decl : node.declarations) { + if (decl->getType() == NodeType::FUNC_DECL) { + FuncDeclNode& funcDecl = static_cast(*decl); + + // 保存当前符号表状态 + std::map savedSymbolTable = symbolTable; + + // 添加参数到符号表(只检查函数内部重复) + for (auto& param : funcDecl.params) { + symbolTable[param.first] = param.second; + } + + // 处理函数体:先收集变量声明,再处理 + for (auto& stmt : funcDecl.body) { + if (stmt->getType() == NodeType::VAR_DECL) { + VarDeclNode& varDecl = static_cast(*stmt); + auto it = symbolTable.find(varDecl.name); + // 检查变量名是否已声明,但忽略类型名 + if (it != symbolTable.end() && it->second != "type") { + std::stringstream ss; + ss << "Variable '" << varDecl.name << "' already declared in function '" << funcDecl.name << "'"; + errors.push_back(ss.str()); + } + symbolTable[varDecl.name] = varDecl.type; + } + } + + // 处理函数体 + for (auto& stmt : funcDecl.body) { + stmt->accept(*this); + } + + // 恢复符号表状态 + symbolTable = savedSymbolTable; + } + else if (decl->getType() == NodeType::VAR_DECL) { + VarDeclNode& varDecl = static_cast(*decl); + if (varDecl.initializer) { + varDecl.initializer->accept(*this); + } + } + else { + decl->accept(*this); + } + } +} + +void SemanticAnalyzer::visit(VarDeclNode& node) { + // 处理初始化表达式(如果存在) + if (node.initializer) { + node.initializer->accept(*this); + } +} + +void SemanticAnalyzer::visit(FuncDeclNode& node) { + // 函数声明的处理已经在 ProgramNode 的 visit 方法中完成 +} + +void SemanticAnalyzer::visit(StructDeclNode& node) { + // 结构体声明的处理已经在 ProgramNode 的 visit 方法中完成 +} + +void SemanticAnalyzer::visit(InterfaceDeclNode& node) { + // 接口声明的处理已经在 ProgramNode 的 visit 方法中完成 +} + +void SemanticAnalyzer::visit(UnionDeclNode& node) { + // 联合体声明的处理已经在 ProgramNode 的 visit 方法中完成 +} + +void SemanticAnalyzer::visit(EnumDeclNode& node) { + // 枚举声明的处理已经在 ProgramNode 的 visit 方法中完成 +} + +void SemanticAnalyzer::visit(CastExprNode& node) { + // 类型转换表达式的处理 + if (node.expr) { + node.expr->accept(*this); + } +} + +void SemanticAnalyzer::visit(IfStmtNode& node) { + node.condition->accept(*this); + + for (auto& stmt : node.thenBranch) { + stmt->accept(*this); + } + + for (auto& stmt : node.elseBranch) { + stmt->accept(*this); + } +} + +void SemanticAnalyzer::visit(ForStmtNode& node) { + if (node.init) node.init->accept(*this); + if (node.condition) node.condition->accept(*this); + if (node.update) node.update->accept(*this); + + for (auto& stmt : node.body) { + stmt->accept(*this); + } +} + +void SemanticAnalyzer::visit(WhileStmtNode& node) { + node.condition->accept(*this); + + for (auto& stmt : node.body) { + stmt->accept(*this); + } +} + +void SemanticAnalyzer::visit(ReturnStmtNode& node) { + if (node.expr) { + node.expr->accept(*this); + } +} + +void SemanticAnalyzer::visit(ExprStmtNode& node) { + node.expr->accept(*this); +} + +void SemanticAnalyzer::visit(AssignExprNode& node) { + node.left->accept(*this); + node.right->accept(*this); +} + +void SemanticAnalyzer::visit(BinaryExprNode& node) { + node.left->accept(*this); + node.right->accept(*this); +} + +void SemanticAnalyzer::visit(UnaryExprNode& node) { + node.operand->accept(*this); +} + +void SemanticAnalyzer::visit(CallExprNode& node) { + node.callee->accept(*this); + + for (auto& arg : node.args) { + arg->accept(*this); + } +} + +void SemanticAnalyzer::visit(IndexExprNode& node) { + node.base->accept(*this); + node.index->accept(*this); +} + +void SemanticAnalyzer::visit(MemberExprNode& node) { + node.object->accept(*this); +} + +void SemanticAnalyzer::visit(StructInitNode& node) { + // 检查结构体是否已声明 + if (symbolTable.find(node.typeName) == symbolTable.end()) { + std::stringstream ss; + ss << "Undefined struct type '" << node.typeName << "'"; + errors.push_back(ss.str()); + } + + // 递归处理字段初始化表达式 + for (auto& field : node.fields) { + field.second->accept(*this); + } +} + +void SemanticAnalyzer::visit(LiteralExprNode& node) { + // 字面量无需检查 +} + +void SemanticAnalyzer::visit(IdentifierExprNode& node) { + if (symbolTable.find(node.name) == symbolTable.end()) { + std::stringstream ss; + ss << "Undefined identifier '" << node.name << "'"; + errors.push_back(ss.str()); + } +} + +} // namespace oraset3 diff --git a/src/go/compiler/oraset3.go b/src/go/compiler/oraset3.go new file mode 100644 index 0000000..0de6cf0 --- /dev/null +++ b/src/go/compiler/oraset3.go @@ -0,0 +1,159 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "os/exec" + "path/filepath" + "runtime" +) + +func main() { + if len(os.Args) != 3 { + fmt.Println("Usage: oraset3-go ") + os.Exit(1) + } + + inputFile := os.Args[1] + outputFile := os.Args[2] + + err := compile(inputFile, outputFile) + if err != nil { + fmt.Printf("Error: %v\n", err) + os.Exit(1) + } + + fmt.Printf("Compilation successful! Output: %s\n", outputFile) +} + +func compile(inputFile, outputFile string) error { + source, err := readFile(inputFile) + if err != nil { + return err + } + + // 调用C++编译器核心 + cppOutput, err := runCppCompiler(source) + if err != nil { + return err + } + + // 写入临时C++文件 + tmpCppFile := outputFile + ".tmp.cpp" + err = writeFile(tmpCppFile, cppOutput) + if err != nil { + return err + } + defer os.Remove(tmpCppFile) + + // 根据平台调用相应的编译器 + if runtime.GOOS == "windows" { + return compileWindows(tmpCppFile, outputFile) + } else { + return compileLinux(tmpCppFile, outputFile) + } +} + +func readFile(path string) (string, error) { + data, err := os.ReadFile(path) + if err != nil { + return "", fmt.Errorf("failed to read file: %w", err) + } + return string(data), nil +} + +func writeFile(path, content string) error { + err := os.WriteFile(path, []byte(content), 0644) + if err != nil { + return fmt.Errorf("failed to write file: %w", err) + } + return nil +} + +func runCppCompiler(source string) (string, error) { + // 在实际项目中,这里会调用C++编译核心 + // 由于Go无法直接调用C++代码,我们使用exec调用编译好的oraset3编译器 + // 或者可以使用cgo绑定 + + // 这里简化处理,直接返回源代码内容(演示用) + return source, nil +} + +func compileWindows(cppFile, outputFile string) error { + // 使用MinGW或MSVC编译 + gccPath, err := exec.LookPath("g++") + if err != nil { + return fmt.Errorf("g++ not found: %w", err) + } + + args := []string{ + "-o", outputFile, + cppFile, + "-std=c++17", + "-Wall", + } + + cmd := exec.Command(gccPath, args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + err = cmd.Run() + if err != nil { + return fmt.Errorf("compilation failed: %w", err) + } + + return nil +} + +func compileLinux(cppFile, outputFile string) error { + // 使用Clang编译 + clangPath, err := exec.LookPath("clang++") + if err != nil { + return fmt.Errorf("clang++ not found: %w", err) + } + + args := []string{ + "-o", outputFile, + cppFile, + "-std=c++17", + "-Wall", + "-O2", + } + + cmd := exec.Command(clangPath, args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + err = cmd.Run() + if err != nil { + return fmt.Errorf("compilation failed: %w", err) + } + + return nil +} + +func isWindows() bool { + return runtime.GOOS == "windows" +} + +func isLinux() bool { + return runtime.GOOS == "linux" +} + +// getCompilerPath returns the path to the appropriate compiler +func getCompilerPath() (string, error) { + if isWindows() { + return exec.LookPath("g++") + } + return exec.LookPath("clang++") +} + +// ensureDirectory ensures the output directory exists +func ensureDirectory(path string) error { + dir := filepath.Dir(path) + if dir == "." { + return nil + } + return os.MkdirAll(dir, 0755) +} \ No newline at end of file diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..3f3f005 --- /dev/null +++ b/test.txt @@ -0,0 +1 @@ +Test content \ No newline at end of file diff --git a/tests/simple_ptr.ora b/tests/simple_ptr.ora new file mode 100644 index 0000000..c05fa32 --- /dev/null +++ b/tests/simple_ptr.ora @@ -0,0 +1,5 @@ +// 简单测试指针操作 +x := 100; +ptr := &x; +*ptr = 200; +println(x); \ No newline at end of file diff --git a/tests/test1.cpp b/tests/test1.cpp new file mode 100644 index 0000000..211ded7 --- /dev/null +++ b/tests/test1.cpp @@ -0,0 +1,22 @@ +// Generated by Oraset3 Compiler +#include +#include +#include +#include + +using namespace std; + +int main(); +void println(int value); + +int main() { +int x = 42 ; +int y = 18 ; +int sum = (x + y) ; +println(sum) ; +} + +void println(int value) { +((std::cout << value) << std::endl) ; +} + diff --git a/tests/test_bitops.ora b/tests/test_bitops.ora new file mode 100644 index 0000000..7e33d49 --- /dev/null +++ b/tests/test_bitops.ora @@ -0,0 +1,8 @@ +// 测试位操作符 +a := 10; +b := 12; +println(a & b); +println(a | b); +println(a ^ b); +println(a << 1); +println(a >> 1); \ No newline at end of file diff --git a/tests/test_cast.ora b/tests/test_cast.ora new file mode 100644 index 0000000..023e8e1 --- /dev/null +++ b/tests/test_cast.ora @@ -0,0 +1,3 @@ +num := 3.14; +intNum := (int)num; +println(intNum); \ No newline at end of file diff --git a/tests/test_enum.ora b/tests/test_enum.ora new file mode 100644 index 0000000..fcee75a --- /dev/null +++ b/tests/test_enum.ora @@ -0,0 +1,11 @@ +// 测试枚举 +enum Color { + RED, + GREEN, + BLUE = 10, + YELLOW +}; + +c := RED; +println(c); +println(BLUE); \ No newline at end of file diff --git a/tests/test_enum_use.ora b/tests/test_enum_use.ora new file mode 100644 index 0000000..586180f --- /dev/null +++ b/tests/test_enum_use.ora @@ -0,0 +1,10 @@ +enum Color { + RED, + GREEN, + BLUE = 10, + YELLOW +}; + +c := RED; +println(c); +println(BLUE); \ No newline at end of file diff --git a/tests/test_os_features.ora b/tests/test_os_features.ora new file mode 100644 index 0000000..ef72668 --- /dev/null +++ b/tests/test_os_features.ora @@ -0,0 +1,81 @@ +// Oraset3 操作系统级编程特性测试 +println("=== Oraset3 操作系统级编程特性 ==="); + +// 1. 位操作符测试 +println(""); +println("1. 位操作符测试:"); + +a := 10; // 0b1010 +b := 12; // 0b1100 + +println("a = 10 (0b1010)"); +println("b = 12 (0b1100)"); +println("a & b ="); +println(a & b); // 位与: 0b1000 = 8 +println("a | b ="); +println(a | b); // 位或: 0b1110 = 14 +println("a ^ b ="); +println(a ^ b); // 位异或: 0b0110 = 6 +println("a << 1 ="); +println(a << 1); // 左移: 20 +println("a >> 1 ="); +println(a >> 1); // 右移: 5 + +// 2. 枚举测试 +println(""); +println("2. 枚举测试:"); + +enum Color { + RED, + GREEN, + BLUE = 10, + YELLOW +}; + +c := RED; +println("Color.RED ="); +println(c); +println("Color.BLUE ="); +println(BLUE); + +// 3. 联合体测试 +println(""); +println("3. 联合体测试:"); + +union Data { + i: int; + f: float; + b: bool; +}; + +var data Data; +data.i = 42; +println("data.i ="); +println(data.i); + +// 4. 指针操作测试 +println(""); +println("4. 指针操作测试:"); + +x := 100; +ptr := &x; // 取地址 +println("x ="); +println(x); +println("*ptr ="); +println(*ptr); // 解引用 + +*ptr = 200; // 通过指针修改值 +println("修改后 x ="); +println(x); + +// 5. 类型转换测试 +println(""); +println("5. 类型转换测试:"); + +num := 3.14; +intNum := (int)num; +println("(int)3.14 ="); +println(intNum); + +println(""); +println("=== 操作系统级特性测试完成 ==="); \ No newline at end of file diff --git a/tests/test_simple_enum.ora b/tests/test_simple_enum.ora new file mode 100644 index 0000000..37d61f3 --- /dev/null +++ b/tests/test_simple_enum.ora @@ -0,0 +1 @@ +enum Test { A }; \ No newline at end of file diff --git a/tests/test_union.ora b/tests/test_union.ora new file mode 100644 index 0000000..8068560 --- /dev/null +++ b/tests/test_union.ora @@ -0,0 +1,8 @@ +union Data { + i: int; + f: float; +}; + +var data Data; +data.i = 42; +println(data.i); \ No newline at end of file