📄 scaner.cpp
字号:
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int label;//Token行数计数
// 初始化函数
void init()
{
label=0;
char *key[]={" ","and", "array", "begin", "bool", "call", "case", "char", "constant", "do", "else",
"end", "false","for","if", "input", "integer", "not", "of","or", "output", "procedure", "program",
"read", "real", "repeat", "set", "then", "to", "true","until", "var", "while", "write",
"symbol", "intconst", "realconst", "charconst", "'", "(", ")", "*", "*/", "+", ",",
"-", ".", "..", "/", "/*", ":", ":=", ";", "<", "<=", "<>", "=", ">", ">=",
"[", "]", }; //Simple语言单词编码,60 个
FILE *fp;
fp=fopen("word.txt","w");
for(int i=1;i<=60;i++)
fprintf(fp,"%d\t\t\t%d\t\t\t%s\n",i,i,key[i]);
fclose(fp); //初始化单词表字表
fp=fopen("symble.txt","w");
fclose(fp); //建立符号表
fp=fopen("token.txt","w");
fclose(fp); //建立输出文件token串
//printf("test.txt为simple语言的测试文件,请在下面输入\n");
}
//根据不同命令查表或造表函数
int find(char *buf,int type,int command)
{
int number=0;
FILE *fp;
int snum;
int stype;
char sname[30];
int i=0;
switch(type)
{
case 1: fp=fopen("word.txt","r");
break;
case 2: fp=fopen("symble.txt","r");
break;
case 3: fp=fopen("symble.txt","r");
break;
}
while(!feof(fp))
{
fscanf(fp,"%d%d%s",&snum,&stype,sname); /////////////
if(!feof(fp))
number++;
if(strcmp(sname,buf)==0)
{
fclose(fp);
return(number); ///若找到,返回在相应表中的序号
}
}
fclose(fp);
if(command==1) //1不造入不表,2则造入表
{
return(0); //找不到,当只需查表,返回0,否则还需造表
}
switch(type)
{
case 1: fp=fopen("word.txt","a");break;
case 2: fp=fopen("symble.txt","a");
fprintf(fp,"%d\t\t\t%d\t\t\t%s\n",number+1,34,buf);
break;//标识符
case 3: fp=fopen("symble.txt","a");
fprintf(fp,"%d\t\t\t%d\t\t\t%s\n",number+1,35,buf);
break;
}
fclose(fp);
return(number+1); //造表时,将字符串添加到表尾并返回序号值
}
//数字串处理函数
void cs_manage(char *buffer)
{
FILE *fp;
int result;
result=find(buffer,3,2); //先查常数表,若找不到则造入常数表并返回序号值
fp=fopen("token.txt","a");
fprintf(fp,"%d\t%s\t%d\t%d\n",++label,buffer,35,result);
fclose(fp); //写入输出文件
}
//字符串处理函数
void ch_manage(char *buffer)
{
FILE *fp;
int result;
result=find(buffer,1,1); //先查单词字表
fp=fopen("token.txt","a");
if(result!=0)
fprintf(fp,"%d\t%s\t%d\t%d\n",++label,buffer,result,-1); //若找到,写入输出文件
else
{
result=find(buffer,2,2); //若找不到,则非关键字,查标识符表,还找不到则造入标识符表
fprintf(fp,"%d\t%s\t%d\t%d\n",++label,buffer,34,result);
} //写入输出文件
fclose(fp);
}
//出错处理函数
void er_manage(char error,int lineno)
{
printf("\nerror: %c ,line %d",error,lineno); //报告出错符号和所在行数
}
//扫描程序
void scanner()
{
FILE *fpin,*fpout;
// char filename[20];
char ch;
char array[30];
char *word;
int i=0,line=1;
int count,result,errorno=0;
// printf("\nthe file name:");
// scanf("%s","filename);
if((fpin=fopen("test.txt","r"))==NULL)
{
printf("cannot open file");
return;
}
ch=fgetc(fpin);
while(ch!=EOF)
{ //按字符依次扫描源程序,直至结束
i=0;
if(((ch>='A')&&(ch<='Z'))||((ch>='a')&&(ch<='z'))||(ch==-1))
{ //以字母开头
while(((ch>='A')&&(ch<='Z'))||((ch>='a')&&(ch<='z'))||(ch==-1)||((ch>='0')&&(ch<='9')))
{
array[i++]=ch;
ch=fgetc(fpin);
}
word=(char *)malloc((i+1)*sizeof(char));
memcpy(word,array,i);
word[i]='\0';
ch_manage(word);
if(ch!=EOF)
fseek(fpin,-1L,SEEK_CUR);
}
else if(ch>='0'&&ch<='9') //以数字开头
{
while(ch>='0'&&ch<='9')
{
array[i++]=ch;
ch=fgetc(fpin);
}
word=(char *)malloc((i+1)*sizeof(char));
memcpy(word,array,i);
word[i]='\0';
cs_manage(word);
if(ch!=EOF)
fseek(fpin,-1L,SEEK_CUR);
}
else if((ch==' ')||(ch=='\t'))
; //消除空格符和水平制表符
else if(ch=='\n')
line++; //消除回车并记录行数
else if(ch=='/')
{ //消除注释
ch=fgetc(fpin);
if(ch!='*')
{ //若为除号,写入输出文件
fpout=fopen("token.txt","a");
fprintf(fpout,"%d\t%s\t%d\t%d\n",++label,word,48,-1);
fclose(fpout);
fseek(fpin,-1L,SEEK_CUR);
}
else if(ch=='*')
{ //若为注释的开始,消除包含在里面的所有字符
count=0;
ch=fgetc(fpin);
while(count!=2)
{ //当扫描到‘*’且紧接着下一个字符为‘/’才是注释的结束
count=0;
while(ch!='*')
ch=fgetc(fpin);
count++;
ch=fgetc(fpin);
if(ch=='/')
count++;
else
ch=fgetc(fpin);
}
}
}
else
{ //首字符为其它字符,即运算限界符或非法字符
array[0]=ch;
ch=fgetc(fpin); //再读入下一个字符,判断是否为双字符运算、限界符
if(ch!=EOF)
{ //若该字符非文件结束符/
array[1]=ch;
word=(char *)malloc(3*sizeof(char));
memcpy(word,array,2);
word[2]='\0';
result=find(word,1,1); //先检索是否为双字符运算、限界符
if(result==0)
{ //若不是
word=(char *)malloc(2*sizeof(char));
memcpy(word,array,1);
word[1]='\0';
result=find(word,1,1); //检索是否为单字符运算、限界符
if(result==0)
{ //若还不是,则为非法字符
er_manage(array[0],line);
errorno++;
fseek(fpin,-1L,SEEK_CUR);
}
else
{ //若为单字符运算、限界符,写入输出文件并将扫描文件指针回退一个字符
fpout=fopen("token.txt","a");
fprintf(fpout,"%d\t%s\t%d\t%d\n",++label,word,result,-1);
fclose(fpout);
fseek(fpin,-1L,SEEK_CUR);
}
}
else
{ //若为双字符运算、限界符,写输出文件
fpout=fopen("token.txt","a");
fprintf(fpout,"%d\t%s\t%d\t%d\n",++label,word,result,-1);
fclose(fpout);
}
}
else
{ //若读入的下一个字符为文件结束符
word=(char *)malloc(2*sizeof(char));
memcpy(word,array,1);
word[1]='\0';
result=find(word,1,1); //只考虑是否为单字符运算、限界符
if(result==0) //若不是,转出错处理
er_manage(array[0],line);
else
{ //若是,写输出文件
fpout=fopen("token.txt","a");
fprintf(fpout,"%d\t%s\t%d\t%s\n",++label,word,result,-1);
fclose(fpout);
}
}
}
ch=fgetc(fpin);
}
fclose(fpin);
printf("\nThere are %d error(s).\n",errorno); //报告错误字符个数
printf("词法分析结束!\n");
}
//主函数
int main()
{
init(); //初始化
scanner(); //扫描源程序
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -