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

📄 编译器.cpp

📁 编译原理课程设计,用C写的PL/0编译器,有详细的文档和代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			if(sym=="rparen")         //子表达式分析完后,应遇到右括号
			{
				getsym();
			}
			else
				error(22);
		}//if
		test(fsys,facbegsys,23);        //一个因子处理完毕,遇到的token应在fsys集合中
		                                //如果不是,抛23号错,并找到下一个因子的开始,使语法分析可以继续运行下去
	}//while
}//factor

void term(symset fsys){               //项处理
	string mulop;
	//factor([times,slash]+fsys);       //每一个项都应该由因子开始,因此调用factor子程序分析因子
	addsym(fsys,"times");
    addsym(fsys,"slash");
	if (sym=="times"||sym=="slash"){   //一个因子后应当遇到乘号或除号
		mulop=sym;
		getsym();
		//factor(fsys+[times,slash]);    //调factor子程序分析因子
		addsym(fsys,"times");
        addsym(fsys,"slash");
		if (mulop=="times"){           //如果刚才遇到乘号
			gen("opr",0,4);            //生成乘法指令
		}
		else 
			gen("opr",0,5);            //生成除法指令
	}//if
}//term



void condition(symset fsys){    //条件处理过程condition
	string relop;              //用于临时记录token(这里一定是一个二元逻辑运算符)的内容
	string a[6]={"eql","neq","lss","leq","gtr","geq"};
	int k=0;
	int j=0;
	if(sym=="oddsym")          //如果是odd运算符(一元
	{
		getsym();
		expression(fsys);
		gen("opr",0,6);        //生成6号操作指令:奇偶判断运算
	}
	else 
	{   
		//expression([eql,neq,lss,leq,gtr,geq]+fsys);    //对表达式左部进行处理计算
		addsym(fsys,"eql");
        addsym(fsys,"neq");
		addsym(fsys,"lss");
		addsym(fsys,"leq");
		addsym(fsys,"gtr");
		addsym(fsys,"qep");
		expression(fsys);
	    for(int i=0;i<6;i++)
		{
			if(sym==a[i])
				k=1;
			else k=-1;
		}
		if(k==1){
			relop=sym;
			getsym();
			expression(fsys);             //对表达式右部进行处理计算
			if (relop=="eql")
				j=1;
			else if(relop=="neq")
				j=2;
			else if(relop=="lss")
				j=3;
            else if(relop=="geq")
				j=4;
			else if(relop=="gtr")
				j=5;
			else if(relop=="leq")
				j=6;
			switch(j){
		    	case 1: {          
				             gen("opr",0,8);      //等号:产生8号判等指令 
							 break;
						   }
			   case 2: { 
				             gen("opr",0,9);      //不等号:产生9号判不等指令
							 break;
						   }
			   case 3: {
				             gen("opr",0,10);     //小于号:产生10号判小指令
							 break;
						   }
			   case 4: {
				             gen("opr",0,11);     //大于等号号:产生11号判不小于指令
							 break;
						   }
			   case 5: {
				             gen("opr",0,12);   //大于号:产生12号判大于指令
							 break;
						   }
			   case 6: {
				             gen("opr",0,13);   //小于等于号:产生13号判不大于指令
							 break;
						   }
			}//switch
		}//if
		if(k==-1)
			error(20);
	}
}//condition

void statement(){       //语句处理过程
	int i,cx1,cx2;
	int psw=0;    //标志位
	if (sym=="ident")
		psw=1;    //如果以标识符开头,psw为1
	if (sym=="readsym")
		psw=2;     //如果是read语句
	if (sym=="writesym")
		psw=3;     //如果遇到write语句
	if (sym=="callsym")
		psw=4;     //如果遇到call语句
	if (sym=="ifsym")  
		psw=5;     //如果遇到if语句
	if (sym=="beginsym")  
		psw=6;     //如果遇到begin语句
	if (sym=="whilesym")
		psw=7;     //如果遇到while语句
	switch(psw)
	{
	    case 1:  {               
			     i=position(id);             //在符号表里查找该标识符的位置
				     if (i==0)
					 { error(11);}
					 else if (table[i].kind!="variable")  //若找到 但该标识符不是变量名
					 {
				         error(12);
					     i=0;
					 }
                 getsym();        //获得下一个token,正常应为赋值号             
                 if (sym=="becomes")
					 getsym();    //如果的确为赋值号,获取下一个token,正常应为一个表达式 
                 else 
					 error(13);
				 expression(fsys);      //处理表达式
				    if (i!=0)
					{
					 gen("sto",lev-table[i].level,table[i].adr);
					}
				 break;
				 }

		case 2:  {
                 getsym();                //获得下一token,正常情况下应为左括号 
				 if  (sym!="lparen")      //如果read语句后跟的不是左括号 
					 error(34);
				 else 
					 while(sym!="comma")   //右括号为止
					 {
						 getsym();
                         if (sym=="ident")
							 i=position(id);
						 else 
							 i=0;
						 if(i==0)
						     error(35);
						 else
						 {
							 //with
							 gen("opr",0,16);
						     gen("sto",lev-table[i].level,table[i].adr);
						 }
						 getsym();
					 }
				 if  (sym!="rparen")      //如果不是右括号
				 {
					 error(33);
                     while(insym(sym,fsys))                    //依靠fsys集,找到下一个合法的token,恢复语法分析 
					 {
						 getsym();
                     }
				 }
				 else getsym();           //如果read语句正常结束,得到下一个token,一般为分号或end 
				 break;
				 }
		case 3:  {
			      getsym();            //获取下一token,正常应为左括号
                  if (sym=="lparen")
				  { 
                      while (sym!="comma")
					  {
						  getsym();
						  addsym(fsys,"rparen");
                          addsym(fsys,"comma");
						  expression(fsys);     //调用expression过程分析表达式,用于出错恢复的集合中加上右括号和逗号
						  gen("opr",0,14);        //生成14号指令:向屏幕输出
					  }
					  if(sym!="rparen")
                          error(35);
					  else getsym();           //正常情况下要获取下一个token,为后面准备好
				  }
				  gen("opr",0,15);                //生成一个15号指令,功能是输出一个换行
				  break;
				 }
		case 4:  {
			      getsym();                  //获取token,应是过程名型标识符
                  if(sym!="ident")
					  error(14);
				  else
					  i=position(id);
				      if(i==0)
						  error(11);
					  else 
					  {
						  //while()
						  {
							  if (table[i].kind=="procedur")     //如果这个标识符为一个过程名
								  gen("cal",lev-table[i].level,table[i].adr);              //生成cal目标代码,呼叫这个过程
							  else error(15);
						  }
                          getsym();
					  }
				  break;
				 }
		case 5:  {
			      getsym();                //获取一token应是一个逻辑表达式
                  addsym(fsys,"thensym");
                  addsym(fsys,"dosym");
				  condition(fsys);
                  if(sym=="then")
					  getsym();
				  else 
					  error(16);
				  cx1=cx;              //记下当前代码分配指针位置
				  gen("jpc",0,0);        //生成条件跳转指令,跳转位置暂时填0,分析完语句后再填写
				  statement();     //分析then后的语句
				  code[cx1].a=cx;      //上一行指令(cx1所指的)的跳转位置应为当前cx所指位置
				  break;
				 }
		case 6:  {
			      getsym();
				  addsym(fsys,"semicolon");
                  addsym(fsys,"endsym");
				  statement();                //对begin与end之间的语句进行分析处理
				  while((sym=="semicolon")||(sym=="statbegsys")) //如果分析完一句后遇到分号或语句开始符循环分析下一句语句
                  {
					  if(sym=="semicolon")  //如果语句是分号(可能是空语句)
						  getsym();
					  else 
						  error(10);                  //如果语句与语句间没有分号,出10号错
					      addsym(fsys,"semicolon");
                          addsym(fsys,"endsym");
				          statement();
				  }
                   if(sym=="endsym")        //如果语句全分析完了,应该遇到end 
                       getsym();
				   else error(17);    
				  break;
				 }
		case 7:  {
			       cx1=cx;                  //记下当前代码分配位置,这是while循环的开始位置
				   getsym();
				   addsym(fsys,"dosym");
				   condition(fsys);       //对这个逻辑表达式进行分析计算
				   cx2=cx;                //记下当前代码分配位置,这是while的do中的语句的开始位置
				   gen("jpc",0,0);          //生成条件跳转指令,跳转位置暂时填0
				   if(sym=="dosym")   //逻辑表达式后应为do语句
				        getsym();
				   else error(18);
				   statement();         //分析do后的语句块
				   gen("jmp",0,cx1);          //循环跳转到cx1位置,即再次进行逻辑判断
				   code[cx2].a=cx;          //把刚才填0的跳转位置改成当前位置,完成while语句的处理
				   break;
				 }
			}
	    //test(fsys, [ ], 19)      //

}

////////////////////////////////////////////////////////////////////////////
void constdeclaration() {			//常量声明处理过程
	if (sym=="ident") {
		getsym();
		if (sym=="becomes"||sym=="eql") {
			if (sym=="becomes") {	//如果是赋值号(常量生明中应该是等号)
				error(1);
			}
			getsym();
			if (sym=="number") {
				enter("constant");	//把这个常量登陆到符号表
				getsym();
			}
			else {
				error(2);			//如果等号后接的不是数字,抛出2号错误
			}
		}
		else {
			error(3);				//如果常量标识符后接的不是等号或赋值号,抛出3号错误
		}
	}
	else {
		error(4);					//如果常量声明过程遇到的第一个符号不为标识符,抛出4号错误
	}
}

void vardeclaration() {				//变量声明过程
	if (sym=="ident") {
		enter("variable");
		getsym();
	}
	else {							//如果变量声明过程遇到的第一个符号不是标识符,抛出4号错误
		error(4);
	}
}

void block(int lev,int tx,string fsys) {		//语法分析
	dx=3;				//地址指示器给出每层局部量当前已分配到的相对位置
	tx0=tx;				//初始符号表指针指向当前层的符号在符号表中的开始位置
	gen("jmp",0,0);		//产生一行跳转指令,跳转位置暂时未知填0
	if (lev>levmax) {	//如果当前过程嵌套层数大于最大允许的套层数
		error(32);
	}
	while (sym=="constsym"||sym=="varsym"||sym=="procsym") {	//常量说明,变量说明,过程说明
		if (sym=="constsym") {		//常量说明处理
			getsym();
			while (sym=="ident") {
				constdeclaration();
				while (sym=="comma") {	//如果遇到了逗号则反复声明下一个常量
					getsym();
					constdeclaration();
				}
				if (sym=="semicolon") {	//如果常量声明结束,应遇到分号
					getsym();
				}
				else {				
					error(5);		//如果常量声明语句结束后没有遇到分号则发出5号错误
				}

⌨️ 快捷键说明

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