简单的词法分析器## 标题
刚学了编译原理,学着做了下词法分析器。
用c++写的,代码比较简单,通俗易懂,喜欢的同学可以看看,代码没有见过二次优化
不足的地方比较多。
使用古老的 VC6.0编译
哈哈哈
/南山荒野客
//20-05-2019
//词法分析器——编译原理
//C++语言
#include<stdio.h>
#include<string.h>
#include<iostream.h>
char prog[80],token[6];
char ch;
int syn,p,m=0,n,row,sum=0;
int biaoji=0;
char *rwtab[18]={"begin","if","then","while","do","end","else","for","int","char","void","break","float","double","swtich","default","return","string"};
//18个保留字
void scaner()
{
/*
分为三部分,分别是标示符、数字、其他符号,对应下面的 if else if 和 else
*/
for(n=0;n<7;n++) token[n]=NULL;//每次读入8个以内的字符
ch=prog[p++];
while(ch==' ')
{
ch=prog[p];
p++;
}
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch=='_')) //可能是标示符或者变量名 (标识符只能以字母或者下划线开头)
{
m=0;
while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch=='_'))
{
token[m++]=ch;
ch=prog[p++];
}
token[m++]='\0';
p--;
syn=10;
for(n=0;n<18;n++) //将识别出来的字符和已定义的保留字作比较,
if(strcmp(token,rwtab[n])==0)
{
syn=n+40;//种别码在40~58
break;
}
}
else if((ch>='0'&&ch<='9')) //数字
{
{m=0;
sum=0;
biaoji=0;
while((ch>='0'&&ch<='9'))//数字后面可以跟数字,字符-‘0’转换为数值
{ sum=sum*10+ch-'0';
token[m++]=ch;
ch=prog[p++];
}
while((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch=='_'))//数字后面跟其他字符则表示字符非法,用biaoji=1标记
{
token[m++]=ch;
ch=prog[p++];
biaoji=1;
}
}
p--;
if(biaoji<1)
syn=11;//合法数字种别码 11
if(biaoji==1)//非法字符报错
syn=-3;
if(sum>32767)//数字溢出报错
syn=-4;
}
else switch(ch) //其他字符
{
case'<':m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='>')
{
syn=21;
token[m++]=ch;
}
else if(ch=='=')
{
syn=22;
token[m++]=ch;
}
else
{
syn=23;
p--;
}
break;
case'>':m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=24;
token[m++]=ch;
}
else
{
syn=20;
p--;
}
break;
case':':m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=18;
token[m++]=ch;
}
else
{
syn=17;
p--;
}
break;
case'*':syn=13;token[0]=ch;break;
case'/':syn=14;token[0]=ch;break;
case'+':syn=15;token[0]=ch;break;
case'-':syn=16;token[0]=ch;break;
case'=':syn=25;token[0]=ch;break;
case';':syn=26;token[0]=ch;break;
case'(':syn=27;token[0]=ch;break;
case')':syn=28;token[0]=ch;break;
case'[':syn=29;token[0]=ch;break;
case']':syn=30;token[0]=ch;break;
case'{':syn=31;token[0]=ch;break;
case'}':syn=32;token[0]=ch;break;
case'#':syn=0;token[0]=ch;break;
case'\n':syn=-2;break;
default: syn=-1;break;//其他错误(如未能识别的字符)
}
}
int main()
{
p=0;
row=1;
cout<<"种别码 40 ~ 58 为保留字"<<endl;
cout<<"种别码 10 为标识符 11为数字 13 ~ 40 之间为其他符号"<<endl;
cout<<"请输入(输入代码以‘#’作为终结符):"<<endl;
do
{
cin.get(ch);
prog[p++]=ch;
}
while(ch!='#');//#作为输入的字符的终结符,读到#停止读入
p=0;
do
{
scaner();
switch(syn)
{
case 11: cout<<"("<<syn<<","<<sum<<")"<<endl; break;
case -1: cout<<"Error in row "<<row<<"!"<<"未能识别的字符"<<endl; break;
case -2: row=row++;break;
case -3: cout<<"("<<"非法字符"<<","<<token<<")"<<endl;break;
case -4:cout<<"("<<"数字过载 "<<sum<<")"<<endl; break;
default: cout<<"("<<syn<<",";
for(int i=0;i<6;i++)
if(token[i]!=NULL)
cout<<token[i];
cout<<")"<<endl;break;
}
}
while (syn!=0);
return 0;
}