实验目的
通过实现PL/0语言(一种示例小语言)的词法分析器,理解词法分析过程,掌握程序各部分之间的接口安排。
分析与设计
程序的输入直接使用经过预处理之后的程序,读取文件到数组buffer。(预处理程序在上一篇文章)
遍历buffer的每一行,对每一行进行提取子串,判断子串是否是关键字、标识符、常数、算符或者界符
对于关键字和标识符:将所有关键字存放于一个数组keyWords当中,当识别出一个由字母组成的字符串时,遍历keyWords数组,判断是否是关键字,如果不是就判定字符串为标识符。(关键字的种别设为A0-A10共十一个,标识符设为ID)
对于常数:将识别出来的由常数构成的字符串判定为常数(种别设为CONST)
对于算符和界符:没读取一个字符,先判断是否是算符或者界符(种别设为B0-B13,共十四个)
部分状态转换图
识别单词的关键代码
//对每一行进行词法分析
for(int i=0;i<n;i++)
{
int flag=0; //标识开始位置
for(int j=0;j<buffer[i].length();j++)
{
//判断单个字符是否为算符或者界符
if(buffer[i][j]=='+') cout<<"(B0,-)"<<endl;
else if(buffer[i][j]=='-') cout<<"(B1,-)"<<endl;
else if(buffer[i][j]=='*') cout<<"(B2,-)"<<endl;
else if(buffer[i][j]=='/') cout<<"(B3,-)"<<endl;
else if(buffer[i][j]=='=') cout<<"(B4,-)"<<endl;
else if(buffer[i][j]=='#') cout<<"(B5,-)"<<endl;
else if(buffer[i][j]=='<') cout<<"(B6,-)"<<endl;
else if(buffer[i][j]=='>') cout<<"(B7,-)"<<endl;
else if(buffer[i][j]==':')
{
cout<<"(B8,-)"<<endl;
j++; //跳过下一个字符
}
else if(buffer[i][j]=='(') cout<<"(B9,-)"<<endl;
else if(buffer[i][j]==')') cout<<"(B10,-)"<<endl;
else if(buffer[i][j]==',') cout<<"(B11,-)"<<endl;
else if(buffer[i][j]=='.') cout<<"(B12,-)"<<endl;
else if(buffer[i][j]==';') cout<<"(B13,-)"<<endl;
if(IsLetter(buffer[i][j]) && flag==0)
{
flag=1;
string str="";//存放识别出的子串
str+=buffer[i][j];
j++;
while(IsLetter(buffer[i][j]))
{
str+=buffer[i][j];
j++;
}
//判断识别出来的子串是否是关键字
if(Reserve(str)==-1) cout<<"(ID,"<<str<<")"<<endl;
else cout<<"(A"<<Reserve(str)<<",-)"<<endl;
flag=0; //将flag置为0,识别下一个子串
j--; //指针后退一个
}
if(IsDigit(buffer[i][j]) && flag==0)
{
flag=1;
string str="";
str+=buffer[i][j];
j++;
while(IsDigit(buffer[i][j]))
{
str+=buffer[i][j];
j++;
}
cout<<"(CONST,"<<str<<")"<<endl;
flag=0;
j--;
}
}
}//zww
词法分析器的运行结果