diy编译器 0x02 lexical

想实现的目标

首先,我想给自己定一个小目标,有点挑战性的目标。

单纯模仿 c 实现一个编译器并无难度,我希望学到更多的东西。

首先,我想实现模板的一小部分,了解下模板和范型的底层实现原理。

其次,如果可能的话,我想加入多文件的编译控制,并非简单的替换。

最后,如果还有时间的话,我希望能够实现 new 出的指针的自动回收机制(参考Rust的垃圾回收)

当然,如果这些也知识尽量去做,模板是我最想实现的。

文法定义

为了让它像一门语言,我认为 lcc 至少应包含一下几种语句:

预处理 ;函数 ;简单的模板 ;表达式 ;迭代与分支 ;

因此,我对我的文法定义如下:

暂时语法中未添加类与自动回收的规则,如果条件允许会在之后补充。

其中语法规则的命名参考了 c++17 的标准。c++ 17 的EBNF 表示如下:

文法规则概述

文法定义从 <translation-unit> 开始

预处理定义从 <preprocessing-seq> 开始

函数与模板的声明从 <function-defination> 和 <template-declaration> 开始

语句定义从 <statement-seq> 开始

表达式定义从 <expression> 开始

基本符号定义全部归为 <literal>

变量定义从 <type-id> 开始


lcc 的文法支持一定的预处理,函数,模板函数,指针,条件,循环,表达式

变量分为 char bool short int long fload void,和复杂类型 enum

其中 string 和 char 支持转义字符

定义的运算符如下:

? : 条件赋值||逻辑或
连接多个表达式&&逻辑与
|按位或^按位异或
&按位与==判断相等
!=判断不等<小于
>大于<=小于等于
>=大于等于<<左移
>>右移+
*
/%模除
(typeid)强制类型转换++前置自增
前置自减*解引用
&取地址+
!逻辑非
~按位取反[]数组
++后置自增后置自减
->enum指针的元素.enum的元素
static_cast<>逻辑类型转换()括号

运算符全部按照优先级从文法中依次定义。

预处理可以支持:

#if #ifdef #ifndef #elif #else #endif 
#include ""     #include <>
#define #undef
#pragma once
#pragma message()
#pragma error()

条件语句和循环语句支持:

if else
switch case
while
do while
break
continue
goto:

模板定义格式必须如下

template <typename A> 
A* func(A a)
{
    return &a;
}

数字只能为十进制。

diy编译器 0x01 项目组织

项目预计分为多个模块,模块间低耦合,编译器前后端分离,方便移植多平台与多语言。

模块:

(ing)

词法分析模块

中间代码生成模块

代码优化模块

目标代码生成模块

表格管理模块

项目架构

预计项目通过 cmake 编译,各模块独立编译成库,便于相互调用。目录结构如下:

.
├── bin
│   └── tcc
├── cmake
│   ├── toolchain_options.cmake
│   └── utils.cmake
├── CMakeLists.txt
├── conf
├── doc
│   ├── c++17_lexical.html
│   └── lex_lcc.xlsx
├── lib
│   ├── CMakeLists.txt
│   ├── cmdline
│   │   ├── cmdline.cxx
│   │   └── cmdline.h
│   └──libcmdline.a
├── LICENSE
├── platform
├── README.md
├── scripts
├── src
│   ├── CMakeLists.txt
│   ├── common
│   │   └── version.hpp
│   ├── lex
│   │   ├── CMakeLists.txt
│   │   ├── lex.cpp
│   │   ├── lex.hpp
│   │   ├── liblex.a
│   │   └── Makefile
│   ├── main
│   │   ├── main.cpp
│   │   └── main.hpp
└── test

/lib:引用的外部库,如命令行解析,日志生成,多线程调用,数据库

/src:编写的各个模块与上层模块,除顶层模块外全部编译为静态链接库

/test:存放一些测试代码

/scripts:存放测试脚本

diy编译器 0x00 General

why?

这将会是一系列文章,从0开始造轮子。这是本系列的第一个部分,编译原理。本部分会从头编写一个编译器,对应的语言就叫 lcc 吧(less cc),编译器叫做 tcc (tiny cc),计划实现 c++ 语言的一个子集。(包含部分的模板)。短期内暂时没有支持类(class)的计划。系列将会在之后统一在 B 站更新视频,希望补充下在重复造轮子的领域内的学习资源的空白。项目的代码仓库为 https://gitee.com/dupeiran/tcc。

how?

系列目录如下(ing):