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

📄 grammer.cpp

📁 此程序为LR递归下降程序
💻 CPP
字号:
#include <string.h>
#include "global.h"
#include "grammer.h"

void procProcess(FILE *fpread,int level)//递归的过程
{
    struct record temp;
	skipLine(fpread);//跳过换行符
	fread(&temp,sizeof(struct record),1,fpread);//读一条记录,记录是二元式形式
	if(((temp.kind==1)&&(level==0))||((temp.kind==3)&&(level>0)))
	{
		if(temp.kind==1)//这个单词是program
		{
			//printf("\nprogram.");
			processProg(fpread,level);//处理program这一行程序
		}
		else if(temp.kind==3)//这个单词是procedure
		{
			//printf("\nprocedure.");
			processProc(fpread,level);//处理procedure这一行程序	
		}
		processShift(fpread,level);//程序转移处理
	}
	else
	{
		if(level==0)//如果处理的是主程序,主程序是第零层
		{
			printf("\nERROR: line-> %d 缺少program.",lineLocation);	//输出错误信息
			skip(fpread);//出错后就跳过若干个单词在处理
			processShift(fpread,level);//程序转移处理
		}
	}
}
void processShift(FILE *fpread,int level)//按照程序的不同形式采取不同的处理方式,这是由于一些程序的模块可以有,也可以没有
{
    struct record temp;
	skipLine(fpread);
	fread(&temp,sizeof(struct record),1,fpread);//读一个二元式,(词法分析的结果)
	switch(temp.kind)//查看读出的单词的编码,按照编码决定程序的走向
	{
		case 2://处理var定义变量,这是处理变量定义的过程
			do
			{
				//printf("\nvar.");
				processVariable(fpread,level);//处理变量,将变量填入符号表
				skipLine(fpread);//跳过换行符,增加了程序的灵活性,一行代码可以写在若干行
				fread(&temp,sizeof(struct record),1,fpread);//读一条记录
			}while(temp.kind==2);//如果有多条定义变量的语句
			switch(temp.kind)
			{
				case 3://处理过程procedure定义
					do
					{
						//printf("\nprocedure.");
						fseek(fpread,recordLength,SEEK_CUR);/*回退一条记录*/
						if(varLocation!=-1){
							backPatch();/*当前过程有参数但没有填写过程表的就填写*/
						}
						procProcess(fpread,level+1);//递归调用,处理过程
						skipLine(fpread);
						fread(&temp,sizeof(struct record),1,fpread);
					}while(temp.kind==3);//如果有多个过程定义
					if(temp.kind==4)//处理begin-end这段代码过程
					{
						//printf("\nbegin.");
						if(varLocation!=-1){
							backPatch();/*当前过程有参数但没有填写过程表的就填写*/
						}
						processPL(fpread);//处理代码过程,在lR分析阶段这一过程是主要的过程
					}
					else
					{
						printf("\nERROR: line-> %d缺少关键字begin.",lineLocation);
						skip(fpread);//错误处理
						processShift(fpread,level);//程序再次转移,看后续代码的形式
					}
					break;
				case 4://处理begin的过程
					//printf("\nbegin.");
					if(varLocation!=-1){
						backPatch();/*当前过程有参数但没有填写过程表的就填写*/
					}
					processPL(fpread);
					break;
				case 17://定义的是变量(17是标识符的编码)
					printf("\nERROR: line-> %d缺少关键字var或procedure.",lineLocation);
					skip(fpread);
					processShift(fpread,level);
					break;
				default://出错了,这是出错的处理
					printf("\nERROR: line-> %d",lineLocation);
					skip(fpread);
					processShift(fpread,level);//转移处理
					break;
			}
			break;
		case 3://这是在一个过程中没有变量定义的时候的处理的情况,有些子程序可以没有变量定义
			do
			{
				//printf("\nprocedure.");
				fseek(fpread,recordLength,SEEK_CUR);/*回退一条记录*/
				if(varLocation!=-1){
					backPatch();/*当前过程有参数但没有填写过程表的就填写*/
				}
				procProcess(fpread,level+1);
				skipLine(fpread);
				fread(&temp,sizeof(struct record),1,fpread);
			}
			while(temp.kind==3);
			if(temp.kind==4)
			{
				//printf("\nbegin.");
				if(varLocation!=-1){
					backPatch();/*当前过程有参数但没有填写过程表的就填写*/
				}
				processPL(fpread);
			}
			else
			{
					printf("\nERROR: line-> %d缺少关键字begin.",lineLocation);
					skip(fpread);
					processShift(fpread,level);
			}
			break;
		case 4://这是当子程序既没有变量定义,又没有子过程定义的时候的处理方法
			//printf("\nbegin.");
			if(varLocation!=-1){
				backPatch();/*当前过程有参数但没有填写过程表的就填写*/
			}
			processPL(fpread);
			break;
		case 17:
			printf("\nERROR: line-> %d缺少关键字var或procedure.",lineLocation);
			skip(fpread);
			processShift(fpread,level);
			break;
		default:
			printf("\nERROR: line-> %d",lineLocation);
			skip(fpread);
			processShift(fpread,level);
			break;
	}
	
}
void processPL(FILE *fpread)//这个过程不处理具体的代码,代码的分析有LR语法分析阶段完成
{
    struct record temp;
	while(!feof(fpread)){
		fread(&temp,sizeof(struct record),1,fpread);
		if(temp.kind==35){
			lineLocation++;
		}else if(temp.kind==5){
			//printf("\nend.");
			return;
		}
	}
	if(temp.kind!=5)
	{
		printf("\nERROR:程序缺少END.");
	}
	if(temp.kind!=34)
	{
		printf("\nERROR:整个程序缺少终结符\".\"");
	}
}
void processVariable(FILE *fpread,int level)//处理变量的过程,包括判断变量是否重定义和将变量填入符号表
{
    struct record temp;
	skipLine(fpread);
	fread(&temp,sizeof(struct record),1,fpread);
	while(temp.kind==17)//判断读入的是否变量,变量的编码是17
	{
		//printf("\n%s",temp.strName);
		totalCount++;
		enterVarTable(temp.strName,level,totalCount);
		skipLine(fpread);
		fread(&temp,sizeof(struct record),1,fpread);
		if(temp.kind==33)
		{
			//printf("\n;");
			return;
		}
		else if(temp.kind==32)
		{
			//printf("\n,");
			skipLine(fpread);
			fread(&temp,sizeof(struct record),1,fpread);	
		}
		else if((temp.kind!=32)&&(temp.kind!=33))
		{
			skip(fpread);
			printf("\nERROR: line-> %d缺少结束符",lineLocation);
		}
	}	
}
void processProc(FILE *fpread,int level)//处理过程的定义
{
    struct record temp;
	skipLine(fpread);
	fread(&temp,sizeof(struct record),1,fpread);
	if(temp.kind==17)
	{
		//printf("\n%s.",temp.strName);
		enterProcTable(temp.strName,level,level-1);
		skipLine(fpread);
		fread(&temp,sizeof(struct record),1,fpread);
		if(temp.kind==30)
		{
			//printf("\n(.");
			processID(fpread,level);
			skipLine(fpread);
			fread(&temp,sizeof(struct record),1,fpread);
			if(temp.kind==31)
			{	
				//printf("\n).");
				skipLine(fpread);
				fread(&temp,sizeof(struct record),1,fpread);	
				if(temp.kind!=33)
				{
					skip(fpread);
					printf("\nERROR: line->%d缺少结束符",lineLocation);
				}
			}
			else
			{
				skip(fpread);
				printf("\nERROR: line->%d缺少右括号",lineLocation);
			}
		}
		else if(temp.kind!=33)
		{
			skip(fpread);	
			printf("\nERROR: line->%d缺少结束符分号",lineLocation);
		}
	}
	else
	{
		printf("\nERROR: line->%d主程序没有定义名字",lineLocation);
		skip(fpread);
		return;	
	}	
}
void processID(FILE *fpread,int level)//处理过程的参数定义,并将过程的部分信息填入过程表
{
    struct record temp;
	skipLine(fpread);
	fread(&temp,sizeof(struct record),1,fpread);
	while(temp.kind==17)
	{
		//printf("\n%s.",temp.strName);
		totalCount++;
		varcount++;
		enterVarTable(temp.strName,level,totalCount);
		skipLine(fpread);
		fread(&temp,sizeof(struct record),1,fpread);
		if(temp.kind==31)
		{
			//printf("\n).");
			fseek(fpread,recordLength,SEEK_CUR);/*回退一条记录*/
			return;
		}
		else if(temp.kind==32)
		{
			//printf("\n,.");
			skipLine(fpread);
			fread(&temp,sizeof(struct record),1,fpread);	
		}
		else if((temp.kind!=32)&&(temp.kind!=31))
		{
			skip(fpread);
			printf("\nERROR: line->%d缺少右括号",lineLocation);
		}
	}
}
void processProg(FILE *fpread,int level)//专门处理program开头的这条语句,也就是分析程序的开头
{
    struct record temp;
	skipLine(fpread);
	fread(&temp,sizeof(struct record),1,fpread);
	if(temp.kind==17)
	{
		//printf("\n%s.",temp.strName);
		enterProcTable(temp.strName,level,level-1);
		skipLine(fpread);
		fread(&temp,sizeof(struct record),1,fpread);
		if(temp.kind!=33)
		{
			printf("\nERROR: line-> %d缺少分号",lineLocation);
			skip(fpread);
			return;
		}
	}
	else
	{
		printf("\nERROR: line-> %d主程序没有定义名字",lineLocation);
		skip(fpread);
		return;	
	}
}
void skip(FILE *fpread)//这个函数用于出错的情况下跳过若干个字符,直到遇到var,procedure,begin为止
{
    struct record temp;
	while(!feof(fpread)){
		fread(&temp,sizeof(struct record),1,fpread);
		if(temp.kind==35){
			lineLocation++;
		}else if((temp.kind==2)||(temp.kind==3)||(temp.kind==4)){
			fseek(fpread,recordLength,SEEK_CUR);/*回退一条记录*/
			return;
		}
	}
}
void skipLine(FILE *fpread)/*跳过换行符*/
{
    struct record temp;
	while(!feof(fpread)){
		fread(&temp,sizeof(struct record),1,fpread);
		if(temp.kind==35){
			lineLocation++;
		}else{
            fseek(fpread,recordLength,SEEK_CUR);/*回退一条记录*/
			break;
		}
	}
}
int searchprocTable(char procName[])//查找是否有同名的过程
{
	int i=0;
	if(curProcPtr==0)//过程表中没内容
		return 0;
	else//过程表中有内容,开始查找制定过程
	{
		for(i=0;i<curProcPtr;i++)
		{
			if(!(strcmp(process[i].procName,procName)))
				return 1;//找到同名过程,返回1
		}
		return 0;//没有找到同名过程返回0
	}
}
void enterProcTable(char procName[],int level,int exProc)//将过程中定义的过程名填入过程表
{
	if(searchprocTable(procName))//查找是否有同名的过程
	{
		printf("\nERROR:procedure %s has been defined.",procName);
	}
	else//没有同名的过程就将该过程名填入过程表
	{
		strcpy(process[curProcPtr].procName,procName);//填入过程的名字
		process[curProcPtr].level=level;//填入过程的层次
		process[curProcPtr].exProc=exProc;	//填入该过程的外过程
		curProcPtr++;//过程表的指针加1
	}	
}
void backPatch()//将过程定义的变量和参数信息填入过程表
{
	process[curProcPtr-1].varCount=varcount;//过程中定义的变量个数
	process[curProcPtr-1].varLocation=varLocation;//过程定义变量的开始位置(在变量表中的开始位置)
	process[curProcPtr-1].totalCount=totalCount;//过程中定义的参数和变量的总个数
	totalCount=0;
	varcount=0;
	varLocation=-1;
}
int searchVarTable(char varName[])//在变量表中查找变量
{
	int i=0;
	if(curVarPtr==0)//变量标中没内容返回0
		return 0;
	else//变量表中有内容,则开始查找改变量
	{
		for(i=0;i<curVarPtr;i++)
		{
			if(!(strcmp(variable[i].varName,varName)))
				return 1;//找到制定变量就返回1
		}
		return 0;//没有找到变量就返回0
	}
}
void enterVarTable(char varName[],int level,int relative)//将变量填入变量表
{
	if(searchVarTable(varName))//察看变量是否在变量表中存在,也就是看变量是否重定义
	{
		printf("\nERROR: variable %s has been defined.",varName);
	}
	else//如果变量以前没有定义,就将他填入变量表中
	{
		strcpy(variable[curVarPtr].varName,varName);
		variable[curVarPtr].level=level;
		variable[curVarPtr].relative=relative;
		if(varLocation==-1)
		{
			varLocation=curVarPtr;/*记录第一个参数的位置*/
		}
		curVarPtr++;
	}
}
void displayVarTable()//将变量标的内容在屏幕上显示出来,方便调试以及测试程序运行是否正确
{
	int i=0;
	printf("\nvarName:            level:    relative:\n");
	for(i=0;i<curVarPtr;i++)
	{
		printf("%-20s",variable[i].varName);	
		printf("%-10d",variable[i].level);
		printf("%-10d",variable[i].relative);
		printf("\n");
	}
}
void displayProcTable()//将过程表的内容在屏幕上显示出来
{
	int i=0;
	printf("\nprocName:          level:  varCount: varLocation:   exProc: totalCount:\n");
	for(i=0;i<curProcPtr;i++)
	{
		printf("%-20s",process[i].procName);	
		printf("%-8d",process[i].level);
		printf("%-10d",process[i].varCount);
		printf("%-15d",process[i].varLocation);
		printf("%-8d",process[i].exProc);
		printf("%-12d",process[i].totalCount);
		printf("\n");
	}	
}
void ishaveLast(FILE *fpread)
{
	struct record temp;
	while(!feof(fpread)){
		fread(&temp,sizeof(struct record),1,fpread);
		if(temp.kind==35){
			lineLocation++;
		}else if(temp.kind==34){
			return;
		}
	}
	if(temp.kind!=34)
	{
		printf("\nERROR:整个程序缺少终结符\".\"");
	}
}

int main()
{
	FILE *fpread;
	if((fpread=fopen("out.pbj","rb"))==NULL)
	{
		printf("\n没有词法分析器产生的中间文件.\n");
//		exit(0);
	}
	procProcess(fpread,0);//分析过程开始
	ishaveLast(fpread);
	fclose(fpread);
	displayVarTable();//输出变量表
	displayProcTable();//输出过程表
	return 1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -