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

📄 pl.cpp

📁 实现自顶向下或自底向上分析方法的实现方法
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*使用方法:
*运行后输入PL/0 源程序文件名
*回答是否输出虚拟机代码
*回答是否输出名字表
*fa.txt   输出虚拟机代码
*fa1.txt  输出源文件及其各行对应的首地址
*fa2.txt  输出结果 
*/
#include <fstream>
#include <iostream>
#include<stdio.h>
#include"string.h"
# define norw 13                 //关键字个数
# define txmax 100               //名字表容量
# define nmax  14                //number的最大位数
# define al 10                   //符号的最大长度
# define amax 2047               //地址上界
# define levmax 3                //最大允许过程嵌套声明层数[0,lexmax]
# define cxmax 200               //最多的虚拟机代码数
#define stacksize 500            //解释执行时使用的栈
enum symbol{                     //符号说明
	 nul,ident,number,plus,minus,times,slash,oddsym,eql,neq,lss,leq,gtr,geq,
	lparen,rparen,comma,semicolon,period,becomes,beginsym,endsym,ifsym,thensym,
	whilesym,writesym,readsym,dosym,callsym,constsym,varsym,procsym,
};
#define symnum 32
enum object{
   constant,variable,procedur,
};
enum fct{
lit,opr,lod,sto,cal,inte,jmp,jpc,
};
#define fctnum 8
struct instruction
{ enum fct f;
  int l;
  int a;
};
void error(int n);//出错处理,打印错误编码
int getsym();//词法分析,获取一个符号
int getch();
void init();//初始化操作
int gen(enum fct x,int y,int z);//生成虚拟机代码
int test(bool*s1,bool*s2,int n);//测试当前符号是否合法
int inset(int e,bool*s);//用数组实现集合的集合运算
int addset(bool*sr,bool*s1,bool*s2,int n);
int subset(bool*sr,bool*s1,bool*s2,int n);
int mulset(bool*sr,bool*s1,bool*s2,int n);
int block(int lev,int tx,bool* fsys);
void interpret();//解释程序
int factor(bool* fsys,int* ptx,int lev);//因子处理
int term(bool*fsys,int*ptx,int lev);//项处理
int condition(bool*fsys,int*ptx,int lev);//条件处理
int expression(bool*fsys,int*ptx,int lev);//表达式处理
int statement(bool*fsys,int*ptx,int lev);//语句处理
void listcode(int cx0);//输入目标代码清单
int vardeclaration(int* ptx,int lev, int* pdx);
int constdeclaration(int* ptx,int lev, int* pdx);//常量声明处理
int position(char* idt,int tx);//查找位置
void enter(enum object k,int* ptx,int lev,int* pdx);
int base(int l,int* s,int b);
FILE * fa;
FILE * fa1;
FILE * fa2;
bool tableswitch;
bool listswitch;
char ch;
enum symbol sym;
char id[al+1];
int  num;
int cc,ll;
int cx;
char line[81];
char a[al+1];
struct instruction code[cxmax];
char word[norw][al];
enum symbol wsym[norw];
enum symbol ssym[256];
char mnemonic[fctnum][5];
bool declbegsys[symnum];
bool statbegsys[symnum];
bool facbegsys[symnum];
struct tablestruct
{  char name[al];                            /*名字*/
   enum object kind;                         /*类型:const,var,array or procedure*/
   int val;                                  /*数值,仅const使用*/
   int level;                                /*所处层,仅const不使用*/
   int adr;                                  /*地址,仅const不使用*/
   int size;                                 /*需要分配的数据区空间,仅procedure使用*/
};
struct tablestruct table[txmax];             /*名字表*/
FILE * fin;
FILE* fout;
char fname[al];
int err;                                       /*错误计数器*/
/*当函数中会发生fatal error时,返回-1告知调用它的函数,最终退出程序*/
#define getsymdo                              if(-1==getsym())return -1
#define getchdo                               if(-1==getch())return -1
#define testdo(a,b,c)                         if(-1==test(a,b,c))return -1
#define gendo(a,b,c)                          if(-1==gen(a,b,c))return -1
#define expressiondo(a,b,c)                   if(-1==expression(a,b,c))return -1
#define factordo(a,b,c)                       if(-1==factor(a,b,c))return -1
#define termdo(a,b,c)                         if(-1==term(a,b,c))return -1
#define conditiondo(a,b,c)                    if(-1==condition(a,b,c))return -1
#define statementdo(a,b,c)                    if(-1==statement(a,b,c))return -1
#define constdeclarationdo(a,b,c)             if(-1==constdeclaration(a,b,c))return -1
#define vardeclarationdo(a,b,c)               if(-1==vardeclaration(a,b,c))return -1
int main()                     //主函数
{	bool nxtlev[symnum];
    printf(" fa.txt   虚拟机代码输出文件\n");
    printf(" fa1.txt  源文件及其各行对应的首地址输出文件\n");
    printf(" fa2.txt  结果输出文件\n");
	printf("Input pl/0 file's name(输入pl/0文法的文档) ?");
	scanf("%s",fname);                                     /*输入文件名*/
	fin=fopen(fname,"r");
	if(fin)
	{	printf("List object code(是否输出虚拟机代码)?(Y/N)");    /*是否输出虚拟机代码*/
		scanf("%s",fname);
		listswitch=(fname[0]=='y'||fname[0]=='Y');
		fa1=fopen("fa1.txt","w");
		fprintf(fa1,"Iput pl/0 file ?");
		fprintf(fa1,"%s\n", fname);
		init();                                          /*初始化*/
		err=0;
		cc=cx=ll=0;
		ch=' ';
		if(-1!=getsym())
		{	fa=fopen("fa.txt","w");
			addset(nxtlev,declbegsys,statbegsys,symnum);
			nxtlev[period]=true;    
			if(-1==block(0,0,nxtlev))			/*调用编译程序*/
			{	fclose(fa);
				fclose(fa1);
				fclose(fin);
				printf("\n");
				return 0;
			}
			fclose(fa);
			fclose(fa1);
			if(sym!=period)
			{
				error(9);
			}
			if(err==0)
			{	fa2=fopen("fa2.txt", "w");
				interpret();
				fclose(fa2);
			}
			else
			{
				printf("Errors in pl/0 program");
			}
		}
		fclose(fin);
	}
	else
	{
		printf("Can't open file!(不存在该文件) \n");
	}
	printf("\n");
	return 0;
}
void init()//初始化
{	int i;
	for(i=0;i<=255;i++)
	{
		ssym[i]=nul;
	}
	ssym['+']=plus;
	ssym['-']=minus;
	ssym['*']=times;
	ssym['/']=slash;
	ssym['(']=lparen;
	ssym[')']=rparen;
	ssym['=']=eql;
	ssym[',']=comma;
	ssym['.']=period;
	ssym['#']=neq;
	ssym[';']=semicolon;
	strcpy(&(word[0][0]),"begin");/*设置保留字名字,按照字母顺序,便于折半查找*/
	strcpy(&(word[1][0]),"call");
	strcpy(&(word[2][0]),"const");
	strcpy(&(word[3][0]),"do");
	strcpy(&(word[4][0]),"end");
	strcpy(&(word[5][0]),"if");
	strcpy(&(word[6][0]),"odd");
	strcpy(&(word[7][0]),"procedure");
	strcpy(&(word[8][0]),"read");
	strcpy(&(word[9][0]),"then");
	strcpy(&(word[10][0]),"var");
	strcpy(&(word[11][0]),"while");
	strcpy(&(word[12][0]),"write");
	wsym[0]=beginsym;	/*设置保留字符号*/
	wsym[1]=callsym;
	wsym[2]=constsym;
	wsym[3]=dosym;
	wsym[4]=endsym;
	wsym[5]=ifsym;
	wsym[6]=oddsym;
	wsym[7]=procsym;
	wsym[8]=readsym;
	wsym[9]=thensym;
	wsym[10]=varsym;
	wsym[11]=whilesym;
	wsym[12]=writesym;
  	strcpy(&(mnemonic[lit][0]),"lit");/*设置指令名称*/
	strcpy(&(mnemonic[opr][0]),"opr");
	strcpy(&(mnemonic[lod][0]),"lod");
	strcpy(&(mnemonic[sto][0]),"sto");
	strcpy(&(mnemonic[cal][0]),"cal");
	strcpy(&(mnemonic[inte][0]),"int");
	strcpy(&(mnemonic[jmp][0]),"jmp");
	strcpy(&(mnemonic[jpc][0]),"jpc");
	for(i=0;i<symnum;i++)/*设置符号集*/
	{	declbegsys[i]=false;
		statbegsys[i]=false;
		facbegsys[i]=false;
	}
	declbegsys[constsym]=true;/*设置声明开始符号集*/
	declbegsys[varsym]=true;
	declbegsys[procsym]=true;
	statbegsys[beginsym]=true;/*设置语句开始符号集*/
	statbegsys[callsym]=true;
	statbegsys[ifsym]=true;
	statbegsys[whilesym]=true;
	facbegsys[ident]=true;/*设置因子开始符号集*/
	facbegsys[number]=true;
	facbegsys[lparen]=true;
}
//用数组实现集合的集合运算
int inset(int e,bool* s)
{
    return s[e];
}
int addset(bool* sr,bool* s1,bool* s2,int n)
{   int i;
    for(i=0;i<n;i++)
    {
       sr[i]=s1[i]||s2[i];  
    }
    return 0;
}
int subset(bool* sr,bool* s1,bool* s2,int n)
{   int i;
    for(i=0;i<n;i++)
    {
       sr[i]=s1[i]&&(!s2[i]);
    }
    return 0; 
}
int mulset(bool* sr,bool* s1,bool* s2,int n)
{   int i;
    for(i=0;i<n;i++)
    {
       sr[i]=s1[i]&&s2[i];  
    } 
    return 0;
}
void error(int n)//出错处理,打印出错位置和错误编码
{	err++;		//错误个数加1
	switch(n)
	{	case 1:
		  printf("把=写成了:=");
		  break;
	    case 2:
		  printf("常量说明=后应是数字");
		  break;
	    case 3:
		  printf("常量说明标识后应为=");
		  break;
	    case 4:
		  printf("procedure/const/var后应是标识符");
		  break;
	    case 5:
		  printf("漏掉逗号");
		  break;
	    case 6:
		  printf("缺少then");
	      break;
	    case 7:
		  printf("缺少end");
		  break;
    	case 8:
		  printf("缺少do");
		  break;
	    case 9:
		  printf("call后标识符应为过程");
		  break;
	    case 10:
		  printf("缺少分号");
		  break;
	    case 11:
		  printf("标识符未声明");
		break;
	    case 12:
		  printf("不能向常量名/过程名赋值");
		  break;
	    case 13:
		  printf("赋值符号:=写错");
		  break;
	    case 14:
		  printf("call后应为标识符");
		  break;
	    case 15:
		  printf("应为运算关系符号");
		  break;
	    case 30:
		  printf("数值越界,这个数太大");
		  break;
    	case 31:
		  printf("地址越界");
		  break;
	    case 32:
		  printf("嵌套层数越界,最深嵌套为三层");
		  break;
	    case 33:
		  printf("read/write表达式缺少右括号");
		  break;
 	    case 34:
          printf("read/write表达式缺少左括号");
		  break;
	}
}
int getch()//  漏掉空格,读取一个字符;每次读一行,存入line缓冲区,line被getsym取空后再读一行
{          //  被函数getsym调用
	if(cc==ll)
    {	if(feof(fin))
		{	printf("program incomplete");
			return -1;
		}
		ll=0;
		cc=0;
		printf("%d ",cx );
		fprintf(fa1,"%d ",cx);
		ch=' ';
		while(ch!=10)
		{   if(EOF==fscanf(fin,"%c",&ch))
			{	line[ll]=0;
				break;
			}
			printf("%c",ch);
			fprintf(fa1,"%c",ch);
			line[ll]=ch;
			ll++;
		}
		printf("\n");
		fprintf(fa1,"\n");
	}
	ch=line[cc];
	cc++;
	return 0;
}
 int getsym()//词法分析,获取一个符号
{	int i,j,k;
	while( ch==' '||ch==10||ch==9)
	{
		getchdo;
	}
	if(ch>='a'&&ch<='z')
	{	k=0;
		do{ if(k<al)
			{ 	a[k]=ch;
				k++;
			}
			getchdo; 
		}while(ch>='a'&&ch<='z'||ch>='0'&&ch<='9');
		a[k]=0;
		strcpy(id,a);
		i=0;
		j=norw-1;
		do{	k=(i+j)/2;
			if(strcmp(id,word[k])<=0)
			{
				j=k-1;
			}
			if(strcmp(id,word[k])>=0)
			{
				i=k+1;
			}
		}while(i<=j);
		if(i-1>j)
		{
			sym=wsym[k];
		}
		else
		{
			sym=ident;
		}
	}
	else
	{	if(ch>='0'&&ch<='9')
		{	k=0;
			num=0;
			sym=number;
			do{	num=10*num+ch-'0';
				k++;
				getchdo;

⌨️ 快捷键说明

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