写一个编译器,首先要知道的就是什么是编译器,我觉得能看到我这篇文章的基本上都知道了。我认为,编译器就是
让计算机读懂代码的程序,在这个程序里,定义了各种规则(编程语言的语法),只要人们按照这个规则和计算机说
话(编程)就能让计算机懂得我们想干嘛。
编译器包括几个模块,也可以说是过程,即词法分析,语法分析,中间代码生成等等。好吧我承认我知道的不清楚,
不过万物起源词法分析(我编的)一定没问题。这里我们就先来第一步,词法分析。词法分析是编译器中比较简单的模块了,
也是最基础的模块。它的作用就是将输入的程序文本文件切割成一个一个的单词和符号,以便接下来的模块使用。
好了,高深的道理就不讲了,我现在的目标就是要写一个函数,这个函数接收一个文件地址,将该文件中的代码分割
成单词和符号,每个单词和符号被称为一个token,返回一个链表,存储所有的token。函数定义就写为:
TokenList_tag LexExcute(string sourcefilepath);//TokenList_tag是链表头指针,指向头节点,sourcefilepath为源文件地址
我将词法分析程序写在lex.cpp文件中,二话不说先上几行代码,顿时感觉自信心爆棚。代码4-7行可以用一行
using namespace std;代替
1 #include<iostream> 2 #include<string > 3 #include<fstream> 4 using std::cout; 5 using std::string; 6 using std::endl; 7 using std::ifstream;
讲道理现在应该先定义一下token了,不过我还不知道token怎么定义,就先不这么搞了,先解决读取文件的问题,
定义一个string变量(filepath)存储文件地址,定义文件流(in)用于读取文件内容,然后从流中每次读取一行,存入
字符串变量line_str,这样思路就很清晰了,我们从line_str中逐个取出字符,然后分析。
1 ifstream in;//文件流 2 string filepath;//文件路径 3 string line_str;//存储每次读出的行 4 int line_len;//读出行的长度 5 int line_pos;//逐字符处理时,用于记录位置 6 int line_num;//记录当前源文件第几行,可能以后报语法错误的时候有用 7 char ch;//逐字符处理时,记录当前字符 8 string token_str;//记录token字符串
为防止出错,我们定义初始化函数init(),将所有变量的初始化放在该函数中,如下:
1 void init() 2 { 3 cout<<"func enter: init"<<endl; 4 line_pos=0; 5 line_num=0; 6 token_str=""; 7 ch='