词法分析有好多方案,这里我只介绍使用状态机的方案。
对于状态机是什么,以及是什么原理,这篇博客不做详解,读者可以查阅相关资料来补充相关知识。
这里主要讲怎么利用相关原理设计词法分析的状态转移表和实现算法。
首先,创建一个状态转移表
举个例子,假如当前输入的字符是'1',那么先设置状态是1,也就是上面表中的整数,然后在整数状态(或者是状态1)下,又遇到了下一个字符'.',这时,表中 [整数,小数点]=2,说明下一步应当将状态转移到2,再读取下一个字符,比如说是'3',这是 [浮点数,数]=2,也就是下一个状态还是2,如果再下一个字符是'a',此时 [浮点数,字母]=0,那么说明一个词语读取完毕,“1.3”这个字符串就被我们分辨出来,并且其状态是2---浮点数,以此类推,就实现了词法分析,上表仅仅是包含了一些字符,可以做到简单的有限范围的词法分析,如果还要更多的词法,那么还要继续扩充上表。
每个字符都有一个映射表,如果遇到的是数字,那么 应该将数字翻译成下标1,这样才可以在状态转移表中当作下标,如果遇到的是字母,将字母映射成2,对应着状态转移表列下标2。。。(以此类推)状态转移表的行坐标是当前的状态,例如前面的[整数,小数点]=[1,3]=2。
我还是把代码贴一下
#include<iostream>
#include<fstream>
#include<vector>
using namespace std;
int stateTable[6][7];//状态转换表
int charTypeTable[128];//字符映射表
void wordAnaly(char * code)
{
if (code == nullptr)
return;
char strToken[64];
char *ptStrToken = strToken;
int nowState = 0, lastState = 0;
char * ptCode = code;
while (true)
{
//获取新的状态,状态0认为是结尾
nowState = stateTable[nowState][charTypeTable[*ptCode]];
//一旦状态是0,说明一个词语生成
if (nowState == 0)
{
nowState = 0;
*ptStrToken = 0;
cout <<"token:<"<< strToken <<","<<lastState<<">"<< endl;
ptStrToken = strToken;
continue;
}
//记录已经接受的字符
*ptStrToken = *ptCode;
++ptStrToken;
if ((*ptCode) == '\0')
break;
++ptCode;
lastState = nowState;
}
}
int main()
{
ifstream infile;
//读取状态转移表
infile.open("stateTable.txt");
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 7; j++)
{
infile >> stateTable[i][j];
}
}
infile.close();
//读取字符映射表
infile.open("charTypeTable.txt");
for (int i = 0; i < 128; i++)
{
infile >> charTypeTable[i];
}
infile.close();
char code[256];
memset(code,0,sizeof(char)*256);
//读取代码文件
FILE * ptFile = fopen("code.txt", "r");
fseek(ptFile, 0, SEEK_END);
int fileLength = ftell(ptFile);
fseek(ptFile, 0, SEEK_SET);
fread(code, 1, fileLength, ptFile);
//词法分析
wordAnaly(code);
return 0;
}