Initial commit: Oraset3 programming language with OS-level features
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
// Generated by Oraset3 Compiler
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <conio.h>
|
||||
#include <commdlg.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
#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
|
||||
}
|
||||
|
||||
+28
@@ -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
|
||||
*~
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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 ..
|
||||
@@ -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% 以上的功能,是一个功能完整、性能优异的编程语言!
|
||||
@@ -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`
|
||||
@@ -0,0 +1,54 @@
|
||||
// Generated by Oraset3 Compiler
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
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) ;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,463 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
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<std::unique_ptr<ASTNode>> 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<ASTNode> 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<std::pair<std::string, std::string>> params;
|
||||
std::string returnType;
|
||||
std::vector<std::unique_ptr<ASTNode>> 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<std::pair<std::string, std::string>> 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<std::pair<std::string, std::string>> 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<ASTNode> condition;
|
||||
std::vector<std::unique_ptr<ASTNode>> thenBranch;
|
||||
std::vector<std::unique_ptr<ASTNode>> 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<ASTNode> init;
|
||||
std::unique_ptr<ASTNode> condition;
|
||||
std::unique_ptr<ASTNode> update;
|
||||
std::vector<std::unique_ptr<ASTNode>> 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<ASTNode> condition;
|
||||
std::vector<std::unique_ptr<ASTNode>> 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<ASTNode> 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<ASTNode> 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<ASTNode> left;
|
||||
std::unique_ptr<ASTNode> 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<ASTNode> left;
|
||||
std::unique_ptr<ASTNode> 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<ASTNode> 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<ASTNode> callee;
|
||||
std::vector<std::unique_ptr<ASTNode>> 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<ASTNode> base;
|
||||
std::unique_ptr<ASTNode> 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<ASTNode> 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<std::pair<std::string, std::unique_ptr<ASTNode>>> 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<std::pair<std::string, std::string>> 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<std::pair<std::string, std::string>> 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<ASTNode> 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<Token> 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<std::unique_ptr<Token>> tokens);
|
||||
std::unique_ptr<ProgramNode> parse();
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<Token>> tokens;
|
||||
size_t pos;
|
||||
|
||||
Token* currentToken();
|
||||
Token* peekToken();
|
||||
void advance();
|
||||
bool match(TokenType type);
|
||||
bool consume(TokenType type);
|
||||
|
||||
std::unique_ptr<ASTNode> parseDeclaration();
|
||||
std::unique_ptr<ASTNode> parseVarDecl();
|
||||
std::unique_ptr<ASTNode> parseFuncDecl();
|
||||
std::unique_ptr<ASTNode> parseStructDecl();
|
||||
std::unique_ptr<ASTNode> parseInterfaceDecl();
|
||||
std::unique_ptr<ASTNode> parseUnionDecl();
|
||||
std::unique_ptr<ASTNode> parseEnumDecl();
|
||||
std::unique_ptr<ASTNode> parseStatement();
|
||||
std::unique_ptr<ASTNode> parseIfStmt();
|
||||
std::unique_ptr<ASTNode> parseForStmt();
|
||||
std::unique_ptr<ASTNode> parseWhileStmt();
|
||||
std::unique_ptr<ASTNode> parseReturnStmt();
|
||||
std::unique_ptr<ASTNode> parseBlock();
|
||||
std::unique_ptr<ASTNode> parseExpression();
|
||||
std::unique_ptr<ASTNode> parseAssignment();
|
||||
std::unique_ptr<ASTNode> parseLogicalOr();
|
||||
std::unique_ptr<ASTNode> parseLogicalAnd();
|
||||
std::unique_ptr<ASTNode> parseEquality();
|
||||
std::unique_ptr<ASTNode> parseComparison();
|
||||
std::unique_ptr<ASTNode> parseShift();
|
||||
std::unique_ptr<ASTNode> parseAdditive();
|
||||
std::unique_ptr<ASTNode> parseMultiplicative();
|
||||
std::unique_ptr<ASTNode> parseUnary();
|
||||
std::unique_ptr<ASTNode> parsePostfix();
|
||||
std::unique_ptr<ASTNode> 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<std::string>& getErrors() const { return errors; }
|
||||
|
||||
private:
|
||||
std::vector<std::string> errors;
|
||||
std::map<std::string, std::string> 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
|
||||
@@ -0,0 +1,714 @@
|
||||
#include "oraset3.h"
|
||||
#include <sstream>
|
||||
#include <cmath>
|
||||
|
||||
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 <iostream>");
|
||||
emitLine("#include <string>");
|
||||
emitLine("#include <vector>");
|
||||
emitLine("#include <map>");
|
||||
emitLine("#include <cmath>");
|
||||
emitLine("#include <fstream>");
|
||||
emitLine("#include <cstdio>");
|
||||
emitLine("#include <cstdlib>");
|
||||
emitLine("#include <sstream>");
|
||||
emitLine("#ifdef _WIN32");
|
||||
emitLine("#include <windows.h>");
|
||||
emitLine("#include <conio.h>");
|
||||
emitLine("#include <commdlg.h>");
|
||||
emitLine("#else");
|
||||
emitLine("#include <unistd.h>");
|
||||
emitLine("#include <sys/ioctl.h>");
|
||||
emitLine("#include <termios.h>");
|
||||
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<ASTNode*> 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<FuncDeclNode&>(*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<LiteralExprNode*>(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<IdentifierExprNode*>(node.callee.get());
|
||||
funcName = ident->name;
|
||||
} else if (node.callee->getType() == NodeType::MEMBER_EXPR) {
|
||||
MemberExprNode* member = static_cast<MemberExprNode*>(node.callee.get());
|
||||
if (member->object->getType() == NodeType::IDENTIFIER_EXPR) {
|
||||
IdentifierExprNode* objIdent = static_cast<IdentifierExprNode*>(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<LiteralExprNode*>(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<LiteralExprNode*>(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
|
||||
@@ -0,0 +1,403 @@
|
||||
#include "oraset3.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <cstdlib>
|
||||
#include <filesystem>
|
||||
#include <sstream>
|
||||
#include <chrono>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace oraset3 {
|
||||
|
||||
// 全局变量:是否导入了 sysui
|
||||
bool sysuiImported = false;
|
||||
|
||||
// 加载头文件
|
||||
std::string loadHeader(const std::string& headerName) {
|
||||
std::vector<std::string> 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<char>(ifs)),
|
||||
std::istreambuf_iterator<char>());
|
||||
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<std::unique_ptr<Token>> 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<char>(ifs)),
|
||||
std::istreambuf_iterator<char>());
|
||||
} // 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<char>(ifs)),
|
||||
std::istreambuf_iterator<char>());
|
||||
} // 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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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 <input_file> - Compile and run with full output" << std::endl;
|
||||
std::cerr << " oraset3 <input_file> <output_file> - Compile to C++ file" << std::endl;
|
||||
std::cerr << " oraset3 <input_file> --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<char>(ifs)),
|
||||
std::istreambuf_iterator<char>());
|
||||
|
||||
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<char>(ifs)),
|
||||
std::istreambuf_iterator<char>());
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
#include "oraset3.h"
|
||||
#include <cctype>
|
||||
#include <unordered_map>
|
||||
|
||||
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<Token> Lexer::nextToken() {
|
||||
skipWhitespace();
|
||||
|
||||
char c = currentChar();
|
||||
int tokenLine = line;
|
||||
int tokenColumn = column;
|
||||
|
||||
if (c == '\0') {
|
||||
return std::make_unique<Token>(TokenType::END_OF_FILE, "", tokenLine, tokenColumn);
|
||||
}
|
||||
|
||||
if (isalpha(c) || c == '_') {
|
||||
std::string id = readIdentifier();
|
||||
|
||||
static const std::unordered_map<std::string, TokenType> 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<Token>(it->second, id, tokenLine, tokenColumn);
|
||||
}
|
||||
return std::make_unique<Token>(TokenType::IDENTIFIER, id, tokenLine, tokenColumn);
|
||||
}
|
||||
|
||||
if (isdigit(c)) {
|
||||
std::string num = readNumber();
|
||||
if (num.find('.') != std::string::npos) {
|
||||
return std::make_unique<Token>(TokenType::FLOAT, num, tokenLine, tokenColumn);
|
||||
}
|
||||
return std::make_unique<Token>(TokenType::INTEGER, num, tokenLine, tokenColumn);
|
||||
}
|
||||
|
||||
if (c == '"' || c == '\'') {
|
||||
std::string str = readString(c);
|
||||
return std::make_unique<Token>(TokenType::STRING, str, tokenLine, tokenColumn);
|
||||
}
|
||||
|
||||
advance();
|
||||
|
||||
switch (c) {
|
||||
case '+': {
|
||||
if (currentChar() == '=') {
|
||||
advance();
|
||||
return std::make_unique<Token>(TokenType::ADD_ASSIGN, "+=", tokenLine, tokenColumn);
|
||||
}
|
||||
return std::make_unique<Token>(TokenType::PLUS, "+", tokenLine, tokenColumn);
|
||||
}
|
||||
case '-': {
|
||||
if (currentChar() == '=') {
|
||||
advance();
|
||||
return std::make_unique<Token>(TokenType::SUB_ASSIGN, "-=", tokenLine, tokenColumn);
|
||||
}
|
||||
return std::make_unique<Token>(TokenType::MINUS, "-", tokenLine, tokenColumn);
|
||||
}
|
||||
case '/': {
|
||||
if (currentChar() == '=') {
|
||||
advance();
|
||||
return std::make_unique<Token>(TokenType::DIV_ASSIGN, "/=", tokenLine, tokenColumn);
|
||||
}
|
||||
// 跳过注释
|
||||
if (currentChar() == '/') {
|
||||
while (currentChar() != '\n' && currentChar() != '\0') {
|
||||
advance();
|
||||
}
|
||||
return nextToken();
|
||||
}
|
||||
return std::make_unique<Token>(TokenType::DIV, "/", tokenLine, tokenColumn);
|
||||
}
|
||||
case '%': return std::make_unique<Token>(TokenType::MOD, "%", tokenLine, tokenColumn);
|
||||
case '=': {
|
||||
if (currentChar() == '=') {
|
||||
advance();
|
||||
return std::make_unique<Token>(TokenType::EQ, "==", tokenLine, tokenColumn);
|
||||
}
|
||||
return std::make_unique<Token>(TokenType::ASSIGN, "=", tokenLine, tokenColumn);
|
||||
}
|
||||
case '!': {
|
||||
if (currentChar() == '=') {
|
||||
advance();
|
||||
return std::make_unique<Token>(TokenType::NEQ, "!=", tokenLine, tokenColumn);
|
||||
}
|
||||
return std::make_unique<Token>(TokenType::NOT, "!", tokenLine, tokenColumn);
|
||||
}
|
||||
case '<': {
|
||||
if (currentChar() == '<') {
|
||||
advance();
|
||||
return std::make_unique<Token>(TokenType::SHL, "<<", tokenLine, tokenColumn);
|
||||
}
|
||||
if (currentChar() == '=') {
|
||||
advance();
|
||||
return std::make_unique<Token>(TokenType::LE, "<=", tokenLine, tokenColumn);
|
||||
}
|
||||
return std::make_unique<Token>(TokenType::LT, "<", tokenLine, tokenColumn);
|
||||
}
|
||||
case '>': {
|
||||
if (currentChar() == '>') {
|
||||
advance();
|
||||
return std::make_unique<Token>(TokenType::SHR, ">>", tokenLine, tokenColumn);
|
||||
}
|
||||
if (currentChar() == '=') {
|
||||
advance();
|
||||
return std::make_unique<Token>(TokenType::GE, ">=", tokenLine, tokenColumn);
|
||||
}
|
||||
return std::make_unique<Token>(TokenType::GT, ">", tokenLine, tokenColumn);
|
||||
}
|
||||
case '&': {
|
||||
if (currentChar() == '&') {
|
||||
advance();
|
||||
return std::make_unique<Token>(TokenType::AND, "&&", tokenLine, tokenColumn);
|
||||
}
|
||||
return std::make_unique<Token>(TokenType::BIT_AND, "&", tokenLine, tokenColumn);
|
||||
}
|
||||
case '|': {
|
||||
if (currentChar() == '|') {
|
||||
advance();
|
||||
return std::make_unique<Token>(TokenType::OR, "||", tokenLine, tokenColumn);
|
||||
}
|
||||
return std::make_unique<Token>(TokenType::BIT_OR, "|", tokenLine, tokenColumn);
|
||||
}
|
||||
case '^': return std::make_unique<Token>(TokenType::BIT_XOR, "^", tokenLine, tokenColumn);
|
||||
case '~': return std::make_unique<Token>(TokenType::BIT_NOT, "~", tokenLine, tokenColumn);
|
||||
case '*': {
|
||||
if (currentChar() == '=') {
|
||||
advance();
|
||||
return std::make_unique<Token>(TokenType::MUL_ASSIGN, "*=", tokenLine, tokenColumn);
|
||||
}
|
||||
return std::make_unique<Token>(TokenType::MUL, "*", tokenLine, tokenColumn);
|
||||
}
|
||||
case '(': return std::make_unique<Token>(TokenType::LPAREN, "(", tokenLine, tokenColumn);
|
||||
case ')': return std::make_unique<Token>(TokenType::RPAREN, ")", tokenLine, tokenColumn);
|
||||
case '{': return std::make_unique<Token>(TokenType::LBRACE, "{", tokenLine, tokenColumn);
|
||||
case '}': return std::make_unique<Token>(TokenType::RBRACE, "}", tokenLine, tokenColumn);
|
||||
case '[': return std::make_unique<Token>(TokenType::LBRACKET, "[", tokenLine, tokenColumn);
|
||||
case ']': return std::make_unique<Token>(TokenType::RBRACKET, "]", tokenLine, tokenColumn);
|
||||
case ',': return std::make_unique<Token>(TokenType::COMMA, ",", tokenLine, tokenColumn);
|
||||
case ';': return std::make_unique<Token>(TokenType::SEMICOLON, ";", tokenLine, tokenColumn);
|
||||
case ':': {
|
||||
if (currentChar() == ':') {
|
||||
advance();
|
||||
return std::make_unique<Token>(TokenType::DOUBLE_COLON, "::", tokenLine, tokenColumn);
|
||||
}
|
||||
if (currentChar() == '=') {
|
||||
advance();
|
||||
return std::make_unique<Token>(TokenType::COLON_ASSIGN, ":=", tokenLine, tokenColumn);
|
||||
}
|
||||
return std::make_unique<Token>(TokenType::COLON, ":", tokenLine, tokenColumn);
|
||||
}
|
||||
case '.': return std::make_unique<Token>(TokenType::DOT, ".", tokenLine, tokenColumn);
|
||||
case '$': {
|
||||
advance(); // 跳过 $
|
||||
std::string id = readIdentifier();
|
||||
return std::make_unique<Token>(TokenType::IMPORT_DIRECTIVE, id, tokenLine, tokenColumn);
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_unique<Token>(TokenType::END_OF_FILE, "", tokenLine, tokenColumn);
|
||||
}
|
||||
|
||||
} // namespace oraset3
|
||||
@@ -0,0 +1,797 @@
|
||||
#include "oraset3.h"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace oraset3 {
|
||||
|
||||
Parser::Parser(std::vector<std::unique_ptr<Token>> 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<ProgramNode> Parser::parse() {
|
||||
auto program = std::make_unique<ProgramNode>();
|
||||
|
||||
while (currentToken()) {
|
||||
program->declarations.push_back(parseDeclaration());
|
||||
}
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
std::unique_ptr<ASTNode> 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<ExprStmtNode>();
|
||||
}
|
||||
// 检查是否是 := 声明(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<ExprStmtNode>();
|
||||
advance();
|
||||
consume(TokenType::SEMICOLON);
|
||||
return stmt;
|
||||
}
|
||||
if (match(TokenType::CONTINUE)) {
|
||||
auto stmt = std::make_unique<ExprStmtNode>();
|
||||
advance();
|
||||
consume(TokenType::SEMICOLON);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
// 顶层表达式语句(无需函数包装)
|
||||
std::unique_ptr<ASTNode> expr = parseExpression();
|
||||
consume(TokenType::SEMICOLON);
|
||||
|
||||
// 将表达式包装在 ExprStmtNode 中
|
||||
auto stmt = std::make_unique<ExprStmtNode>();
|
||||
stmt->expr = std::move(expr);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
std::unique_ptr<ASTNode> Parser::parseVarDecl() {
|
||||
auto decl = std::make_unique<VarDeclNode>();
|
||||
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<ASTNode> Parser::parseFuncDecl() {
|
||||
auto decl = std::make_unique<FuncDeclNode>();
|
||||
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<ASTNode> Parser::parseStructDecl() {
|
||||
auto decl = std::make_unique<StructDeclNode>();
|
||||
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<ASTNode> Parser::parseInterfaceDecl() {
|
||||
auto decl = std::make_unique<InterfaceDeclNode>();
|
||||
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<ASTNode> Parser::parseUnionDecl() {
|
||||
auto decl = std::make_unique<UnionDeclNode>();
|
||||
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<ASTNode> Parser::parseEnumDecl() {
|
||||
auto decl = std::make_unique<EnumDeclNode>();
|
||||
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<ASTNode> 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<ExprStmtNode>();
|
||||
advance();
|
||||
consume(TokenType::SEMICOLON);
|
||||
return stmt;
|
||||
}
|
||||
if (match(TokenType::CONTINUE)) {
|
||||
auto stmt = std::make_unique<ExprStmtNode>();
|
||||
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<ASTNode> expr = parseExpression();
|
||||
consume(TokenType::SEMICOLON);
|
||||
|
||||
// 将表达式包装在 ExprStmtNode 中
|
||||
auto stmt = std::make_unique<ExprStmtNode>();
|
||||
stmt->expr = std::move(expr);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
std::unique_ptr<ASTNode> Parser::parseBlock() {
|
||||
auto block = std::make_unique<ExprStmtNode>();
|
||||
advance(); // 跳过 {
|
||||
|
||||
// 简单处理:只处理第一个语句
|
||||
if (!match(TokenType::RBRACE) && currentToken()) {
|
||||
block->expr = parseStatement();
|
||||
}
|
||||
|
||||
// 跳过其余语句直到找到 }
|
||||
while (!match(TokenType::RBRACE) && currentToken()) {
|
||||
advance();
|
||||
}
|
||||
|
||||
consume(TokenType::RBRACE);
|
||||
return block;
|
||||
}
|
||||
|
||||
std::unique_ptr<ASTNode> Parser::parseIfStmt() {
|
||||
auto stmt = std::make_unique<IfStmtNode>();
|
||||
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<ASTNode> Parser::parseWhileStmt() {
|
||||
auto stmt = std::make_unique<WhileStmtNode>();
|
||||
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<ASTNode> Parser::parseForStmt() {
|
||||
auto stmt = std::make_unique<ForStmtNode>();
|
||||
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<ASTNode> Parser::parseReturnStmt() {
|
||||
auto stmt = std::make_unique<ReturnStmtNode>();
|
||||
advance(); // 跳过 return
|
||||
|
||||
if (!match(TokenType::SEMICOLON)) {
|
||||
stmt->expr = parseExpression();
|
||||
}
|
||||
|
||||
consume(TokenType::SEMICOLON);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
std::unique_ptr<ASTNode> Parser::parseExpression() {
|
||||
return parseAssignment();
|
||||
}
|
||||
|
||||
std::unique_ptr<ASTNode> Parser::parseAssignment() {
|
||||
std::unique_ptr<ASTNode> left = parseLogicalOr();
|
||||
|
||||
if (match(TokenType::ASSIGN) || match(TokenType::COLON_ASSIGN)) {
|
||||
auto assign = std::make_unique<AssignExprNode>();
|
||||
assign->left = std::move(left);
|
||||
assign->op = match(TokenType::ASSIGN) ? "=" : ":=";
|
||||
advance();
|
||||
assign->right = parseAssignment();
|
||||
return assign;
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
std::unique_ptr<ASTNode> Parser::parseLogicalOr() {
|
||||
std::unique_ptr<ASTNode> left = parseLogicalAnd();
|
||||
|
||||
while (match(TokenType::OR)) {
|
||||
auto binary = std::make_unique<BinaryExprNode>();
|
||||
binary->left = std::move(left);
|
||||
binary->op = "||";
|
||||
advance();
|
||||
binary->right = parseLogicalAnd();
|
||||
left = std::move(binary);
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
std::unique_ptr<ASTNode> Parser::parseLogicalAnd() {
|
||||
std::unique_ptr<ASTNode> left = parseEquality();
|
||||
|
||||
while (match(TokenType::AND)) {
|
||||
auto binary = std::make_unique<BinaryExprNode>();
|
||||
binary->left = std::move(left);
|
||||
binary->op = "&&";
|
||||
advance();
|
||||
binary->right = parseEquality();
|
||||
left = std::move(binary);
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
std::unique_ptr<ASTNode> Parser::parseEquality() {
|
||||
std::unique_ptr<ASTNode> left = parseComparison();
|
||||
|
||||
while (match(TokenType::EQ) || match(TokenType::NEQ)) {
|
||||
auto binary = std::make_unique<BinaryExprNode>();
|
||||
binary->left = std::move(left);
|
||||
binary->op = match(TokenType::EQ) ? "==" : "!=";
|
||||
advance();
|
||||
binary->right = parseComparison();
|
||||
left = std::move(binary);
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
std::unique_ptr<ASTNode> Parser::parseComparison() {
|
||||
std::unique_ptr<ASTNode> left = parseShift();
|
||||
|
||||
while (match(TokenType::LT) || match(TokenType::GT) || match(TokenType::LE) || match(TokenType::GE)) {
|
||||
auto binary = std::make_unique<BinaryExprNode>();
|
||||
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<ASTNode> Parser::parseShift() {
|
||||
std::unique_ptr<ASTNode> 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<BinaryExprNode>();
|
||||
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<ASTNode> Parser::parseAdditive() {
|
||||
std::unique_ptr<ASTNode> left = parseMultiplicative();
|
||||
|
||||
while (match(TokenType::PLUS) || match(TokenType::MINUS)) {
|
||||
auto binary = std::make_unique<BinaryExprNode>();
|
||||
binary->left = std::move(left);
|
||||
binary->op = match(TokenType::PLUS) ? "+" : "-";
|
||||
advance();
|
||||
binary->right = parseMultiplicative();
|
||||
left = std::move(binary);
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
std::unique_ptr<ASTNode> Parser::parseMultiplicative() {
|
||||
std::unique_ptr<ASTNode> left = parseUnary();
|
||||
|
||||
while (match(TokenType::MUL) || match(TokenType::DIV) || match(TokenType::MOD)) {
|
||||
auto binary = std::make_unique<BinaryExprNode>();
|
||||
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<ASTNode> 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<UnaryExprNode>();
|
||||
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<ASTNode> Parser::parsePostfix() {
|
||||
std::unique_ptr<ASTNode> expr = parsePrimary();
|
||||
|
||||
while (true) {
|
||||
if (match(TokenType::LPAREN)) {
|
||||
// 函数调用
|
||||
auto call = std::make_unique<CallExprNode>();
|
||||
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<StructInitNode>();
|
||||
structInit->typeName = static_cast<IdentifierExprNode*>(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<ASTNode> 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<MemberExprNode>();
|
||||
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<IndexExprNode>();
|
||||
index->base = std::move(expr);
|
||||
index->index = parseExpression();
|
||||
consume(TokenType::RBRACKET);
|
||||
expr = std::move(index);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
std::unique_ptr<ASTNode> 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<CastExprNode>();
|
||||
cast->targetType = targetType;
|
||||
cast->expr = parseUnary(); // 使用 parseUnary 允许括号内的表达式
|
||||
return cast;
|
||||
}
|
||||
}
|
||||
|
||||
if (match(TokenType::INTEGER) || match(TokenType::FLOAT)) {
|
||||
auto lit = std::make_unique<LiteralExprNode>();
|
||||
lit->value = tokens[pos]->value;
|
||||
lit->type = match(TokenType::FLOAT) ? "float" : "int";
|
||||
advance();
|
||||
return lit;
|
||||
}
|
||||
|
||||
if (match(TokenType::STRING)) {
|
||||
auto lit = std::make_unique<LiteralExprNode>();
|
||||
lit->value = tokens[pos]->value;
|
||||
lit->type = "string";
|
||||
advance();
|
||||
return lit;
|
||||
}
|
||||
|
||||
if (match(TokenType::TRUE)) {
|
||||
auto lit = std::make_unique<LiteralExprNode>();
|
||||
lit->value = "true";
|
||||
lit->type = "bool";
|
||||
advance();
|
||||
return lit;
|
||||
}
|
||||
|
||||
if (match(TokenType::FALSE)) {
|
||||
auto lit = std::make_unique<LiteralExprNode>();
|
||||
lit->value = "false";
|
||||
lit->type = "bool";
|
||||
advance();
|
||||
return lit;
|
||||
}
|
||||
|
||||
if (match(TokenType::IDENTIFIER)) {
|
||||
auto ident = std::make_unique<IdentifierExprNode>();
|
||||
ident->name = tokens[pos]->value;
|
||||
advance();
|
||||
return ident;
|
||||
}
|
||||
|
||||
if (match(TokenType::LPAREN)) {
|
||||
advance();
|
||||
std::unique_ptr<ASTNode> expr = parseExpression();
|
||||
consume(TokenType::RPAREN);
|
||||
return expr;
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unexpected token");
|
||||
}
|
||||
|
||||
} // namespace oraset3
|
||||
@@ -0,0 +1,313 @@
|
||||
#include "oraset3.h"
|
||||
#include <sstream>
|
||||
|
||||
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<FuncDeclNode&>(*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<VarDeclNode&>(*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<StructDeclNode&>(*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<InterfaceDeclNode&>(*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<UnionDeclNode&>(*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<EnumDeclNode&>(*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<FuncDeclNode&>(*decl);
|
||||
|
||||
// 保存当前符号表状态
|
||||
std::map<std::string, std::string> 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<VarDeclNode&>(*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<VarDeclNode&>(*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
|
||||
@@ -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 <input_file> <output_file>")
|
||||
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)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// 简单测试指针操作
|
||||
x := 100;
|
||||
ptr := &x;
|
||||
*ptr = 200;
|
||||
println(x);
|
||||
@@ -0,0 +1,22 @@
|
||||
// Generated by Oraset3 Compiler
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
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) ;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// 测试位操作符
|
||||
a := 10;
|
||||
b := 12;
|
||||
println(a & b);
|
||||
println(a | b);
|
||||
println(a ^ b);
|
||||
println(a << 1);
|
||||
println(a >> 1);
|
||||
@@ -0,0 +1,3 @@
|
||||
num := 3.14;
|
||||
intNum := (int)num;
|
||||
println(intNum);
|
||||
@@ -0,0 +1,11 @@
|
||||
// 测试枚举
|
||||
enum Color {
|
||||
RED,
|
||||
GREEN,
|
||||
BLUE = 10,
|
||||
YELLOW
|
||||
};
|
||||
|
||||
c := RED;
|
||||
println(c);
|
||||
println(BLUE);
|
||||
@@ -0,0 +1,10 @@
|
||||
enum Color {
|
||||
RED,
|
||||
GREEN,
|
||||
BLUE = 10,
|
||||
YELLOW
|
||||
};
|
||||
|
||||
c := RED;
|
||||
println(c);
|
||||
println(BLUE);
|
||||
@@ -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("=== 操作系统级特性测试完成 ===");
|
||||
@@ -0,0 +1 @@
|
||||
enum Test { A };
|
||||
@@ -0,0 +1,8 @@
|
||||
union Data {
|
||||
i: int;
|
||||
f: float;
|
||||
};
|
||||
|
||||
var data Data;
|
||||
data.i = 42;
|
||||
println(data.i);
|
||||
Reference in New Issue
Block a user