热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

自己动手制作C语言编译器(1):设计

这篇文章我们要从整体上讲解如何设计我们的C语言编译器。本系列:首先要说明的是,虽然标题是编译器,但实际上我们构建的是C语言的解释器&#

这篇文章我们要从整体上讲解如何设计我们的 C 语言编译器。

本系列:

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

1.解释器与编译器仅在代码生成阶段有区别,而其它方面如词法分析、语法分析是一样的。

2.解释器需要我们实现自己的虚拟机与指令集,而这部分能帮助我们了解计算机的工作原理。

编译器的构建流程

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

1.词法分析器,用于将字符串转化成内部的表示结构。

2.语法分析器,将词法分析得到的标记流(token)生成一棵语法树。

3.目标代码的生成,将语法树转化成目标代码。

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

所以我们会根据下面的流程:

1.构建我们自己的虚拟机以及指令集。这后生成的目标代码便是我们的指令集。

2.构建我们的词法分析器

3.构建语法分析器

编译器的框架

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

next()用于词法分析,获取下一个标记,它将自动忽略空白字符。

program()语法分析的入口,分析整个 C 语言程序。

expression(level)用于解析一个表达式。

eval()虚拟机的入口,用于解释目标代码。

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

因为我们的源代码看起来就像是:

#include

#include

#include

#include

 

int token;            // current token

char *src, *old_src;  // pointer to source code string;

int poolsize;         // default size of text/data/stack

int line;             // line number

 

void next() {

    token = *src++;

    return;

}

 

void expression(int level) {

    // do nothing

}

 

void program() {

    next();                  // get next token

    while (token > 0) {

        printf("token is: %c\n", token);

        next();

    }

}

 

int eval() { // do nothing yet

    return 0;

}

 

int main(int argc, char **argv)

{

    int i, fd;

 

    argc--;

    argv++;

 

    poolsize = 256 * 1024; // arbitrary size

    line = 1;

 

    if ((fd &#61; open(*argv, 0)) <0) {

        printf("could not open(%s)\n", *argv);

        return -1;

    }

 

    if (!(src &#61; old_src &#61; malloc(poolsize))) {

        printf("could not malloc(%d) for source area\n", poolsize);

        return -1;

    }

 

    // read the source file

    if ((i &#61; read(fd, src, poolsize-1)) <&#61; 0) {

        printf("read() returned %d\n", i);

        return -1;

    }

    src[i] &#61; 0; // add EOF character

    close(fd);

 

    program();

    return eval();

}

上面的代码看上去挺复杂&#xff0c;但其实内容不多&#xff0c;就是读取一个源代码文件&#xff0c;逐个读取每个字符&#xff0c;并输出每个字符。这里重要的是注意每个函数的作用&#xff0c;后面的文章中&#xff0c;我们将逐个填充每个函数的功能&#xff0c;最终构建起我们的编译器。如果想一起交流的可以加这个群&#xff1a;941636044 &#xff0c;有什么问题可以群里面交流&#xff0c;群里面也有一些方便学习C语言C&#43;&#43;编程的资料可以给你利用。

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


推荐阅读
  • 如何在 Node.js 环境中将 CSV 数据转换为标准的 JSON 文件格式? ... [详细]
  • 基址获取与驱动开发:内核中提取ntoskrnl模块的基地址方法解析
    基址获取与驱动开发:内核中提取ntoskrnl模块的基地址方法解析 ... [详细]
  • 求助高手调试程序,非常感谢您的支持!在编写C语言程序时遇到了一些问题,具体代码如下:```c#include #include #include #define MAX 50int t;```希望有经验的开发者能提供指导,帮助解决调试中的难题。感谢您的时间和帮助! ... [详细]
  • 掌握PHP编程必备知识与技巧——全面教程在当今的PHP开发中,了解并运用最新的技术和最佳实践至关重要。本教程将详细介绍PHP编程的核心知识与实用技巧。首先,确保你正在使用PHP 5.3或更高版本,最好是最新版本,以充分利用其性能优化和新特性。此外,我们还将探讨代码结构、安全性和性能优化等方面的内容,帮助你成为一名更高效的PHP开发者。 ... [详细]
  • 在探讨C语言编程文本编辑器的最佳选择与专业推荐时,本文将引导读者构建一个基础的文本编辑器程序。该程序不仅能够打开并显示文本文件的内容及其路径,还集成了菜单和工具栏功能,为用户提供更加便捷的操作体验。通过本案例的学习,读者可以深入了解文本编辑器的核心实现机制。 ... [详细]
  • 本文详细探讨了Java中Unicode编码的二进制转换方法及其具体实现。通过分析\u开头的字符串,解释了每组\uxxxx如何对应一个特定的Unicode字符,并提供了相关代码示例以加深理解。希望读者在实际开发中能有效应用这些知识。 ... [详细]
  • 本文详细探讨了Zebra路由软件中的线程机制及其实际应用。通过对Zebra线程模型的深入分析,揭示了其在高效处理网络路由任务中的关键作用。文章还介绍了线程同步与通信机制,以及如何通过优化线程管理提升系统性能。此外,结合具体应用场景,展示了Zebra线程机制在复杂网络环境下的优势和灵活性。 ... [详细]
  • 如何高效启动大数据应用之旅?
    在前一篇文章中,我探讨了大数据的定义及其与数据挖掘的区别。本文将重点介绍如何高效启动大数据应用项目,涵盖关键步骤和最佳实践,帮助读者快速踏上大数据之旅。 ... [详细]
  • 在处理遗留数据库的映射时,反向工程是一个重要的初始步骤。由于实体模式已经在数据库系统中存在,Hibernate 提供了自动化工具来简化这一过程,帮助开发人员快速生成持久化类和映射文件。通过反向工程,可以显著提高开发效率并减少手动配置的错误。此外,该工具还支持对现有数据库结构进行分析,自动生成符合 Hibernate 规范的配置文件,从而加速项目的启动和开发周期。 ... [详细]
  • 在ROS环境中解决libxml2 I/O警告:无法加载外部实体问题的详细方法
    在ROS环境中解决libxml2 I/O警告:无法加载外部实体问题的详细方法 ... [详细]
  • 在 Windows 10 环境中,通过配置 Visual Studio Code (VSCode) 实现基于 Windows Subsystem for Linux (WSL) 的 C++ 开发,并启用智能代码提示功能。具体步骤包括安装 VSCode 及其相关插件,如 CCIntelliSense、TabNine 和 BracketPairColorizer,确保在 WSL 中顺利进行开发工作。此外,还详细介绍了如何在 Windows 10 中启用和配置 WSL,以实现无缝的跨平台开发体验。 ... [详细]
  • 在晴朗天气条件下,对一种神奇的魔法现象进行了深入分析。该题目为原创,基准时间限制为1秒,空间限制为131072KB,分值20,属于3级难度的算法题。研究发现,这种魔法现象在阳光明媚的环境中表现得尤为显著,进一步探讨了其背后的科学原理和技术实现方法。 ... [详细]
  • 每日精选Codeforces训练题:1119E(贪心算法)、821C(栈模拟)和645D(拓扑排序)
    题目涉及三种不同类型的算法问题:1119E(贪心算法)、821C(栈模拟)和645D(拓扑排序)。其中,1119E的问题背景是有n种不同长度的棍子,长度分别为2^0, 2^1, …, 2^(n-1),每种棍子的数量为a[i]。任务是计算可以组成的三角形数量。根据三角形的性质,任意两边之和必须大于第三边。该问题可以通过贪心算法高效解决,通过合理选择棍子组合来最大化三角形的数量。 ... [详细]
  • Eclipse JFace Text框架中IDocument接口的getNumberOfLines方法详解与编程实例 ... [详细]
  • 本文基于Proteus平台,对步进电机的仿真与控制技术进行了深入研究。通过修改代码,实现了步进电机精确转动1圈的控制。实验结果验证了该方法的有效性和可靠性,为步进电机在精密控制领域的应用提供了有力支持。 ... [详细]
author-avatar
暮色归家
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有