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

📄 pl0.java

📁 编译原理课程设计 PL0编译器 java版本
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
				errorNumber++;new erro(word.getLineNum(),3);
			}			
		}
		else//如果常量声明过程中遇到的第一个字符不是标识符,调用4号错误
		{
			errorNumber++;new erro(word.getLineNum(),4);
		}
	}
	public  void vardeclaration()    //变量声明的方法
	{
	  if(word.getSym().equals("ident"))
		{
			id=word.getNam();
			enter("variable");//调用符号表注册方法 进行变量的注册
			word=CiFa.GetToken();
		}
		else//如果变量声明过程中遇到的第一个字符不是标识符,调用4号错误
		{
			errorNumber++;new erro(word.getLineNum(),4);
	  }
	}
	public void enter(String k) //注册名字表
	{                           //k中保存的是传过来的 string
		if(k.equals("constant"))
		{//如果是常量,则要判断此常量的赋值是否大于整数的最大允许值2047
			int num=Integer.parseInt(word.getNam());
			 if(num>2047)
			                 {
			                 	nameArray.addElement(new nameClass(id,k,0,0,0));
			                  new	erro(word.getLineNum(),31);//若整数越界,抛出31号错误,并将其赋为0,继续进行分析
			                 }else//若整数没有越界,则给nameArray增加一个nameClass对象
			                    nameArray.addElement(new nameClass(id,k,num,0,0));
		}
		else if(k.equals("variable"))
		{
			nameArray.addElement(new nameClass(id,k,0,lev,dx));
		  dx=dx+1;
		}
		else if(k.equals("procedure"))
		{
			nameArray.addElement(new nameClass(id,k,0,lev,0));
		}
	}//符号表注册完成
	public int position(String id)  //查找名字表
	{
		int i=0;
		while(i<nameArray.size()&&(!((nameClass)nameArray.get(i)).getNam().equals(id)))
		{
			i++;	
		}
		if(i>=nameArray.size())
	  {  
		  return  -1;
		}//如果没有找到,则返回负值	   
		else 
		{  
			return  i;
		}
	}
	public void statement1()//语句的分析处理   
	{
		int i;
	  int  cx1;
		int  cx2;
		if(word.getSym().equals("ident")) //所谓语句可能是赋值语句,以标识符开头;
		{
			i=position(word.getNam());   //在符号表中找到该标识符所在位置;
			if(i==-1)   //如果返回的i为负值,则表示没有找到;抛出11号错误
			  { errorNumber++;new erro(word.getLineNum(),11);}
			else  if(!((nameClass)nameArray.get(i)).getKind().equals("variable"))//如果在符号表中找到了,但是该标识符不是变量名,则抛出12号错误
			{
				errorNumber++;new erro(word.getLineNum(),12);
				i=-1;//并将i置为-1做为错误的标志;
			}
			word=CiFa.GetToken();  //继续读取下一个token,正常应该是赋值符号
			if(word.getSym().equals("becomes"))
			{
				word=CiFa.GetToken();//如果是赋值符号,则继续读取一个token,正常应该是一个表达式;
			}
			else
			{
			 errorNumber++;new erro(word.getLineNum(),13);//如果不是赋值符号,则抛出13号错误
			}
			expression();  //进行表达式的处理;
			if(i!=-1)//如果i不是负值,则表示未曾出错,i所表示的是当前语句左边标识符在符号表中的位置;
			{//生成一条把表达式的值写往指定内存的代码;
				pcodeArray.addElement(new pcode("sto",lev-((nameClass)nameArray.get(i)).getLev(),((nameClass)nameArray.get(i)).getAdr()));
			}
		}
		else if(word.getSym().equals("callsym"))//如果遇到了call语句
		{
			word=CiFa.GetToken();//读取一个token,正常应该是一个过程名型的标识符
			if(!word.getSym().equals("ident"))//如果不是标识符,抛出14号错误
			{
				errorNumber++;new erro(word.getLineNum(),14);
			}
			else
			{
				i=position(word.getNam());//查找符号表
				if(i==-1)
				{errorNumber++;new erro(word.getLineNum(),11);}//如果没有找到,抛出11号错误
				else if(((nameClass)nameArray.get(i)).getKind().equals("procedure"))
				{//生成call指令,call这个过程
					pcodeArray.addElement(new pcode("cal",lev-((nameClass)nameArray.get(i)).getLev(),((nameClass)nameArray.get(i+1)).getAdr()));
				}
				else  {errorNumber++;new erro(word.getLineNum(),15);}//如果找到的不是过程名,抛出15号错误
				word=CiFa.GetToken();
			}
		}
		else if(word.getSym().equals("ifsym"))//如果是if语句
		{
			word=CiFa.GetToken();//if后正常是条件,所以执行condition函数
			condition();
			if(word.getSym().equals("thensym"))
			 { word=CiFa.GetToken();}
			else  { errorNumber++;new erro(word.getLineNum(),16);}//如果if后不是then 则抛出16号错误!
			cx=pcodeArray.size();
			cx1=cx;
			pcodeArray.addElement(new pcode("jpc",0,0));
			statement1();
			((pcode)pcodeArray.get(cx1)).setA(pcodeArray.size());
			
		}
		else if(word.getSym().equals("beginsym"))
		{
			word=CiFa.GetToken();
			statement1();
			while(word.getSym().equals("semicolon")||word.getSym().equals("beginsym")||word.getSym().equals("callsym")||word.getSym().equals("ifsym")||word.getSym().equals("whilesym"))
			{
				if(word.getSym().equals("semicolon"))  
				{word=CiFa.GetToken();}
				else  {errorNumber++;new erro(word.getLineNum(),10);}
				statement1();
			}
			if(word.getSym().equals("endsym"))
			{
				word=CiFa.GetToken();
			}
			else  { errorNumber++;new erro(word.getLineNum(),17);}
		}
		else  if(word.getSym().equals("whilesym"))
		{
			cx=pcodeArray.size();
			cx1=cx;//记录当前代码分配位置,这是while循环的开始位置
			word=CiFa.GetToken();//读取token,应该是一个条件表达式
			condition();
			cx=pcodeArray.size();
			cx2=cx;//记录当天代码位置,这是while循环的do中的语句的开始位置
			pcodeArray.addElement(new pcode("jpc",0,0));//生成条件跳转指令,跳转位置暂时填0
			if(word.getSym().equals("dosym"))//   判断是否是do,否则抛出18号错误
			{word=CiFa.GetToken();}
			else  { errorNumber++;new erro(word.getLineNum(),18);}
			statement1();//开始分析do后的语句块
			pcodeArray.addElement(new pcode("jmp",0,cx1));//跳转到cx1处,即再次进行判断是否进行循环
			((pcode)pcodeArray.get(cx2)).setA(pcodeArray.size());//把刚才跳转暂时填0的位置改成当前位置,完成对循环的处理
		}
		else  if(word.getSym().equals("readsym"))
		{
			word=CiFa.GetToken();//如果遇到了“读”语句块,则继续读取token,应该是左括号
			if(word.getSym().equals("lparen"))
			{				
					word=CiFa.GetToken();
					if(word.getSym().equals("ident"))
					{
						i=position(word.getNam());
						if(i==-1){ errorNumber++;new erro(word.getLineNum(),11);}
						else
						{
							pcodeArray.addElement(new pcode("opr",0,16));//生成16号读指令,从键盘读取数字
							pcodeArray.addElement(new pcode("sto",lev-((nameClass)nameArray.get(i)).getLev(),((nameClass)nameArray.get(i)).getAdr()));//生成sto指令,存入指定变量
						}
					}
					word=CiFa.GetToken();
				
				while(word.getSym().equals("comma"))//循环得到read语句的参数,直到该参数后不是逗号为止
				{
					word=CiFa.GetToken();
					if(word.getSym().equals("ident"))
					{
						i=position(word.getNam());
						if(i==-1){ errorNumber++;new erro(word.getLineNum(),11);}
						else
						{
							pcodeArray.addElement(new pcode("opr",0,16));
							pcodeArray.addElement(new pcode("sto",lev-((nameClass)nameArray.get(i)).getLev(),((nameClass)nameArray.get(i)).getAdr()));
						}
					}
					word=CiFa.GetToken();
				}
				if(!word.getSym().equals("rparen"))
				{errorNumber++;new erro(word.getLineNum(),9);}//如果不是预想的右括号,抛出9号错误
			}
			else{ errorNumber++;new erro(word.getLineNum(),0);}//如果不是左括号,抛出0号错误
			word=CiFa.GetToken();
		}
		else if(word.getSym().equals("writesym"))
		{
			word=CiFa.GetToken();
			if(word.getSym().equals("lparen"))
			{
					word=CiFa.GetToken();
					expression();
					pcodeArray.addElement(new pcode("opr",0,14));	
				while(word.getSym().equals("comma"))
					{
					word=CiFa.GetToken();
					expression();
					pcodeArray.addElement(new pcode("opr",0,14));	
				}
				
				if(!word.getSym().equals("rparen")) 
				   {errorNumber++;new erro(word.getLineNum(),9);}
				else  
				  { word=CiFa.GetToken();}
			}
			pcodeArray.addElement(new pcode("opr",0,15));	
		}
	}
	public void condition()  //条件分析;
	{
		String relop=null;
		if(word.getSym().equals("oddsym"))   //如果是一元运算符
		{
			word=CiFa.GetToken();
			expression();//对一元运算的表达式进行分析
			pcodeArray.addElement(new pcode("opr",0,6));//生成奇偶判断指令
		}
		else                               //不是一元运算符则是2元运算符 
		{
			expression();//对左边的表达式进行分析
			relop=word.getSym();//把2元运算符保存起来
			word=CiFa.GetToken();
			expression();//对右边的表达式进行分析     然后根据刚才保存的运算符,生成相应判断指令
			if(relop.equals("eql"))
			{pcodeArray.addElement(new pcode("opr",0,8));}
			else if(relop.equals("neq"))
			{pcodeArray.addElement(new pcode("opr",0,9));}
			else if(relop.equals("lss"))
			{pcodeArray.addElement(new pcode("opr",0,10));}
			else if(relop.equals("geq"))
			{pcodeArray.addElement(new pcode("opr",0,11));}
			else if(relop.equals("gtr"))
			{ pcodeArray.addElement(new pcode("opr",0,12));}
			else if(relop.equals("leg"))
			{pcodeArray.addElement(new pcode("opr",0,13));}
			else  
			{ 
				System.out.println(word.getNam()+"   "+relop);
				errorNumber++;new erro(word.getLineNum(),20);}//如果刚才保存的不是逻辑运算符,则抛出20号错误
		}
	}//条件分析完毕
	public  void expression()  //表达式的处理
	{
		String addop=null; //保存表达式开头的符号  用于表示正负
		if(word.getSym().equals("plus")||word.getSym().equals("minus"))
		{  
			addop=word.getSym();//把正负号保存在string类型的addop中,继续读取一个token,正常应该为表达式的一个项
			word=CiFa.GetToken();
			term();//进行项的分析
			if(addop.equals("minus")) //如果保存下来的是个负号,则生成一条1号指令,取反运算
			{pcodeArray.addElement(new pcode("opr",0,1));}
		}
		else  //如果不是正负号开头,就应该是一个表达式的项开头,直接进行项的分析
		{		
			term(); 
		}
		while(word.getSym().equals("plus")||word.getSym().equals("minus"))//项后应该应该是加运算或者减法运算
		{
			addop=word.getSym();//把运算符保存在addop中
			word=CiFa.GetToken();
			term();//分析项
			if(addop.equals("plus")) //项分析完毕后,如果刚才保存的是加号,则生成加法指令
			{pcodeArray.addElement(new pcode("opr",0,2));}
			else                                               //否则生成减法指令
			{ pcodeArray.addElement(new pcode("opr",0,3));}
		}
		
	}//表达式分析完毕
	public  void term()//项的处理
	{
		String mulop=null;
		factor();//每个项都是由一个因子开头,所以直接调用因子分析方法
		while(word.getSym().equals("times")||word.getSym().equals("slash"))//因子后应该遇到乘号或是除号
		{
			mulop=word.getSym();  //把运算符保存在mulop中(乘法或是除法)
			word=CiFa.GetToken();
			factor();//运算符后应该是一个因子,进行因子分析
			if(mulop.equals("times")) //如果刚才保存的运算符为乘号则生成opr 4号乘法指令,
			{  pcodeArray.addElement(new pcode("opr",0,4));}
			else  //如果刚才保存的不是乘号,则生成除法运算指令
			{ pcodeArray.addElement(new pcode("opr",0,5));}
		}
	}//项分析完毕
	public void factor()  //因子的分析处理;
	{
		int i;
		while(word.getSym().equals("ident")||word.getSym().equals("number")||word.getSym().equals("lqaren"))//循环处理因子
		{
			if(word.getSym().equals("ident"))//如果遇到的是标识符,则查符号表
			{
				i=position(word.getNam());
				if(i==-1)   //如果查符号表后返回负值,则表示没有找到,抛出11号错误
				{errorNumber++;new erro(word.getLineNum(),11);}
				//如果返回的不是负值,则表示在符号表中的找到了该标识符,getKind返回该标识符的类型
				else  if(((nameClass)nameArray.get(i)).getKind().equals("constant"))	
				//如果该标识符为常量,则生成lit指令,把val放到栈顶
				{pcodeArray.addElement(new pcode("lit",0,((nameClass)nameArray.get(i)).getVal()));	
					word=CiFa.GetToken();}
				else  if(((nameClass)nameArray.get(i)).getKind().equals("variable"))
				{ //如果该标识符为变量,则生成lod指令,把变量放到栈顶
					pcodeArray.addElement(new pcode("lod",lev-((nameClass)nameArray.get(i)).getLev(),((nameClass)nameArray.get(i)).getAdr()));	
					word=CiFa.GetToken();
				}
			  else  if(((nameClass)nameArray.get(i)).getKind().equals("procedure"))
			  {//如果该标识符为过程名,出错,抛出21号错误
			  	errorNumber++;new erro(word.getLineNum(),21); 
			  	word=CiFa.GetToken();}				
				}
			  else if(word.getSym().equals("number"))//如果因子分析时遇到的为数字
			  {
			  	int num=Integer.parseInt(word.getNam());
				  if(num>2047)//判断数字大小超过允许最大值amax
				  {
					  errorNumber++;new erro(word.getLineNum(),7);//如果数字越界,则抛出7号错误,并把数字按0处理;
					  num=0;			
				  }
				  pcodeArray.addElement(new pcode("lit",0,num));//生成lit指令,把这个数值字面常量放到栈顶
					word=CiFa.GetToken();
			  }
			  else if(word.getSym().equals("lqaren"))//如果因子分析遇到的为左括号
			  {
			  	word=CiFa.GetToken();//继续读取一个token
			  	expression();      //递归调用表达式分析
				  if(word.getSym().equals("rqaren"))//表达式分析完后,应该遇到右括号
				  { word=CiFa.GetToken();}
				  else  { errorNumber++;new erro(word.getLineNum(),22);}//如果表达式分析完后,没有遇到右括号,则抛出22号错误
			   }
		 }
	}	//因子分析完毕
	public void printName()                  //这段代码没用,仅仅是用来查看符号表内容的
	{
		 for(int t=0;t<nameArray.size();t++)//测试用
	 {
		 	nameClass name=(nameClass)nameArray.get(t);
	   System.out.println("符号表内容NAME "+name.getNam()+"  KIND "+name.getKind()+"  VAL "+name.getVal()+"  LEVL "+name.getLev()+"  ADR "+name.getAdr());
	 }

⌨️ 快捷键说明

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