⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cifa.cpp

📁 编译原理中的词法分析工具,还需自己创建一个文本.写入代码.
💻 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 + -