feat: L Language v0.1 编译器完整实现

5 阶段编译流水线: 词法分析 → 语法分析(Pratt) → 语义分析(类型推断) → LLVM IR → .exe

模块:
- lexer: 手写状态机, 40 种 Token, // 和 /* */ 注释
- parser: Pratt 表达式解析(9 级优先级) + 递归下降语句/函数
- ast: 14 种节点类型 + 工厂函数
- sema: 作用域链符号表 + 类型推断 + 类型检查
- codegen: AST → LLVM-C API, print_i64/f64/bool 内建
- driver: 命令行 + 流水线串联 + 错误报告
- util: Arena bump allocator (8MB)

测试: 65 单元测试(词法41+语法15+语义9) + 5 集成测试 全部通过

语言特性: i64/f64/bool/void, let不可变变量, if/else, while, 递归函数
This commit is contained in:
2026-06-05 00:26:59 +08:00
commit 3b7bab1e1b
40 changed files with 5804 additions and 0 deletions
+94
View File
@@ -0,0 +1,94 @@
cmake_minimum_required(VERSION 3.20)
project(l_lang C)
set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED ON)
# === LLVM 配置 ===
set(LLVM_PREFIX "D:/settings/Language/LLVM" CACHE PATH "LLVM installation prefix")
# 查找 LLVM(优先使用 CONFIG 模式,失败则手动配置)
find_package(LLVM 19 QUIET CONFIG
HINTS ${LLVM_PREFIX}/lib/cmake/llvm
${LLVM_PREFIX}/cmake
)
if(NOT LLVM_FOUND)
message(STATUS "LLVM CONFIG not found — using manual LLVM paths")
set(LLVM_FOUND TRUE)
set(LLVM_INCLUDE_DIRS "${LLVM_PREFIX}/include")
set(LLVM_LIBRARY_DIR "${LLVM_PREFIX}/lib")
set(LLVM_LIBRARIES "${LLVM_PREFIX}/lib/LLVM-C.lib")
# 标记使用手动模式
set(LLVM_MANUAL_MODE ON)
else()
message(STATUS "LLVM found: ${LLVM_DIR}")
message(STATUS "LLVM includes: ${LLVM_INCLUDE_DIRS}")
message(STATUS "LLVM available libs: ${LLVM_AVAILABLE_LIBS}")
set(LLVM_MANUAL_MODE OFF)
endif()
# === 编译器库(不含 main.c,供测试复用)===
file(GLOB_RECURSE L_LANG_LIB_SOURCES "src/*.c")
list(REMOVE_ITEM L_LANG_LIB_SOURCES "${CMAKE_SOURCE_DIR}/src/driver/main.c")
add_library(l_lang_lib STATIC ${L_LANG_LIB_SOURCES})
target_include_directories(l_lang_lib PRIVATE
${CMAKE_SOURCE_DIR}/include
${LLVM_INCLUDE_DIRS}
src/util src/lexer src/ast src/parser src/sema src/codegen src/driver
)
target_compile_options(l_lang_lib PRIVATE -Wall -Wextra -g)
# === 编译器可执行文件 ===
add_executable(l_lang src/driver/main.c)
target_link_libraries(l_lang PRIVATE l_lang_lib)
target_include_directories(l_lang PRIVATE
${CMAKE_SOURCE_DIR}/include
${LLVM_INCLUDE_DIRS}
src/util src/lexer src/ast src/parser src/sema src/codegen src/driver
)
# === 链接 LLVM(通过库)===
if(LLVM_MANUAL_MODE)
target_link_libraries(l_lang_lib PUBLIC ${LLVM_LIBRARIES})
message(STATUS "Linking LLVM manually: ${LLVM_LIBRARIES}")
else()
target_link_libraries(l_lang_lib PUBLIC LLVM)
endif()
# === LLVM 定义 ===
if(NOT LLVM_MANUAL_MODE)
target_compile_definitions(l_lang_lib PRIVATE ${LLVM_DEFINITIONS})
endif()
# === 测试可执行文件(每个测试文件独立编译,各有自己的 main)===
# Parser 测试
add_executable(l_lang_test test/test_parser.c)
target_link_libraries(l_lang_test PRIVATE l_lang_lib)
target_include_directories(l_lang_test PRIVATE
${CMAKE_SOURCE_DIR}/include
${LLVM_INCLUDE_DIRS}
src/util src/lexer src/ast src/parser src/sema src/codegen src/driver
test
)
# Lexer 测试
add_executable(l_lang_lexer_test test/test_lexer.c)
target_link_libraries(l_lang_lexer_test PRIVATE l_lang_lib)
target_include_directories(l_lang_lexer_test PRIVATE
${CMAKE_SOURCE_DIR}/include
${LLVM_INCLUDE_DIRS}
src/util src/lexer src/ast src/parser src/sema src/codegen src/driver
test
)
# Sema 测试
add_executable(l_lang_sema_test test/test_sema.c)
target_link_libraries(l_lang_sema_test PRIVATE l_lang_lib)
target_include_directories(l_lang_sema_test PRIVATE
${CMAKE_SOURCE_DIR}/include
${LLVM_INCLUDE_DIRS}
src/util src/lexer src/ast src/parser src/sema src/codegen src/driver
test
)