📄 cifa.cpp
字号:
//实验一 词法分析
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include <conio.h>
#include <fstream.h>
#include <iostream.h>
#define NULL 0
FILE *fp;//源文件指针
FILE *out,*in;//输出二元式表文件指针,输出预处理文件指针
char ch;
char filename[50];//源文件路径及名称
char *keyword[4]={"IF","THEN","ELSE","GOTO"};//关键字
char *operatornum[4]={"+","-","*","/"};//运算符
char *comparison[6]={">","<",">=","<=","=","<>"};//关系符
char *interpunction[4]={",",":","(",")"};//界符
int x=-1,y=-1,z=-1;
//符号表
#define Klen 10//关键字
#define Ilen 30//标识符
#define Clen 40//常数
#define Plen 20//界符
#define Olen 20//运算符
#define Llen 10//标号
char K[Klen][10],P[Plen][2],I[Ilen][20],O[Olen][2];
int C[Clen],L[Llen];
//////////////////////////////////////////////////////////////////////////////////////////
bool search(char searchstr[],int wordtype)//查找单词种别函数
{
int i;
switch(wordtype)
{
case 1: for(i=0;i<=3;i++)//识别关键字
{
if(strcmp(keyword[i],searchstr)==0)
return true;
}
case 2: for(i=0;i<=3;i++)//识别运算符
{
if(strcmp(operatornum[i],searchstr)==0)
return true;
}
case 3: for(i=0;i<=5;i++)//识别关系符
{
if(strcmp(comparison[i],searchstr)==0)
return true;
}
case 4: for(i=0;i<=3;i++)//识别界符
{
if(strcmp(interpunction[i],searchstr)==0)
return true;
}
}
return false;
}
//////////////////////////////////////////////////////////////////////////////////////////
char letterprocess (char ch)//字母处理函数
{
int i=-1,j=-1,k,a=1;
char letter[10],temp[10];
while(isalnum(ch)!=0)//isalnum是C++分类函数检查参数c是否为字母 若参数ch为字母,则返回TRUE
{
letter[++i]=ch;
ch=fgetc(fp);
}
letter[i+1]='\0';
if(search(letter,1))//输出关键字二元式
{
printf("(K,%5s)\n",letter);
fprintf(out,"(K,%s)\n",letter);
if(strcmp(letter,"GOTO")==0)//输出标号二元式
{
ch=fgetc(fp);
while(isdigit(ch)!=0)
{
temp[++j]=ch;
ch=fgetc(fp);
}
temp[j+1]='\0';
printf("(L,%5s)\n",temp);
fprintf(out,"(L,%s)\n",temp);
L[++y]=atoi(temp);//填写标号符号表,atoi()将字符串转换成整型数
}
}
else//输出标识符二元式
{
printf("(I,%5s)\n",letter);
fprintf(out,"(I,%s)\n",letter);//fprintf是用于文件操作的
for(k=0;k<10;k++)
{
if(strcmp(letter,I[k])==0)
a=0;
}
if(a==1)
strcpy(I[++x],letter);//填写标识符符号表
}
return ch;
}
//////////////////////////////////////////////////////////////////////////////////////////
char numberprocess(char ch)//数字处理函数
{
int i=-1,n,temp,a=1;
char num[20];
while(isdigit(ch)!=0)//若ch是数字('0'-'9')返回非0值,否则返回0
{
num[++i]=ch;
ch=fgetc(fp);
}
if(isalpha(ch)!=0)//若ch是字母('A'-'Z','a'-'z')返回非0值,否则返回0
{
while(isalpha(ch)!=0)
{
num[++i]=ch;
ch=fgetc(fp);
}
num[i+1]='\0';
printf("非法标识符: %s\n",num);
fprintf(out,"非法标识符: %s\n",num);
}
if(ch==':')//输出标号二元式
{
num[i+1]='\0';
printf("(L,%5s)\n",num);
fprintf(out,"(L,%s)\n",num);
L[++y]=atoi(num);//填写标号符号表
}
else//输出常数二元式
{
num[i+1]='\0';
printf("(C,%5s)\n",num);
fprintf(out,"(C,%s)\n",num);
temp=atoi(num);
for(n=0;n<10;n++)
{
if(temp==C[n])
a=0;
}
if(a==1)
C[++z]=temp;//填写常数符号表
}
return ch;
}
//////////////////////////////////////////////////////////////////////////////////////////
char otherprocess(char ch)//其它字符处理函数
{
int i=-1;
char other[10];
if(ch=='(')
{
other[++i]=ch;
ch=fgetc(fp);
}
while(isalnum(ch)==0&&ch!=' '&&ch!='('&&ch!=')')
{
other[++i]=ch;
ch=fgetc(fp);
}
if(ch==')')
{
other[++i]=ch;
ch=fgetc(fp);
}
other[i+1]='\0';
if(search(other,4))//输出界符二元式
{
printf("(P,%5s)\n",other);
fprintf(out,"(P,%s)\n",other);
}
else if(search(other,2)||search(other,3))//输出运算符二元式
{
printf("(O,%5s)\n",other);
fprintf(out,"(O,%s)\n",other);
}
else
{
printf("非法字符: %s\n",other);
fprintf(out,"非法字符: %s\n",other);
}
return ch;
}
//////////////////////////////////////////////////////////////////////////////////////////
char process(char ch)//空格处理函数
{
while(ch==' ')
ch=fgetc(fp);
return ch;
}
//////////////////////////////////////////////////////////////////////////////////////////
void pro_process(char *buf)//预处理函数
{
ifstream cinf(filename,ios::in);
int i=0;//计数器
char old_ch='\0',cur_ch;//前一个字符,当前字符
bool comment=false;//false表示当前字符未处于注释中
while(cinf.read(&cur_ch,sizeof(char)))//从文件读一个字符
{
switch(comment)
{
case false:
if(old_ch=='/'&&cur_ch=='*')//进入注释
{
i--;//去除已存入扫描缓冲区的字符'/'
comment=true;
}
else
{
if(old_ch=='\\'&&cur_ch=='\n')//发现续行
i--;//去除已存入扫描缓冲区的字符'\'
else
{
if(cur_ch=='\t'||cur_ch=='\r'||cur_ch=='\n')//空格取代Tab换行
cur_ch=' ';
if(old_ch==' '&&cur_ch==' ')//一个空格取代多个空格
i--;//去除已存入扫描缓冲区的字符' '
buf[i++]=cur_ch;
}
}
break;
case true:
if(old_ch=='*'&&cur_ch=='/')//离开注释
comment=false;
}
old_ch=cur_ch;//保留前一个字符
}
buf[i++]='#';//在源程序尾部添加字符'#'
}
//////////////////////////////////////////////////////////////////////////////////////////
void main ()//主函数
{
char str;
char buf[4048]={'\0'};
int i=0;
out=fopen("二元式表.txt","w");
in=fopen("预处理.txt","w");
printf("请输入源文件路径及名称:");
scanf("%s",filename);
printf("**********************************词法分析程序**********************************\n");
printf("K:关键字 I:标识符 C:常数 O:运算符 P:界符 L:标号\n");
if((fp=fopen(filename,"rt"))==NULL)
printf("源文件无法打开!\n");
else//打开源文件
{
pro_process(buf);//生成预处理文件
while(buf[i]!='#')
{
fputc(buf[i],in);
i++;
}
fputc('#',in);
fclose(in);
fp=fopen("预处理.txt","r");
str=fgetc(fp);
while(str!='#')
{
str=process(str);//空格处理
if(str=='#')
break;
if(isalpha(str)!=0)
str=letterprocess(str);//字母处理
else
{
if(isdigit(str)!=0)
str=numberprocess(str);//数字处理
else
str=otherprocess(str);//其它字符处理
}
}
printf("输出结果保存在二元式表.txt文件中,请打开查看。\n");
printf("词法分析结束!\n");
fclose(out);
fclose(fp);
}
system("pause");
exit(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -