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

📄 1.cpp

📁 PLX编译器,采用多遍式和自顶向下分析法. (内附测试代码)
💻 CPP
字号:
/*
PLX语义分析程序 
2007.11.24
*/
//头文件 
#include <stdio.h>
#include <string.h>
//全局变量
//输入格式
struct in
{
	int  type1;//关键字1 数字2 标识符3 运算符4
	int  type2;//小类
	char name[12];//数字以外的(字符串形式)
	int  value;//数字的值
	int lineno;//行号
    //int	column;
};

struct symbol//符号表
{
	char name[12];
	int position;
	int type;//aident 1 bident 2
}sym[64];

struct output
{
	int type;
	int opnum;
	int line;
};
output out[100];

int symcount=0;
int outno=0;

in input1;//保存当前分析的token

FILE *fp1,//源程序
	*fp2;//生成程序
//函数申明
void getsym();//从文件中读一个token
bool match(char type1,int type2,in token);//匹配token
bool prog();//识别prog
bool ds();//完成
bool ss();
bool d();
bool s();
bool ae();
bool be();
bool at();
bool af();
bool bt();
bool bf();
bool re();
bool insert(in token,int type);
int check(in token);
void gen(int com,int opnum);
int findpos(in token);

//主函数
int main()
{


	   if((fp1=fopen("词法分析结果.txt","r"))==NULL)
	   {
 			printf("不能打开源文件\n");
			return 0;
	   }//if

	   if((fp2=fopen("target code.txt","w"))==NULL)
	   {
 			printf("不能打开源文件\n");
			return 0;
	   }//if

	   getsym();
	   if(!prog())printf("this is not prog\n");
	   printf("no error \n");

	   for(int i=0;i<outno;i++)
	   {
		 printf("%d %d %d \n",out[i].type,out[i].opnum,out[i].line);
         fprintf(fp2,"%d %d %d ",out[i].type,out[i].opnum,out[i].line);
	   }
	   
	   return 0;
}

void getsym()
{
   fread(&input1,sizeof(input1),1,fp1);
   fgetc(fp1);
}

bool match(char type1,int type2,in token)
{
	if(type1==token.type1&&type2==token.type2)return true;
	//printf("此处未匹配 行%d \n",token.lineno);
	return false;
}

bool prog()// prog = "program" ds "begin" ss "end" ".". //done
{
	if(!match(1,11,input1))//program
	{
		printf("程序应该以program关键字开始  行%d",input1.lineno);
		return false;
	}
	ds();
	//插入语句生成部分 
	gen(5,symcount);
	printf("\n");
	//
	if(!match(1,1,input1))//begin
	{
	
		printf("程序应该以begin关键字开始程序段  行%d \n",input1.lineno);
		return false;
	}
	getsym();
	ss();
	if(!match(1,4,input1))//end
	{
		printf("程序应该以end关键字结束程序段  行%d \n",input1.lineno);
		return false;
	}
	getsym();
	if(!match(5,10,input1))//"."
	{
		printf("程序应该以.结束  行%d \n",input1.lineno);
		return false;
	}
	gen(10,0);


   return true;
}

bool ds()// ds = d {";" d }. //done
{
	getsym();
	d();
	while( match(5,11,input1) )//;
	{
	getsym();
	d();
	}
	return true;
}

bool d()// d = "integer" aident {"," aident} | "logical" bident {"," bident}  //done
{

	if(match(1,7,input1))// "integer" aident {"," aident} 
	{
		getsym();
		match(3,1,input1);//aident
		//插入符号表
		insert(input1,1);

        getsym();
		while(match(5,7,input1))// ","
		{        
			getsym();
            match(3,1,input1);//aident
			//插入符号表
			insert(input1,1);
            getsym();
		}

	}
	else //if(match(1,8,input1))// "logical" bident {"," bident} 
	{
        getsym();
		match(3,1,input1);//bident
		//插入符号表
	    insert(input1,2);

        getsym();
		while(match(5,7,input1))// ","
		{        
			getsym();
            match(3,1,input1);//bident
			//插入符号表
		    insert(input1,2);
            getsym();
		}

	}
    
	return true;
}

bool ss()//done
{	
/*
	if(match(3,1,input1)||//aident bident
		match(1,6,input1)||//if
		match(1,16,input1)||//while  write
		match(1,12,input1)||//repeat
        match(1,17,input1)//write
		)*/
		s();
    while( match(5,11,input1) )//;
	{	
	getsym();
	s();
	}
	return true;
}



bool insert(in token,int type)//done
{
	if(symcount<63)
	{
     sym[symcount].type=type;
     strcpy(sym[symcount++].name,token.name);
	 return true;
	}
	else return false;//符号表满 
}

int check(in token)//done
{
	for(int i=0;i<symcount;i++)
	{
       if(strcmp(token.name,sym[i].name)==0)return sym[i].type;
	}
	return -1;
}

int findpos(in token)//done
{
	for(int i=0;i<symcount;i++)
	{
       if(strcmp(token.name,sym[i].name)==0)return i;
	}
	return -1;
}


bool ae()// ae= ["-"] at {("-"|"+") at }. //done
{
	int optype=-1;
	if(match(5,5,input1)) 
	{
		getsym();//["-"]
		optype=1;
	}
	at();
	if(1==optype)
		gen(8,optype);

	while(match(5,5,input1)||match(5,4,input1))//{("-"|"+") at }
	{
		if(match(5,5,input1))optype=3;
		else optype=2;

        getsym();
		at();
		gen(8,optype);
	}

	return true;
}

bool at()// at = af {("*"|"/") af}.   //done
{
	int optype=-1;
     af();
	 while(match(5,0,input1)||match(5,1,input1))//("*"|"/")  ???
	 {
		 if(match(5,0,input1))optype=4;
		 else optype=5;

        getsym();
		af();
		 gen(8,optype);

	 }
	 return true;
}

bool be()// bt {"or" bt}  //done yuyi yet
{

    bt();
	while(match(1,10,input1))//"or"
	{
		getsym();
		bt();
	}
    return true;
}

bool af()// af = aident | number | "(" ae ")" .  //done
{
	int pos=-1;
	if(match(3,1,input1))
	{//判断是aident
		if(check(input1)!=1)
		{
			printf("变量类型错误 行%d \n",input1.lineno);
			return false;
		}

		pos=findpos(input1);
		gen(2,pos);

        getsym();
		return true;
	}
	else if(match(2,1,input1))  //number
	{
		gen(1,input1.value);
		getsym();
		return true;
	}
	else if(match(5,2,input1)) // "(" ae ")"
	{
	       getsym();
           ae();
		   match(5,3,input1);
		   getsym();
		   return true;
	}
	return true;
}

bool bt()// bt = bf {"and" bf } . //done yuyi yet
{
	bf();
	while(match(1,0,input1))//and
	{
	getsym();
	bf();
	}
	return true;
}

bool bf()//bf = bident | "true" | "false" |"not" bf |"(" be ")" | re . //done
{
	int pos=-1;
    if( match(3,1,input1) && (check(input1)==2) )//bident
	{
		pos=findpos(input1);
		gen(2,pos);
		
		getsym();
		return true;
	}
	if(match(1,14,input1)||match(1,5,input1))//true false
	{
		if(match(1,14,input1)) gen(1,1);
		else gen(1,0);
		getsym();
		return true;
	}
	if(match(1,9,input1))//not yuyi yet
	{
     getsym();
	 bf();
	 return true;
	}
	if(match(5,2,input1))//"(" be ")"
	{
       getsym();
	   be();
	   match(5,3,input1);// ")"
	}
	else
	{
		re();
		return true;
	}

	return false;
}

bool re()// re = (aident | number )( "=" | ">=" | "<" | "<=" | "/=" ) ae . //yet
{
	if(match(3,1,input1))//aident
	{//判断aident
		  int pos=-1;
		  int optype=-1;
          if(check(input1)!=1)
		  {
			  printf("变量的类型不正确 行%d",input1.lineno);
			  return false;
		  }
		  pos=findpos(input1);
		  gen(2,pos);
		  getsym();
		  //( "=" | ">=" | "<=" | "/="| "<"  )
		  if(match(5,6,input1)||match(4,1,input1)||match(4,0,input1)||match(4,2,input1)||match(5,8,input1))
		  {
				if( match(5,6,input1) )optype=8;
				if( match(4,1,input1) )optype=11;
				if( match(4,0,input1) )optype=13;
				if( match(4,2,input1) )optype=9;
				if( match(5,8,input1) )optype=10;

			  getsym();	 
		      ae();
			  gen(8,optype);
			  return true; 
		  }
		  else printf("赋值的表达式不正确 行%d \n",input1.lineno);
		  
	}
	if(match(2,1,input1)) //number yuyi yet
	{
		  getsym();
          //( "=" | ">=" | "<" | "<=" | "/=" )
		  if(match(5,6,input1)||match(4,1,input1)||match(4,0,input1)||match(4,2,input1))
		  {
			  getsym();
		      ae();
			  return true;
		  }
		  else printf("赋值的表达式不正确 行%d \n",input1.lineno);
	}
    return false;
}

bool s()//yet
/*
aident " := " ae |
bident " := " be |
"if" be "then" ss ["else" ss] "end" |
"while" be "do" ss "end" |
"repeat" ss "until" be |
"write" ae .
*/
{
	int type=0;
    if(match(3,1,input1))//aident " := " ae | bident " := " be
	{
		//参考符号表
		int pos=-1;
		pos=findpos(input1);

		type=check(input1);
		getsym();
		match(4,3,input1);// ":="    
		getsym();
        if(type==1) ae();
		else if(type==2) be();
		else printf("变量的类型不正确 行%d\n",input1.lineno);

		gen(3,pos);
		printf("\n");

		return true;
	}
	if( match(1,6,input1) )//"if" be "then" ss ["else" ss] "end" 
	{
		int ifend=-1;
		int elsebegin=-1;
		int waitline1=-1;//else begin
		int waitline2=-1;//if end

		getsym();
		be();
		printf("\n");

		waitline1=outno;
		gen(7,-1);//else begin

		match(1,13,input1);//then
		getsym();
		ss();

		waitline2=outno;
		gen(6,-1);//if end

        printf("\n");

		elsebegin=outno;
		out[waitline1].opnum=elsebegin;

		if(match(1,3,input1))//else
		{
            getsym();
			ss();
		}
		printf("\n");

		ifend=outno;
        out[waitline2].opnum=ifend;

		match(1,4,input1);//end
		getsym();
		return true;
	}
	if( match(1,16,input1) )//"while" be "do" ss "end"
	{
		int whilebegin=outno;
		int waitline=-1;

		getsym();
		be();
		printf("\n");

		waitline=outno;//等待回填	
		gen(7,-1);


		match(1,2,input1);//do
        getsym();
		ss();
		printf("\n");

		gen(6,whilebegin);
		//huitian
		out[waitline].opnum=outno;
		//huitian

		match(1,4,input1);//end
		getsym();

		return true;
	}
	if( match(1,12,input1) )//"repeat" ss "until" be 
	{ 
		getsym();
	    ss();
		printf("\n");

        match(1,15,input1);//until
		getsym();
		be();
		return true;
	}
	if( match(1,17,input1) )//write" ae
	{
		getsym();
		ae();
		gen(9,0);
	}


	return true;
}

void gen(int com,int opnum)
{
	//printf("%d %d %d \n",com,opnum,outno++);
	out[outno].line=outno;
	out[outno].opnum=opnum;
	out[outno].type=com;
	outno++;
	//printf("%d %d \n",com,opnum);
}


/*
fread(p,sizeof(*p),1,fp1);写成fread(p,sizeof(p),1,fp1);其中in *p,导致读入的信息不正确
*/

/*
//关键字表
char keywords[KEYNUM][KEYNUM]={
	"and",
	"begin",
	"do",
	"else",
	"end",
	"false",
	"if",
	"integer",
	"logical",
	"not",
	"or",
	"program",
	"repeat",
	"then",
	"true",
	"until",
	"while",
	"write",
};
//符号表(单个)
char symbol1[SYMBOLNUM]={'*' , '/' , '(' , ')' ,
						 '+' , '-' , '=' , ',' ,             
			             '<' , '>' , '.' , ';' ,
						 
};
//符号表(组合)
char symbol2[10][3]={ "<=" , ">="  , "/=" ,":=" };
*/

/*
对于多次重复的未想出处理方法 11.14
*/

⌨️ 快捷键说明

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