【问题描述】 设计一个词法扫描器。词法扫描器的功能是输入源程序,输出单词符号。写出关键字集合和程序流程图。例如源程序为C语言。输入如下一段:
main() {
int a,b;
a = 10;
b = a + 20;
}
输出如图:
(2,”main”)
(5,”(“)
(5,”)“)
(5,”{“)
(1,”int”)
(2,”a”)
(5,”,”)
(2,”b”)
(5,”;”)
(2,”a”)
(4,”=”)
(3,”10”)
(5,”;”)
(2,”b”)
(4,”=”)
(2,”a”)
(4,”+”)
(3,”20”)
(5,”;”)
(5,” ) “ )
源程序:
#include<stdio.h>
#include<stdlib.h>
#include<iostream.h>
#include<conio.h>
#include<string.h>
void main()
{
char key[][15]={ "auto","break","case","char","const","continue","default","do",
"double","else","enum","extern","float","for","goto","if",
"int","long","register","return","short","signed","sizeof","static",
"struct","switch","typedef","union","unsigned","void","volatile","while"
};
char opr[7] = {'+','-','*','/','=','>','<'};
char c[10] = {'(',')','{','}','[',']',',',';','.','#'};
int i = 0, j, k;
int count = 0, sign, end;
char w[1000], ch;
char ls[50]; // 临时存放读取字符的数组
FILE *fp;
fp=fopen("liu.txt","r");
if(fp==NULL)
{
printf("open file error!/n");
getch();
exit(0);
}
while((ch=fgetc(fp)) != EOF)
{
w[count]=ch;
count++;
putchar(ch);
}
cout<<endl;
loop:
while(1)
{
if(w[i] == EOF)
{
system("pause");
exit(0);
}
while(w[i] != 32 && w[i] != 10 ) // 读取的字符不为空格和回车
{
for(j=0; j<7; j++)
if(w[i] == opr[j]) //判断是否为运算符
{
cout<<"("<<4<<","<<"/""<<w[i]<<"/""<<")"<<endl;
i++;
goto loop;
}
for(j=0; j<10; j++)
if(w[i] == c[j]) //判断是否为标点
{
cout<<"("<<5<<","<<"/""<<w[i]<<"/""<<")"<<endl;
i++;
goto loop;
}
k=0;
end=0;
while(w[i]>47 && w[i]<58) //判断是否为数字
{
ls[k] = w[i];
i++;
k++;
if(w[i]<=47 || w[i]>=58)
{
end = 1; //下一字符是否为数字的标识
break;
}
}
if(end==1)
{
cout<<"("<<3<<","<<"/"";
for(j=0; j<k; j++)
cout<<ls[j];
cout<<"/""<<")"<<endl;
}
k=0;
end=0;
while((w[i]>=65 && w[i]<=90) || (w[i]>=97 && w[i]<=122)) //判断是否为字母
{
ls[k] = w[i];
i++;
k++;
if((w[i]<65 || w[i]>90) && (w[i]<97 || w[i]>122))
{
end = 1;
ls[k]='/0' ; //下一字符是否为字母的标识
break;
}
}
if(end==1)
{
sign = 1;
for(j=0; j<32; j++)
if(strcmp(key[j],ls) == 0)
{
cout<<"("<<1<<","<<"/"";
for(j=0; j<k; j++)
cout<<ls[j];
cout<<"/""<<")"<<endl;
sign = 0;
break; //是否为关键字的标识
}
if(sign == 1)
{
cout<<"("<<2<<","<<"/"";
for(j=0; j<k; j++)
cout<<ls[j];
cout<<"/""<<")"<<endl;
}
}
}
i++;
}
}
在此程序中最有意义的就是下面这一段对数字的处理(字符类似),这是关键。
k=0;
end=0;
while(w[i]>47 && w[i]<58) //判断是否为数字
{
ls[k] = w[i];
i++;
k++;
if(w[i]<=47 || w[i]>=58)
{
end = 1; //下一字符是否为数字的标识
break;
}
}
if(end==1)
{
cout<<"("<<3<<","<<"/"";
for(j=0; j<k; j++)
cout<<ls[j];
cout<<"/""<<")"<<endl;
}
在程序中我用
if(w[i]<=47 || w[i]>=58)
{
end = 1; //下一字符是否为数字的标识
break;
}
来判断下一字符是否为数字,并对标识置数,就可以处理数字串了。后面跟着对标识的处理:
if(end==1)
{
cout<<"("<<3<<","<<"/"";
for(j=0; j<k; j++)
cout<<ls[j];
cout<<"/""<<")"<<endl;
}
即输出数字串。