这是“手把手教你构建 C 语言编译器”系列的第二篇,我们要从整体上讲解如何设计我们的 C 语言编译器。

手把手教你构建 C 语言编译器系列共有10个部分:

  1. 手把手教你构建 C 语言编译器(0)——前言
  2. 手把手教你构建 C 语言编译器(1)——设计
  3. 手把手教你构建 C 语言编译器(2)——虚拟机
  4. 手把手教你构建 C 语言编译器(3)——词法分析器
  5. 手把手教你构建 C 语言编译器(4)——递归下降
  6. 手把手教你构建 C 语言编译器(5)——变量定义
  7. 手把手教你构建 C 语言编译器(6)——函数定义
  8. 手把手教你构建 C 语言编译器(7)——语句
  9. 手把手教你构建 C 语言编译器(8)——表达式
  10. 手把手教你构建 C 语言编译器(9)——总结

首先要说明的是,虽然标题是编译器,但实际上我们构建的是 C 语言的解释器,这意味着我们可以像运行脚本一样去运行 C 语言的源代码文件。这么做的理由有两点:

  1. 解释器与编译器仅在代码生成阶段有区别,而其它方面如词法分析、语法分析是一样的。
  2. 解释器需要我们实现自己的虚拟机与指令集,而这部分能帮助我们了解计算机的工作原理。

编译器的构建流程

一般而言,编译器的编写分为 3 个步骤:

  1. 词法分析器,用于将字符串转化成内部的表示结构。
  2. 语法分析器,将词法分析得到的标记流(token)生成一棵语法树。
  3. 目标代码的生成,将语法树转化成目标代码。

已经有许多工具能帮助我们处理阶段1和2,如 flex 用于词法分析,bison 用于语法分析。只是它们的功能都过于强大,屏蔽了许多实现上的细节,对于学习构建编译器帮助不大。所以我们要完全手写这些功能。

所以我们会依照以下步骤来构建我们的编译器:

  1. 构建我们自己的虚拟机以及指令集。这后生成的目标代码便是我们的指令集。
  2. 构建我们的词法分析器
  3. 构建语法分析器

编译器框架

我们的编译器主要包括 4 个函数:

  1. next() 用于词法分析,获取下一个标记,它将自动忽略空白字符。
  2. program() 语法分析的入口,分析整个 C 语言程序。
  3. expression(level) 用于解析一个表达式。
  4. eval() 虚拟机的入口,用于解释目标代码。

这里有一个单独用于解析“表达式”的函数 expression 是因为表达式在语法分析中相对独立并且比较复杂,所以我们将它单独作为一个模块(函数)。下面是相应的源代码:

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>int token;            // current token
char *src, *old_src;  // pointer to source code string;
int poolsize;         // default size of text/data/stack
int line;             // line numbervoid next() {token = *src++;return;
}void expression(int level) {// do nothing
}void program() {next();                  // get next tokenwhile (token > 0) {printf("token is: %c\n", token);next();}
}int eval() { // do nothing yetreturn 0;
}int main(int argc, char **argv)
{int i, fd;argc--;argv++;poolsize = 256 * 1024; // arbitrary sizeline = 1;if ((fd = open(*argv, 0)) < 0) {printf("could not open(%s)\n", *argv);return -1;}if (!(src = old_src = malloc(poolsize))) {printf("could not malloc(%d) for source area\n", poolsize);return -1;}// read the source fileif ((i = read(fd, src, poolsize-1)) <= 0) {printf("read() returned %d\n", i);return -1;}src[i] = 0; // add EOF characterclose(fd);program();return eval();
}

上面的代码看上去挺复杂,但其实内容不多。它的流程为:读取一个文件(内容为 C 语言代码),逐个读取文件中的字符,并输出。这里需要的是注意每个函数的作用,后面的文章中,我们将逐个填充每个函数的功能,最终构建起我们的编译器。

本节的代码可以在 Github 上下载,也可以直接 clone

git clone -b step-0 https://github.com/lotabout/write-a-C-interpreter

这样我们就有了一个最简单的编译器:什么都不干的编译器,下一章中,我们将实现其中的eval函数,即我们自己的虚拟机。

转自https://lotabout.me/2015/write-a-C-interpreter-1/

手把手教你构建 C 语言编译器(1)- 设计相关推荐

  1. 手把手教你构建 C 语言编译器(8)- 表达式

    这是整个编译器的最后一部分,解析表达式.什么是表达式?表达式是将各种语言要素的一个组合,用来求值.例如:函数调用.变量赋值.运算符运算等等. 表达式的解析难点有二:一是运算符的优先级问题,二是如何将表 ...

  2. 手把手教你构建 C 语言编译器.参考.0 -- 前言

    手把手教你构建C语言编译器.参考.0 -- 前言 写在前面 简介 写在前面 在此,十分感谢 三点水 的学习分享手把手教你构建 C 语言编译器: https://lotabout.me/2015/wri ...

  3. 手把手教你构建 C 语言编译器(4)- 递归下降

    本章我们将讲解递归下降的方法,并用它完成一个基本的四则运算的语法分析器. 手把手教你构建 C 语言编译器系列共有10个部分: 手把手教你构建 C 语言编译器(0)--前言 手把手教你构建 C 语言编译 ...

  4. 手把手教你构建 C 语言编译器(3)- 词法分析器

    本章我们要讲解如何构建词法分析器. 手把手教你构建 C 语言编译器系列共有10个部分: 手把手教你构建 C 语言编译器(0)--前言 手把手教你构建 C 语言编译器(1)--设计 手把手教你构建 C ...

  5. alpha因子常见问题_手把手教你构建量化因子分析体系

    原标题:手把手教你构建量化因子分析体系 挖掘Alpha因子.评价Alpha因子.改进Alpha因子是量化投资者职业生涯永恒的奋斗目标,而一套严密有效的因子分析体系是这一切的基石."不以规矩, ...

  6. 独家 | 手把手教你学习R语言(附资源链接)

    作者:NSS 翻译:杨金鸿 术语校对:韩海畴 全文校对:林亦霖 本文约3000字,建议阅读7分钟. 本文为带大家了解R语言以及分段式的步骤教程! 人们学习R语言时普遍存在缺乏系统学习方法的问题.学习者 ...

  7. 超级干货 :手把手教你学习R语言(附资源链接)

    作者:NSS:翻译:杨金鸿:校对:韩海畴,林亦霖: 本文约3000字,建议阅读7分钟. 本文为带大家了解R语言以及分段式的步骤教程! 人们学习R语言时普遍存在缺乏系统学习方法的问题.学习者不知道从哪开 ...

  8. 手把手教你学习R语言

    本文为带大家了解R语言以及分段式的步骤教程! 人们学习R语言时普遍存在缺乏系统学习方法的问题.学习者不知道从哪开始,如何进行,选择什么学习资源.虽然网络上有许多不错的免费学习资源,然而它们多过了头,反 ...

  9. 6个关键步骤,手把手教你构建图模型

    导读:图模型作为当前流行的信息处理加工技术,自提出以来,迅速在学术界和工业界得到了普及,在智能推荐.决策分析等方面有着广泛的应用. 作者:华为公司数据管理部 来源:大数据DT(ID:hzdashuju ...

  10. 实战案例,手把手教你构建电商用户画像 | 附代码

    导读:本文以真实案例,手把手教你搭建电商系统的用户画像. 先来看该电商用户画像用到的标签. 数据内容包括user_id(用户身份).item_id(商品).IDbehavior_type(用户行为类型 ...

最新文章

  1. .NET平台开源项目速览(2)Compare .NET Objects对象比较组件
  2. Linux下用iptables做端口映射
  3. 算法-----数组------合并两个有序数组
  4. sql server与java实例_Origin数据处理实例教程50节02040101
  5. 转 -----那些年总也记不牢的IO
  6. 每列大于0的个数_题目1342——把一个数字减少到0的步骤数
  7. 2017.9.5 postgresql加密函数的使用
  8. Java构造方法的继承调用
  9. java 奇数 字符乱码_socket中文奇数个出现乱码的解决办法
  10. Python MySQL示例教程
  11. BIGEMAP APP离线卫星地图数据应用
  12. 可以插卡的ipad_平板电脑可以插手机卡吗,终于能插卡了!苹果iPad 2018蜂窝网络版上架国内官网...
  13. 1.7 爬取汽车之家实战
  14. Red Rover 简单字符串应用
  15. 安装sql server 过程(为了使用SQL Server Management Studio)
  16. Scene…… couldn‘t be loaded because it has not been added to the build settings or the AssetBundle...
  17. 163邮箱申请注册条件,邮件注册申请,邮箱的格式怎么写?
  18. SAP S4 MM配置详解之三:物料主数据-定义物料类型/物料状态/字段选择控制/物料组
  19. 培训机构出来的程序员目前的就业前景怎么样?
  20. 成兴光 | LED灯珠的封装形式

热门文章

  1. 微商公社新兵连第六天
  2. 拳王虚拟项目公社:你最重要的事情是什么?
  3. Linux编程经典实例,PyQt4 精彩实例分析 - 实例1 Hello Kitty! _Linux编程_Linux公社-Linux系统门户网站...
  4. processing图片粒子化_谈谈文字图片粒子化
  5. 手写Vue个人组件库——fl-Badge
  6. 2019年8月2 星期五 今日计划
  7. L1-017 到底有多二 (15 分) C语言
  8. 如何设置电脑桌面动态壁纸
  9. 【旧资料整理】笔记本无线共享路由器网络连接方法要点总结
  10. what to benefit from the C++14 Standard