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

📄 pl.cpp

📁 这是我们的一个上机题,做词法分析和语法的,希望对大家的学习有所帮助
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// PL.cpp : Defines the entry point for the console application.
//
#include "common.h"

////////////////////////////////////////////////////////////
////////////////////////函数头定义如下//////////////////////
////////////////////////////////////////////////////////////

SYMLIST * listsAdd(SYMLIST * list1,SYMLIST * list2);
SYMLIST * listAddSym(SYMLIST * list,SYMBOL sym);
int SYMINLIST(SYMBOL sym,SYMLIST * list);
void COPYLIST(SYMLIST * list1,SYMLIST * list2);

void error(int);
int nError;

void INITIAL();
void ENTERID();
void ENTERPREID();

void getSymbols(FILE *);
void getASymbol();
void destroySymbols();
SymbolItem *Symbols=NULL;
SymbolItem *CurSymbol=NULL;

void GEN(OPCOD func,int level,int address);
void WriteObjCode(char *);
void WriteCodeList(char *);

void ENTERARRAY(SYMLIST * list,TYPES type,int low,int high);
void ENTERBLOCK();
void ENTER(OBJECT object);
int GETPOSITION(char * id);
void CONSTANT(SYMLIST * list,CONSTREC & constRec);
void ARRAYTYP(SYMLIST * list,int & aref,int & arsz);
void TYP(SYMLIST * list,TYPES & tp,int & rf,int & sz);
void PARAMENTERLIST(SYMLIST * list);

void CONSTDECLARATION(SYMLIST * list);
void TYPEDECLARATION(SYMLIST * list);
void VARDECLARATION(SYMLIST * list);
void PROCDECLARATION(SYMLIST * list);

void FACTOR(SYMLIST * list,TYPEITEM & typeItem);
void TERM(SYMLIST * list,TYPEITEM & typeItem);
void SIMPLEEXPRESSION(SYMLIST * list,TYPEITEM & typeItem);
void EXPRESSION(SYMLIST * list,TYPEITEM & typeItem);
void ARRAYELEMENT(SYMLIST * list,TYPEITEM & typeItem);

void ASSIGNMENT(SYMLIST * list);
void IFSTATEMENT(SYMLIST * list);
void WHILESTATEMENT(SYMLIST * list);
void FORSTATEMENT(SYMLIST * list);
void REPEATSTATEMENT(SYMLIST * list);
void CASESTATEMENT(SYMLIST * list);
void soncase(SYMLIST * list,int & jumpback,int temp);
void COMPOUND(SYMLIST * list);
void STANDPROC(SYMLIST * list,int i);
void CALL(SYMLIST * list);
void STATEMENT(SYMLIST * list);
void BLOCK(SYMLIST * list,int level);

////////////////////////////////////////////////////////////
////////////////////函数过程定义如下////////////////////////
////////////////////////////////////////////////////////////

void GEN(OPCOD func,int level,int address) //将产生的代码保存到代码数组CODE里面
{										   //并将代码索引CX增加 1	
	static int lineNumber=0;
	if(CX>MAXNUMOFCODEADDRESS)
	{
		printf("PROGRAM TOO LONG!");
		exit(0);
	}

	printf("%d\t",lineNumber);                 //下面三个语句用来在编译的过程中显示代码
	printf(ObjCodeScript[func],level,address); //注意:现实的代码不是完全的,但是可以帮助理解
	printf("\n");

	CODE[CX].lineNumber=lineNumber++;
	CODE[CX].func=func;
	CODE[CX].level=level;
	CODE[CX].address=address;
	CX++;
}



void WriteObjCode(char *filename)  //将产生的代码写进*.pld文件里面(二进制形式)
{
	FILE *fcode;
	
	fcode=fopen(filename,"wb");
	if(!fcode)
		error(40);  //不能打开.pld文件
	for(int i=0;i<CX;i++)
	{
		fwrite(&CODE[i].func,sizeof(OPCOD),1,fcode);
		fwrite(&CODE[i].level,sizeof(int),1,fcode);
		fwrite(&CODE[i].address,sizeof(int),1,fcode);
	}
	fclose(fcode);	
}

void WriteCodeList(char *filename)  //将产生的代码写进*.lst文件(可见字符形式)
{
	FILE *flist;
	
	flist=fopen(filename,"wb");
	if(!flist)
		error(39);  //不能打开.lst文件
	for(int i=0;i<CX;i++)
	{
		fprintf(flist,"%d\t",i);
		fprintf(flist,ObjCodeScript[CODE[i].func],CODE[i].level,CODE[i].address);
		fprintf(flist,"\n");
	}
	fclose(flist);
}

void WriteLabelCode(char *filename)  //将产生的代码写进*.lab文件(可见字符形式)
{
	FILE *flabel;
	
	flabel=fopen(filename,"wb");
	if(!flabel)
		error(41);  //不能打开.lst文件
	for(int i=0;i<JX;i++)
	{
		fprintf(flabel,"第%d项:\t",i+1);
		fprintf(flabel,"%d",JUMADRTAB[i]);
		fprintf(flabel,"\n");
	}
	fclose(flabel);
}

void ENTERARRAY(TYPES type,int low,int high)  //向数组信息表填入一个表项
{
	if(low>high)
	{
		error(19); //"数组上下大小关系界错误"
	}
	if (AX==MAXNUMOFARRAYTABLE)
	{
		error(24);  //数组表溢出
		printf("TOO LONG ARRAYS IN PROGRAM!");
	}
	else
	{
		AX++;
		ATAB[AX].intType=type;
		ATAB[AX].low=low;
		ATAB[AX].high=high;
	}
}

void ENTERBLOCK()           //每当编译一个过程开始时,保证调用该函数一次
{							//用来向程序体表填入一个表项以登记此过程体
	if(BX==MAXNUMOFBLOCKTABLE)
	{
		error(26);  //程序体表溢出
		printf("TOO MANY PROCEDURE IN PROGRAM!");
	}
	else
	{
		BX++;
		displayLevel++;  //编译到了一个过程,层次加一
		BTAB[BX].last=0;
		BTAB[BX].lastPar=0;
	}
}

void QUITBLOCK()        //每当一个过程编译完时,保证调用该函数一次
{
	displayLevel--;     //层次减一
}


void ENTER(OBJECT kind) //在编译的过程中将遇到的符号填入符号表中
{						//如果在同一层次内有两次定义性质的出现,则报错
	int j,l;
	if(TX==MAXNUMOFNAMETABLE)
	{
		error(25);  //名字表溢出
		printf("PROGRAM TOO LONG!");
	}
	else
	{
		strcpy(NAMETAB[0].name,CurSymbol->value.lpValue);    //当前标识符(注意:只能是标识符)的内容填入符号表的第一项??????????
		j=BTAB[DISPLAY[displayLevel]].last;   //将临时变量j设成当前DISPLAY表项所指向的程序体表项的last域
		l=j;
		while(stricmp(NAMETAB[j].name,CurSymbol->value.lpValue))  
			j=NAMETAB[j].link;               //顺藤摸瓜
		if(j>0)
			error(31); //如果摸着了,则本程序体内符号重复定义
	    else
		{             //否则,填入相应的信息
			TX++;
			strcpy(NAMETAB[TX].name,CurSymbol->value.lpValue);
			NAMETAB[TX].link=l;
			NAMETAB[TX].kind=kind;
			NAMETAB[TX].type=NOTYP;
			NAMETAB[TX].ref=0;
			NAMETAB[TX].level=displayLevel;
			NAMETAB[TX].normal=0;
			switch(kind)
			{
			case VARIABLE:
			case PROCEDURE:
				NAMETAB[TX].unite.address=0;break;
			case KONSTANT:
				NAMETAB[TX].unite.value=0;break;
			case TYPEL:
				NAMETAB[TX].unite.size=0;break;
			}
			BTAB[DISPLAY[displayLevel]].last=TX;
		}		
	}
}

int GETPOSITION(char * id)  //通过标识符的内容在名字表里面查找其索引
{
	int i=0,j=displayLevel;
	strcpy(NAMETAB[0].name,id);
	//j=displayLevel;

	do              //在所有的活动记录(注意:是活动的)里面顺藤摸瓜
	{
		i=BTAB[DISPLAY[j]].last;
		while (stricmp(NAMETAB[i].name,CurSymbol->value.lpValue))
			i=NAMETAB[i].link;
		j--;        //一个记录里面没有摸到,则到上一级里面去
	}while( j>=0 && i==0);   
	if(i==0)      // 表示没有摸到
		error(33);  //没有定义符号
	return (int)i;
}

void CONSTANT(SYMLIST * list,CONSTREC & constRec)  //从源程序里面获取一个常量类型的数据
{												   //传引用参数constRec 用来记录获取的结果
	int x,sign;

	constRec.type=NOTYP;
	constRec.value=0;
	if(SYMINLIST(CurSymbol->type,&CONSTBEGSYS))
	{
		if(CurSymbol->type==CHARCON)
		{
			constRec.type=CHARS;
			constRec.value=CurSymbol->value.iValue;
			getASymbol();
		}
		else
		{
			sign=1;       //将常量的符号默认置为正
			if(CurSymbol->type==PLUS || CurSymbol->type==MINUS)
			{
				if(CurSymbol->type==MINUS)
					sign=-1;  //置为负
				getASymbol();
			}

			if(CurSymbol->type==IDENT)
			{
				x=GETPOSITION(CurSymbol->value.lpValue);  //查表
				if(x!=0)
				{
					if(NAMETAB[x].kind!=KONSTANT)
						error(17);// 应该是常量或者常量标识符
					else
					{
						constRec.type=NAMETAB[x].type;
						constRec.value=sign*NAMETAB[x].unite.value;
					}
				}
				getASymbol();
			}
			else if(CurSymbol->type==INTCON)
			{
				constRec.type=INTS;
				constRec.value=sign*CurSymbol->value.iValue;
				getASymbol();
			}
		}
	}
}

void ARRAYTYP(SYMLIST * list,int & arrayRef,int & arraySize)  //获取一个数组类型的信息,传引用参数arrayRef和arraySize
{																  //用来记录从数组获取的引用信息和大小信息	
	TYPES eleType;
	CONSTREC low,high;
	int eleRef,eleSize;

	//////////////////////////////////////////////////////////
	SYMLIST * tempList=new SYMLIST;
	tempList->AddHead(COLON);	tempList->AddHead(RBRACK);
	tempList->AddHead(RPAREN);	tempList->AddHead(OFSYM);
	CONSTANT(tempList,low);         //获得数组下标的下限
	delete tempList;
	//////////////////////////////////////////////////////////

	if(low.type!=INTS && low.type!=CHARS)
		error(20);  //下标元素类型错误
    if(CurSymbol->type==DPOINT)
		getASymbol();
	else
		error(42);//应该是'..'

	//////////////////////////////////////////////////////////
    SYMLIST * tempList1=new SYMLIST;
	tempList1->AddHead(COMMA);	tempList1->AddHead(RBRACK);
	tempList1->AddHead(RPAREN);	tempList1->AddHead(OFSYM);
	CONSTANT(tempList1,high);        //获得数组下标的上限
	delete tempList1;
	//////////////////////////////////////////////////////////

	if(low.type!=high.type)
	{
		error(21);  //上下界的类型不一致
		high.value=low.value;
	}

	ENTERARRAY(low.type,low.value,high.value);   //向数组信息表登记

	arrayRef=AX;
	if(CurSymbol->type==COMMA)   //如果当前符号是逗号,表示数组是多维的
	{
		getASymbol();
		eleType=ARRAYS;    //数组的“子维”的类型是数组
		ARRAYTYP(list,eleRef,eleSize);   //获取较低维的数组的信息
	}
	else
	{
		if(CurSymbol->type==RBRACK)
			getASymbol();
		else
		{
			error(5);  //应该是']'
			if(CurSymbol->type==RPAREN)
				getASymbol();
		}

		if(CurSymbol->type==OFSYM)
			getASymbol();
		else
			error(10);  //应该是'of'
		TYP(list,eleType,eleRef,eleSize);   //获取数组元素的类型
	}
	arraySize=(high.value-low.value+1)*eleSize;   //计算本数组类型的大小
	ATAB[arrayRef].size=arraySize;
	ATAB[arrayRef].eleType=eleType;          //填信息
	ATAB[arrayRef].elRef=eleRef;
	ATAB[arrayRef].elSize=eleSize;
}


void TYP(SYMLIST * list,TYPES & type,int & ref,int & size)//获取(到名字表里面查找)当前的标识符的类型信息
{	
	int x;		

	type=NOTYP;
	ref=0;
	size=0;
	if(SYMINLIST(CurSymbol->type,&TYPEBEGSYS))
	{
		if(CurSymbol->type==IDENT)
		{
			x=GETPOSITION(CurSymbol->value.lpValue);   //查表
			if(x!=0)
			{
				if(NAMETAB[x].kind!=TYPEL)
				{
					error(15);  //应该是类型标识符
				}
				else
				{
					type=NAMETAB[x].type;
					ref=NAMETAB[x].ref;
					size=NAMETAB[x].unite.size;
					if(type==NOTYP)
						error(36);  //类型定义出错
				}
				getASymbol();
			}
		}
		else if (CurSymbol->type==ARRAYSYM)  //如果是数组类型
		{
			getASymbol();
			if(CurSymbol->type==LBRACK)
				getASymbol();
			else
			{
				error(4);  //应该是'['
				if(CurSymbol->type==LPAREN)
					getASymbol();
			}
			type=ARRAYS;
			ARRAYTYP(list,ref,size);  //返回数组类型的信息
		}
	}
}


void PARAMENTERLIST(SYMLIST * list)  //编译某个过程的参数列表
{
	TYPES type;	
	int ref,size,x,helper;

	type=NOTYP;
	ref=0;
	size=0;

	getASymbol();	
	while(CurSymbol->type==IDENT || CurSymbol->type==VARSYM)
	{
		int valuePar=0;  //默认是变量参数
		if(CurSymbol->type!=VARSYM)
			valuePar=1;  //如果当前符号不是var则表明是值参数
		else
			getASymbol();
			
		helper=TX;
		if(CurSymbol->type==IDENT)
		{
			ENTER(VARIABLE);  //编译到一个变量,将其信息填入符号表
			getASymbol();
		}
		else 
			error(14);  //应该是标识符

		while(CurSymbol->type==COMMA)  //如果当前符号是逗号,则说明是一个参数列表,继续读入下一个标识符
		{
			getASymbol();

⌨️ 快捷键说明

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