Skip to content

Repository files navigation

面向SysY2022的编译器

本项目是一个面向 SysY2022 的分阶段编译器实现。这个目录收集了项目从词法分析、语法分析、语义分析与 LLVM IR 生成,到 RISC-V 目标代码生成和后端优化的核心版本,方便展示一个编译器从前端到后端逐步成型的过程。

整理时只保留核心源码、必要说明和本地演示脚本,未纳入测试输出、公开测试点数据、性能实验产物、依赖缓存和旧实验二进制文件。

语言与标准依据

本编译器主要参照课程给定的 SysY2022 语言定义和实验文法实现。SysY 是用于编译原理教学和编译系统竞赛的 C 语言子集,整体语义接近 C,但语法范围和运行时接口经过裁剪,适合按编译器阶段逐步实现。

本仓库已收录必要参考文档:

核心文法入口为:

CompUnit -> { Decl } { FuncDef } MainFuncDef

程序由全局声明、普通函数定义和 main 函数组成。支持的主要语法成分包括:

  • 声明:常量声明 ConstDecl、变量声明 VarDecl
  • 类型:以 int 为基础,后续版本也保留了部分 float 处理能力
  • 函数:int / void 函数、形参表、实参表和函数调用
  • 语句:赋值、表达式语句、语句块、if/elsewhilebreakcontinuereturn
  • 输入输出:getint()printf(...)
  • 左值:普通变量、一维数组、二维数组
  • 表达式:一元表达式、乘除模、加减、关系、相等、逻辑与、逻辑或、常量表达式

表达式优先级和结合性按类 C 规则组织,逻辑运算 &&|| 需要满足短路求值语义。

词法规范

词法分析阶段识别 SysY 源码中的 token,并过滤空白与注释。主要 token 类型包括:

  • 关键字:constintvoidifelsewhilebreakcontinuereturnprintf
  • 标识符:由字母或下划线开头,后接字母、数字或下划线
  • 整数常量:支持十进制、八进制和十六进制形式;课程语义约束中要求普通十进制整数不能含非法前导零
  • 字符串常量:用于 printf,转义字符重点支持 \n
  • 运算符:+-*/%=!<><=>===!=&&||
  • 分隔符:()[]{};,
  • 注释:支持 // 行注释和 /* ... */ 块注释

早期词法版本使用 Flex 生成扫描器;后续完整编译器版本改为手写词法分析器,便于和递归下降语法分析、错误定位和后端生成逻辑集成。

语法与语义约束

语法分析阶段参照 SysY2022 EBNF 文法,将可选结构 [] 和重复结构 {} 改写为 Bison 或递归下降可处理的产生式。语法分析实验要求输出指定非终结符,例如 <CompUnit><FuncDef><Stmt><AddExp> 等,同时不输出 <BlockItem><Decl><BType> 等辅助节点。

重要语义约束包括:

  • 常量表达式 ConstExp -> AddExp 中引用的标识符必须是常量
  • 常量数组不能作为函数实参传递
  • 相邻的一元运算符不能相同,例如 --+4 不符合语义约束
  • 一元 ! 只用于条件表达式相关语义
  • printf 字符串中的转义字符重点限制为 \n
  • 有返回值函数的最后一条语句应为 return
  • main 函数返回值按课程约定处理

中间代码和目标代码阶段还需要维护作用域、符号表、常量值、数组维度、函数签名、控制流标签、循环上下文和运行时调用信息。

中间表示与目标平台

第三阶段生成 LLVM IR。LLVM IR 是一种与具体机器无关的中间表示,便于表达变量、临时值、控制流、函数调用和内存访问,也便于用 lli 进行本地解释执行验证。

第四、五阶段生成 64-bit RISC-V 汇编,接口遵循目标代码生成任务要求:

compiler -S -o testcase.s testcase.sy

最终竞赛版额外支持:

compiler -S -o testcase.s testcase.sy -O1

其中 -O1 用于开启保守优化。优化目标是在通过功能测试的前提下改进生成汇编的执行效率。

编译器总体结构

完整编译器的典型处理流程如下:

SysY 源码
-> 词法分析,生成 token 序列
-> 语法分析,构造语法结构或 AST
-> 语义分析,维护符号表、类型、作用域和常量信息
-> 中间代码生成,输出 LLVM IR
-> 目标代码生成,输出 RISC-V 汇编
-> 可选优化,改进常量、分支、循环、寄存器和局部代码质量

项目中的早期版本更强调单个实验阶段的输出格式;后期版本逐渐合并为单文件编译器,直接完成从 SysY 源文件到 LLVM IR 或 RISC-V 汇编的翻译。

版本索引

  1. 01_Lexical_Analysis_Front_End

    • 阶段:词法分析前端
    • 来源:Lexical_analyzer/
    • 作用:基于 Flex 实现 SysY 词法分析,识别关键字、标识符、常量、运算符和分隔符等词法单元,属于早期词法分析实验版本。
  2. 02_Syntax_Analysis_Front_End

    • 阶段:语法分析前端
    • 来源:Syntax_analyzer1/
    • 作用:基于 Flex/Bison 实现 SysY 语法分析,并按实验要求输出指定的语法非终结符。
    • 选择理由:相比 Syntax_analyzer/,该版本通过包装规约只输出一次 <CompUnit>,更符合语法分析实验中“父节点标签只输出一次”的要求。
  3. 03_Semantic_Analysis_LLVM_IR_Generation

    • 阶段:语义分析与 LLVM IR 中间代码生成
    • 来源:Intermediate_code_generation/compiler.cpp
    • 作用:单文件 SysY 编译器,包含手写词法分析、递归下降语法分析、AST 构建、语义处理和 LLVM IR 生成,读取 testfile.txt 并输出 output.ll
  4. 04_RISCV_Backend_Code_Generation

    • 阶段:RISC-V 后端目标代码生成
    • 来源:Target_code_generation/Compiler.cpp
    • 作用:将 SysY 源程序翻译为 64 位 RISC-V 汇编,满足 compiler -S -o testcase.s testcase.sy 的目标代码生成接口;该版本保留为竞赛优化前的基础后端版本。
  5. 05_Optimizing_RISCV_Backend

    • 阶段:带优化的 RISC-V 后端
    • 来源:Competition/Compiler.cpp
    • 作用:最终竞赛版 SysY 编译器,支持 RISC-V 汇编生成,并提供 -O1 优化模式。
    • 选择理由:该文件与最新的可提交备份 Competition/backups/Compiler_submit_ready_random_state_cache_fix_20260601.cpp 内容一致,因此将根目录下的 Competition/Compiler.cpp 作为最终优化版的标准版本。

本地演示

可以运行统一演示脚本感受每个阶段的效果:

./run_stage_demos.sh

只运行某个阶段:

./run_stage_demos.sh --stage 3

保留临时输出文件:

./run_stage_demos.sh --keep

脚本会展示词法 token、语法规约输出、LLVM IR、普通 RISC-V 汇编和 -O1 优化版 RISC-V 汇编。lli 是可选依赖;如果本机安装了 lli,第三阶段会额外执行生成的 LLVM IR。

About

Coursework for the Compilation Principles Course

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages