【开源编译器】二、(常量声明)基于Flex + Yacc开发的Fe语言编译器

  • 项目链接:https://github.com/FeliGame/FeCompiler
  • 本项目中的文法和AST数据结构设计参考了北京大学编译器实践项目pku-minic.github.io/online-doc/
  • 本博客会同步更新开发进度,欢迎各位交流、批评!

简介

Fe语言是一种语法类似C的高级语言,由于笔者将重点放在编译器的语义分析和代码优化上,因此目前阶段语法和C不会有什么不同。
该编译器会生成Koopa IR,并基于Koopa IR生成目标汇编代码(RISC-V)。

源代码结构

  • README 展示了具体的文法规则
  • fe.l 词法分析
  • fe.y 语法分析
  • ast.hpp 语法制导翻译的抽象语法树(目前实现是基于DFS的LR语法制导翻译),其中的Dump函数能够生成Koopa IR并导入到文件
  • main.cpp 输入fe源代码,选择输出文件、代码类型等(.fe->.koopa或者.fe->.koopa->.riscv)
  • riscv_gen.cpp 将分析出来的Koopa IR翻译成RISC-V
  • sbt.hpp 符号表,其中维护了:
    • BLOCK_HASH 维护【块ID, 块指针】的哈希表,其中块数据结构BlockNode的属性有父块指针、子块指针组,以此构成一个块树;
    • TYPE_HASH 用于实现【类型名】到【类型ID】的转换;
    • VAR_SBT、CONST_SBT、TYPE_SBT 基于vector< unordered_map < int, SBTNode> >实现的符号表。

目前进度

相较本系列上一篇博客(单语句计算器),可以实现多语句,常量的声明、定义,以及字面量的运算表达等,新增机制:

  • 引入了继承属性,成为LL语法分析,基本实现方式是在调用子节点Dump函数之前向子节点赋当前的继承属性值,而综合属性则在Dump函数调用之后由子节点赋给父节点;
  • ast.hpp中加入继承属性isConst,实现了【常量合并】的中间代码优化,大幅度减少了中间代码的指令数,例如:
int main() {
	return 1 + 3 * 4;
}
/* 
优化前生成中间代码Koopa IR如下:
fun @main(): i32 {
%entry:
%1 = add 1, 12
ret %1
}
常量合并优化:
fun @main(): i32 {
%entry:
ret 13
}
*/

原理:常量(包括字面量)之间的运算结果仍然是一个常量,因此当前节点isConst值设为真;若isConst值为真,则可以将常量合并的运算结果存放到综合属性r_val,并返回给归纳后的非终结符节点,以供后续使用;

  • 为了方便开发和debug,ast.hpp中加入debug_mode选项开关,设置为true时,可以输出中间代码生成时的AST层次结构,例如一段代码的输出如下:
int main() {
  	const int a = 1 + 1;
}

/*
debug_mode开启时,运行编译器会在cerr错误流输出如下信息:
comp_unit
|func_def
|func_def
||func_type
||block
block_item
|decl
||const_decl
b_type
|||const_defs
||||const_def
|||||const_init_val
||||||exp
|||||||lor
||||||||land
|||||||||eq
||||||||||rel
|||||||||||add
|||||||||||add
||||||||||||add
|||||||||||||mul
||||||||||||||unary
||||||||||||mul
|||||||||||||unary
*/

效果展示

int main() {
  // 忽略我的存在
  /*
    fa的发放啊\n\nff
  */
  const int a = 1 + 2 * 3;
  return a;
}
/*
输出的中间代码:
fun @main(): i32 {
%entry:
ret 7
}
*/

下一步加入

  • 变量声明和定义

解决的难题

  • SBT数据结构及相关函数调用的设计
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值