---
title: c语言手搓一个500+行的类c语言解释器（1）- 目标和前言
date: 2020-04-10T22:37:45-08:00
tags: tutorial
---

# 用c语言手搓一个500+行的类c语言解释器: 给编程初学者的解释器教程（1）- 目标和前言

项目github地址及源码：
[https://github.com/yunwei37/tryC](https://github.com/yunwei37/tryC)

## 一个小目标
这一系列教程希望面向初学者，使用c语言手工实现一个简单的解释器来玩，不需要您掌握除了c语言以外的其他前置知识，也不需要您学习过编译原理的相关知识（当然如果能对简单的数据结构有所了解的话会更好，比如树、栈等）。

> 写一个能执行代码的解释器不仅是一件很有（zhuang）趣（bi）的事情，大概也可以作为刚学习完c语言的一个练手的小项目啦

不同于大部分常见的其他只支持四则运算的所谓”手工解释器“教程，我们希望在代码结构尽量清晰的600行代码中，手工（不借助lex/yacc等工具）完成一个脚本语言“try”，实现以下功能：

- 选择和循环的流程控制语句
- 支持的数据类型：双精度浮点数、字符型、字符串、浮点数数组
- 支持函数和变量的定义、函数的递归调用、嵌套作用域

（如果看不懂下面这段也没关系，可以略过啦）

> 这个小玩意采用递归下降法进行语法分析，同时不显式构建语法树，不生成中间代码或目标代码，在语法分析的同时进行解释执行；

### 解释器可运行的代码示例
递归计算文波那契数列 1 - 15，将结果存入数组中，并打印：
    
```c
# Fibonacci sequence
func fun{ 
	if(x <= 2){  
		return(1);  
	}
	y = 0;
	x = x - 1;
	y = fun(x);
	x = x - 1;
	return(y + fun(x));
};

# save the Fibonacci sequence of 1 to 15 in an array 
array arr(15);	
x = 1;
while( x <= 15 ){
	arr[x - 1] = fun(x);
	x = x + 1;
}

puts("Fibonacci sequence:");
# print the Fibonacci sequence of 1 to 15
i = 0;
while(i < 15){			
	print(arr[i]);
	i=i+1;
}

```

（起名困难x）这个小玩意我们就随便叫它tryC吧，当做是一个小的尝试。

本人水平有限，如有疏漏之处，还请多多指教。

### 部分语言规则：

- 注释在一行内，以‘#’开头；
- 语句以‘;’结尾
- 赋值语句类型：
  
    ```c
    x = 123.4;
    x = 'c';
    x = "hello world!";
    ```

- 循环语句：
  
    ```c
    while( bool ){
	    statements
    }
    ```

- 选择语句：
  
    ```c
    if( bool ){
	    statements
    }

    if( bool ){
	    statements
    }else{
        statements
    }
    ```

- 定义函数：函数参数在定义中不出现，在调用中获取；返回值为double
  
    ```c
    func function_name{
        ...
        return(expression);
    }

    ```

- 定义数组：
  
    ```c
    array array_name(array_length);        

    ```

- 输入输出：
  
    ```c
    puts(string);
    print(num);
    read(num);
    ```

## 写在前面

### 关于写这玩意的缘由（写的很乱可以不看系列）

之前大一学c语言的时候，老师要求实现一个四则运算的计算器，于是我想...要是能给计算器加上函数和变量的定义就好啦...那大概能算一个简单的解释器？我应该怎样去实现它呢？就去查了不少资料七拼八凑加上自己脑补搓了一个出来...虽然能跑起来但是代码混乱不堪一塌糊涂，不过也挺好玩的。

这里的部分是过了一年之后大二学编译原理的时候，把当时的代码用相对比较规范完善的方式重写了一遍，也因此希望把它整理成一个简单的教程，让c语言的初学者也可以愉快地搓一个解释器玩；或者让学过编译原理的同学，能够把理论和实践联系起来，（<del>不要像我一样被一大堆的理论迷惑住或吓跑</del>），对于如何构造一个解释器有个直观感性的认识，并且发现它并不像想象的那么困难。

### 需要了解的前置知识

- c语言的指针、函数指针、结构体等
- 递归的思想

### 心理准备

- 写一个600行的解释器虽然不算什么大工程，但相关的原理还是稍微有些复杂的，可能需要多花一些时间理解程序的运行过程；

- 代码可能难以调试，尤其在没有生成中间代码的情况下；

### 参考资料

- 《编译原理及其实践》

- [c4](https://github.com/rswier/c4)
    用四个函数和很少的代码就完成了功能相当完善的 C 语言编译器, 并且能够自举；我自己写作的时候也借鉴了c4的许多实现思想；

- [手把手教你构建 C 语言编译器](https://lotabout.me/2015/write-a-C-interpreter-0/)
    对c4的一个重写版，附有详细的中文教程

- [Let's Build a Compiler, by Jack Crenshaw ](https://compilers.iecc.com/crenshaw/)
    一个英文的初学者教程，讲解如何实现一个编译器
