当前位置: 首页 > news >正文

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

这是“手把手教你构建 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/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-3209.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

html表单

表单语法&#xff1a; 表单元素格式&#xff1a; 语法&#xff1a; 表单元素&#xff1a; 文本框-语法 <input type"text"(文本框) name"userName"(文本框名称) value"用户名"(文本框初始值) size"30"(文本框长度) maxlength…...

12个夏季旅行彩色lr预设

夏季来临&#xff0c;计划海滩旅行的朋友&#xff0c;可以试试这款12个夏季旅行彩色lr预设&#xff0c;这些预设将帮助您获得清晰、专业的旅行照片&#xff0c;只需单击一下按钮&#xff0c;即可获得完美、专业的触感。 12个夏季旅行彩色lr预设介绍 由来自51个国家和地区的国…...

LeetCode每日一题 - 有多少小于当前数字的数字

题目&#xff1a; 给你一个数组 nums&#xff0c;对于其中每个元素 nums[i]&#xff0c;请你统计数组中比它小的所有数字的数目。 换而言之&#xff0c;对于每个 nums[i] 你必须计算出有效的 j 的数量&#xff0c;其中 j 满足 j ! i 且 nums[j] < nums[i] 。 以数组形式返回…...

用Python爬取彼岸图网图片

用Python爬取彼岸图网图片 *使用了 四个模块 import time import requests from lxml import etree import os 没有的话自行百度安装。 #encoding utf-8 import time import requests from lxml import etree import os# http://www.netbian.com/ 爬虫 if __name__ __mai…...

Ambari2.7.3集群Oozie调度Spark示例

文章目录1.环境准备2.修改配置文件2.1 解压Oozie自带样例包2.2 修改workflow.xml文件2.3 修改job.properties文件3.上传到HDFS4.提交任务5.监控1.环境准备 集群版本&#xff1a;Ambari2.7.3 HDP3.0.1.0-187集群开启Kerberos身份认证&#xff0c;Ranger权限认证 2.修改配置文…...

02.xshell连不上虚拟机linux的解决办法

虚拟机使用的NAT模式&#xff0c;用Xshell一直连接不上虚拟机上的Linux&#xff0c;最后百度搜索之后&#xff0c;解决步骤如下&#xff1a; 1.在虚拟机里面输入ifconfig&#xff0c;查询虚拟机ip地址 2.打开网络连接&#xff0c;修改VMnet1 IP地址改为与虚拟机同一网段 比如…...

第k个数(快速选择)

算法思路 快速选择&#xff1a; 1.即任意选一个数&#xff0c;将数组划分为二。 2.最终根据该数所在的位置&#xff0c;即第&#xff1f;大&#xff0c;选择第k大的数字所在区间进行划分。 时间复杂度分析&#xff0c;第一次划分n,下一次划分期望n/2&#xff0c;n/4…累加和小…...

2021年茶艺师(中级)模拟考试及茶艺师(中级)模拟考试系统

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 茶艺师&#xff08;中级&#xff09;模拟考试是安全生产模拟考试一点通总题库中随机出的一套茶艺师&#xff08;中级&#xff09;模拟考试系统&#xff0c;在公众号安全生产模拟考试一点通上点击茶艺师&#xff08;中…...

yolov5 detect.py报错

新手求助 yolov5训练了自己的数据集后&#xff0c;test没问题&#xff0c;但是运行detect.py就报错了&#xff0c;一直找不到问题所在&#xff0c; 求大佬指点指点...

DEX 争霸战火升级,BabySwap 会否成为下一代黑马?

在 AMM机制大力推动下&#xff0c;DEX的群雄争霸比预想中来得要快且凶猛。伴随着诸如高盛等主流资本逐步认可DeFi 的意义&#xff0c;在真正的去中心化金融爆发的前夜&#xff0c;可以说谁抢占了DEX 红海的先机&#xff0c;谁就赢得了未来。 从早期以太坊的Uniswap和DoDo&…...

flutter 常用的第三方组件

引用文章链接&#xff1a; https://www.jianshu.com/p/a523e5f131b2 1、格式化日期时间组件&#xff1a;https://pub.dev/packages/date_format 2、日期选择组件&#xff1a;https://pub.dev/packages/flutter_cupertino_date_picker 3、轮播图组件&#xff1a;https://pub.…...

nginx隐藏x-real-ip头配置

实现隐藏X-Real-Ip头&#xff0c;可通过配置server{} proxy_set_header实现。 server { listen 10.10.98.10:8080 backlog20480; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_…...

8.文本处理(编码解码/文件操作)

本章主要从文本处理、系统监控、日志、FTP、邮件监控、微信监控等方面来介绍基础运维的相关知识。 8.1 文本处理 在日常的运维工作中一般都离不开与文本,如日志分析、编码转换、ETL加工等。本节从编码原理、文本操作、读写配置文件、解析XML等实用编程知识出发,希望能抛砖引…...

【vue】vue3学习笔记(三)

接上篇 面包屑 安装path-to-regexpcomponent/breadcrumb/index <template><el-breadcrumb class"app-breadcrumb breadcrumb-container" separator"/"><el-breadcrumb-item v-for"(item, index) in levelList" :key"item…...

MVC三层架构

什么是MVC&#xff1a; Model view Controller 模型、视图、控制器 1.以前的架构模型 用户直接访问控制层&#xff0c;控制层就可以直接操作数据库&#xff1b; servlet--CRUD-->数据库 弊端&#xff1a;程序十分臃肿&#xff0c;不利于维护 servlet的代码中&#xff1a…...

zookeeper--一致性协议 ZAB

一、简介 ZAB 协议全称&#xff1a;Zookeeper Atomic Broadcast&#xff08;Zookeeper 原子广播协议&#xff09;。 是一个为分布式应用提供高效且可靠的分布式协调服务。在解决分布式一致性方面&#xff0c;Zookeeper 并没有使用 Paxos &#xff0c;而是采用了 ZAB 协议。 Z…...

Android面试回忆录:帮助程序员提高核心竞争力的30条建议,真香!

**新技术层出不穷&#xff0c;去年kotlin到如今Flutter&#xff0c;技术迭代&#xff0c;你是否会变得固步自封&#xff1f;**那么看本篇文章帮你解决问题&#xff0c;让你知道怎么样学习&#xff0c;学习那些技术点才能不被时代的迭代快速淘汰&#xff01; 首先&#xff0c;先…...

2021-05-30解决centos+宝塔面板,FTP传输421 Too many connections问题错误

解决centos宝塔面板&#xff0c;FTP传输421 Too many connections”问题错误 1、首先连入服务器 在/www/server/pure-ftpd/etc下&#xff0c;找到pure-ftpd.conf 2、vim pure-ftpd.conf 没有vim的&#xff0c;用其他编辑软件也可以 3、找到 #Maximum number of sim clients wit…...

RK3399 DDR频率修改

RK3399 DDR频率修改 一、DDR当前频率获取与可调节范围 1、获取当前DDR频率、可调值、容量 cat /sys/class/devfreq/dmc/cur_freq2、查看DDR频率可调节的值 cat /sys/class/devfreq/dmc/available_frequencies3、获取DDR容量 cat /proc/meminfo二、DDR测试定频 1、因为RK3…...

javascript正则表达式常用合集

javascript正则表达式常用的合集 参考网址 {n}: n 是一个正整数&#xff0c;匹配了前面一个字符刚好出现了 n 次 {n,}: n是一个正整数&#xff0c;匹配前一个字符至少出现了n次 {n,m}: n 和 m 都是整数。匹配前面的字符至少n次&#xff0c;最多m次。如果 n 或者 m 的值是0&…...

++i与i++的区别

i是先自增&#xff0c;再返回i i是先返回i&#xff0c;再自增...

Typora + GitHub云笔记本

前言&#xff1a;Typora是一款牛逼的编辑器&#xff0c;这应该是大家公认的吧&#xff0c;不过也有人觉得并非如此&#xff0c;毕竟&#xff0c;它就像八九十年代的大哥大&#xff0c;你只有带着你的电脑才能看到你自己写的笔记&#xff0c;如何拉屎的时候也可以自我陶醉在自己…...

一文读懂参考基因组和基因组注释+最全下载方法

文章目录一、什么是参考基因组和基因组注释&#xff1f;二、参考基因组版本命名1、常用人参考基因组对应表2、常用小鼠参考基因组对应表三、下载1、NCBI2、Ensemble3、GENCODE4、UCSC5、iGenomes四、其他参考基因组信息一、什么是参考基因组和基因组注释&#xff1f; 先来理一…...

关于函数传参的再理解(含引用)

情景引入—小小日记 6/1的我开开心心的度过儿童节&#xff0c;复习一哈数据结构课上的内容。 but&#xff01;&#xff0c;这红红的一条让我心慌。不可创建变量&#xff01; 下面是当时的源码&#xff08;二叉排序树&#xff09; #include <iostream> using namespace…...

DockerMaven插件

DockerMaven插件 前言 微服务部署我所知的目前有三种方式: &#xff08;1&#xff09;手动部署&#xff1a;首先基于源码打包生成jar包&#xff08;或war包&#xff09;&#xff0c;将jar包&#xff08;或war包&#xff09;上传至虚拟机并拷贝至JDK容器 &#xff08;2&…...

性能工具之Jmeter-Dubbo脚本开发

内容目录&#xff1a; 1、idea 环境项目部署 2、nacos 环境部署 3、dubbo插件部署 4、不带参数请求 5、带参参数请求 Apache Dubbo 是一款高性能、轻量级的开源Java RPC框架&#xff0c;它提供了三大核心能力&#xff1a;面向接口的远程方法调用&#xff0c;智能容错和负载均衡…...

有关斜率的数学题?

转自自家学校的OJ网站 题目描述&#xff1a; Description cdwcgt成为了风纪班的成员&#xff01; 风纪班的主要任务为维持治安、巡逻、注意可疑人物、仲裁吵架、追查违法药品&#xff0c;所涉及范围广大&#xff0c;偶尔会有较危险的工作。 职能与警方有重叠&#xff0c;因此经…...

后端 | SpringBoot整合Dubbo+Nacos2

1.前言 这是一个基于SpringBoot整合Apache DubboNacos的极简教程&#xff0c;笔者使用到的技术及版本如下&#xff1a; SpringBoot 2.4.5 Dubbo 2.7.11 Nacos 2.0.1&#xff08;自行安装&#xff09; Dubbo官网&#xff1a;https://dubbo.apache.org/zh/ Nacos官网&#…...

JavaEE期末考 Struts实例

Struts实例代码Web代码List.jspEdit.jsp配置文件默认包下的struts.xmlWEB-INF下的web.xmlJava代码action包BookAction.javadao包BookDao.javaBookDaoImpl.javadb包DBConnection.javafactory包DAOFactory.javamodel包Book.javaservice包BookService.javap1包和pojo包为空使用的库…...

SpringCloud-07-sleuth+zipkin

Spring Cloud Sleuth是Spring Cloud提供的分布式跟踪解决方案&#xff0c;它借用了Google的Dapper组件的术语&#xff0c;并且兼容Twitter的Zipkin。 Spring Cloud Sleuth官网&#xff1a;https://docs.spring.io/spring-cloud-sleuth/docs/2.2.8.RELEASE/reference/html/#ter…...

python爬虫中怎么写反爬虫

1、通过UA判断&#xff1a;UA是UserAgent&#xff0c;是要求浏览器的身份标志。 UA是UserAgent&#xff0c;是要求浏览器的身份标志。反爬虫机制通过判断访问要求的头部没有UA来识别爬虫&#xff0c;这种判断方法水平很低&#xff0c;通常不作为唯一的判断标准。反爬虫非常简单…...

浅谈基于GIS天地图进行商业市场分析及信息系统设计实现

摘要&#xff1a;天地图主要提供地图浏览和查询服务&#xff0c;形式单一&#xff0c;商业推广与市场竞争力较弱&#xff0c;造成了公众对天地图的使用率与依赖性不高。本文以拓展天地图的商业价值为主要目的&#xff0c;分析了互联网团购信息的特点&#xff0c;重点设计了多源…...

python开发要学什么_运维为什么要学编程?编程为什么是Python?

作者介绍&#xff1a; comyn&#xff0c;李学明。python大神&#xff0c;原大众点评运维平台架构师&#xff0c;腾讯广告部核心运维专家&#xff0c;饿了么Python运维开发高级总监&#xff0c;现就职于海淘公司。多年一线运维经验&#xff0c;参与过架构改造、平台迁移、自动化…...

[转载] 全班95%孩子不认识蜡烛!科学老师很无奈:到底是孩子无知,还是课本OUT

转载来源: https://baijiahao.baidu.com/s?id1620333427946564962&wfrspider&forpc 孙老师在杭州一所热门公办小学教科学&#xff0c;已经有二十年的教龄&#xff0c;这礼拜竟然被一个三年级小朋友的问题难住了! 当天&#xff0c;她上的是实验课&#xff0c;因为要研…...

CSDN学霸课表——Unity全掌握

Unity大型网络游戏开发实战视频课程讲师&#xff1a;张刚 本次系列课程的目标是让Unity3D初学者快速掌握Unity3d的网络开发技术,课程重点将对TCP数据通信时如何对数据进行序列化和反序列化&#xff0c;如何解析数据包等重要知识点进行深入探讨。对使用unity开发网络游戏和网络…...

基于Unity的游戏开发(上)-李学明-专题视频课程

基于Unity的游戏开发(上)—60061人已学习 课程介绍 本课程是Unity游戏开发的入门课程&#xff0c;课程分为上、下两个部分。上篇主要讲述游戏的基本概念、Unity的开发环境、游戏资源的创建和使用等基础内容。课程收益通过本课程学习&#xff0c;学生将熟悉Unity的开发环境&a…...

基于Unity的游戏开发(下)-李学明-专题视频课程

基于Unity的游戏开发&#xff08;下&#xff09;—31071人已学习 课程介绍 本课程是Unity游戏开发的入门课程&#xff0c;课程分为上、下两个部分。下部分主要介绍JavaScript脚本程序开发、动画、粒子、网络和GUI系统课程收益通过本课程的学习&#xff0c;学员将了解JavaScr…...

为什么叫python编程-运维为什么要学编程?编程为什么是Python?

作者介绍&#xff1a; comyn&#xff0c;李学明。python大神&#xff0c;原大众点评运维平台架构师&#xff0c;腾讯广告部核心运维专家&#xff0c;饿了么Python运维开发高级总监&#xff0c;现就职于海淘公司。多年一线运维经验&#xff0c;参与过架构改造、平台迁移、自动化…...

Unity游戏开发基础-李学明-专题视频课程

Unity游戏开发基础—2792人已学习 课程介绍 以Unity 2017版为基础&#xff0c;详细介绍Unity游戏开发的基本过程和基本技术&#xff0c;包括&#xff1a;资源创建、灯光、声音、GUI、动画控制和网络游戏开发等内容。 课程主要以实例演示方式进行讲解&#xff0c;并提供实例工…...

数组的平移操作

问题描述&#xff1a;给定一个数组&#xff0c;对其扩容后得到一个新数组&#xff0c;将和原数组中对应的元素往后平移给定的偏移量对应的位数&#xff0c;若平移后会越界&#xff0c;则至多平移至新数组的末尾。 1.给定数组&#xff08;原数组&#xff09; int[] ints { 1,…...

图像处理之图像平移

一、图像平移 图像平移&#xff1a;将图像上的所有像素点按照给定的偏移量移动&#xff0c;平移不改变图像内容&#xff0c;只改变图像位置 设像素点(x,y)(x, y)(x,y)进行平移到点(x∗,y∗)(x^*, y^*)(x∗,y∗)&#xff0c;其中xxx轴方向的平移量为Δx\Delta{x}Δx&#xff0c;…...

matlab 傅里叶平移,图像处理:二维傅里叶变化的平移性_matlab实现

傅里叶变化的平移性&#xff1a;matlab代码验证过程实现&#xff1a;%% 研究傅里叶变化 的 平移特性%空间域 乘以exp &#xff0c;频率域移动clc;clearI imread(rice.jpg);I rgb2gray(I);I im2double(I);figure;subplot(1, 3, 1);imshow(I);title(原图);%傅里叶变化f fft2(…...

数据增广:旋转,缩放,平移以及错切

在深度学习&#xff08;图像领域&#xff09;中&#xff0c;为了提升训练样本数量数据增广是非常常见的手段。比如&#xff1a; 随机水平翻转随机色调(H)、饱和度(S)、明度(V)调整随机旋转&#xff0c;缩放&#xff0c;平移以及错切还有近几年常用的mixup&#xff0c;mosaic等…...

巧妙地数组之类的数据平移

最新博客地址,欢迎访问^_^ 巧妙的序列型数据平移原理代码实现原理 例如{1&#xff0c; 2&#xff0c; 3&#xff0c; 4&#xff0c; 5&#xff0c; 6&#xff0c; 7&#xff0c;8}要向左平移2个单位 先将前两个数据{1&#xff0c;2}反转为{2&#xff0c;1}之后将后面的数据{3…...

图像平移

图像平移定义&#xff1a;将图像中所有的点按照指定的平移量水平或者垂直移动 对于原图中被移出图像显示区域的点通常有两种处理方法&#xff1a;可以直接丢弃&#xff0c;也可以通过适当增加目标图像尺寸的方法使得新图像中能够包含这些点。 MATLAB实现&#xff1a; %图像平移…...

1 奥运排行榜 (30分)

代码&#xff1a; #include <algorithm> #include <stdio.h> #include <algorithm> using namespace std;struct node1 {int ID;int glod; }country1[230]; struct node2 {int ID;int award; }country2[230]; struct node3 {int ID;double glod_ave; }count…...

css 平移到某个位置_CSS3平移动画效果

在这篇文章中主要是讲如何通过CSS3实现平移动画效果&#xff0c;在开始之前先给大家介绍一下与平移动画有关的CSS3属性以及相关的属性描述。一、transition-property&#xff1a;是用来指定当元素其中一个属性改变时执行transition效果(例如&#xff1a;长度&#xff0c;宽度&a…...

Flutter 平移动画 — 4种实现方式

系列文章 Flutter 旋转动画 — RotationTransitionFlutter 平移动画 — 4种实现方式Flutter 淡入淡出与逐渐出现动画Flutter 尺寸缩放、形状、颜色、阴影变换动画Flutter 列表Item动画 — AnimatedList实现Item左进左出、淡入淡出Flutter Hero 实现共享元素转场动画Flutter He…...

html中列表怎么平移,css如何设置图片平移

css设置图片平移的方法&#xff1a;1、通过“translate(x,y)”属性使元素在x轴和y轴方向同时移动&#xff1b;2、通过“translate X(x)”属性使元素仅在x轴方向移动&#xff1b;3、通过“translateY(y)”属性使元素仅在y轴方向移动即可。本教程操作环境&#xff1a;windows7系统…...

html5 div平移,使用JavaScript平移DIV元素

我试图在容器中有一个div,当用户单击并拖动文档区域中的某个位置时,按住中间的单击按钮,.room元素将在.viewport元素内平移.JSvar mouseX 0;var mouseY 0;var scale 1.0;$(document).mousemove(function (e) {var offset $(.room).offset();//relative mouse x,ymouseX pa…...