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

📄 pl02.java

📁 一个pl0 的很好的编译程序,完整的实验,可以很好的了解pl0的编译过程,已经编译的整个过程
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
package pl0Compiler;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Scanner;


public class Pl02 {
	final int norw=18;      /*关键字个数*/
	final int txmax =100;   /*名字表容量*/
	final int nmax = 14;    /*number的最大位数*/
	final int al =10;       /*符号的最大长度*/
	final int amax=2047;    /*地址上界*/
	final int levmax =3;    /*最大允许过程嵌套声明层数[0,lexmax]*/
	final int cxmax=200;     /*最多的虚拟机代码数*/
    final int 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,elsesym,forsym,tosym,downtosym,
	 returnsym,pluseql,minuseql,dplus,dminus
};
final static int symnum=32;
/*-------类型------*/
enum object{
	   constant,
	   variable,
	   procedur,
	};
/*----目标指令-------*/
enum fct{
	lit, opr,  lod,  sto,  cal,  inte,  jmp,  jpc,
};
final int fctnum=8;
/*--------------*/
class instruction
{
   fct f;
  int l;
  int a;
};
boolean tableswitch=true;
boolean listswitch=true;
char ch;
symbol sym;
String id="";
int  num;
int cc,ll;
int cx;
char[] line=new char[81];
//String line=new String();
//char[] a=new char[al+1];
instruction[] code=new instruction[cxmax];
String[] word=new String[norw];
symbol[] wsym=new symbol[norw];
symbol[] ssym=new symbol[256];
String[] mnemonic=new String[fctnum];
boolean[] declbegsys=new boolean[symnum];
boolean[] statbegsys=new boolean[symnum];
boolean[] facbegsys=new boolean[symnum];
/*------------------------------*/
class tablestruct
{
  String name;            /*名字*/
   object kind;                         /*类型:const,var,array or procedure*/
   int val;                             /*数值,仅const使用*/
   int level;                           /*所处层,仅const不使用*/
   int adr=0;                             /*地址,仅const不使用*/
   int size;                            /*需要分配的数据区空间,仅procedure使用*/
};
tablestruct[] table=new tablestruct[txmax];             /*名字表*/

File SourceFile;
RandomAccessFile randomAFile; 
String SourceFileName="e:/pl0_1.txt";//"E:/三年级课程/编译原理/PL0源码C语言版/pl0.txt";//"E:/三年级课程/编译原理/PL0源码C语言版/pl0.txt";

int err;                                /*错误计数器*/

public static void  main(String args[])
{
	boolean[] nxtlev=new boolean[symnum];
	Pl02 pl=new Pl02();
                         
	pl.init();                                          /*初始化*/

	pl.err=0;
	pl.cc=0;
	pl.cx=0;
	pl.ll=0;
	pl.ch=' ';

	if(-1!=pl.getsym()) {
		nxtlev=pl.addset(nxtlev,pl.declbegsys,pl.statbegsys,symnum);
			
		nxtlev[symbol.period.ordinal()]=true;    
		if(1==pl.block(0,0,nxtlev))
			return;			/*调用编译程序*/
		
		if(pl.sym!=symbol.period)
		{
			pl.error(9);
		}
		if(pl.err==0)
		{
			
			pl.interpret();
		
		}
		else
		{
			System.out.printf("Errors in pl/0 program");
		}
	}
		else
		{
			System.out.printf("Can't open file! \n");
		}

}


void init()
{
	SourceFile = new File(SourceFileName);
	try {
		randomAFile = new RandomAccessFile(this.SourceFile, "r");
	} catch (FileNotFoundException e) {
			e.printStackTrace();
	}
	for(int j=0;j<table.length;j++)
	    table[j]=new tablestruct();
     for(int j=0;j<code.length;j++)
	    	code[j]=new instruction();
	int i;
	for(i=0;i<=255;i++)
	{
		ssym[i]=symbol.nul;
	}
	ssym['+']=symbol.plus;
	ssym['-']=symbol.minus;
	ssym['*']=symbol.times;
	ssym['/']=symbol.slash;
	ssym['(']=symbol.lparen;
	ssym[')']=symbol.rparen;
	ssym['=']=symbol.eql;
	ssym[',']=symbol.comma;
	ssym['.']=symbol.period;
   // ssym['#']=symbol.neq;
	ssym[';']=symbol.semicolon;
	/*设置保留字名字,按照字母顺序,便于折半查找*/
	 word[0]="begin" ;
	 word[1]="call" ;
	 word[2]="const" ;
	 word[3]="do" ;
	 word[4]="downto" ;
	 word[5]="else" ;
	 word[6]="end" ;
	 word[7]="for" ;
	 word[8]="if" ;
	 word[9]="odd" ;
	 word[10]="procedure" ;
	 word[11]="read" ;
	 word[12]="return" ;
	 word[13]="then" ;
	 word[14]="to" ;
	 word[15]="var" ;
	 word[16]="while" ;
	 word[17]="write" ;

	
	/*设置保留字符号*/
	wsym[0]=symbol.beginsym;
	wsym[1]=symbol.callsym;
	wsym[2]=symbol.constsym;
	wsym[3]=symbol.dosym;
	wsym[4]=symbol.downtosym;
	wsym[5]=symbol.elsesym;
	wsym[6]=symbol.endsym;
	wsym[7]=symbol.forsym;
	wsym[8]=symbol.ifsym;
	wsym[9]=symbol.oddsym;
	wsym[10]=symbol.procsym;
	wsym[11]=symbol.readsym;
	wsym[12]=symbol.returnsym;
	wsym[13]=symbol.thensym;
	wsym[14]=symbol.tosym;
	wsym[15]=symbol.varsym;
	wsym[16]=symbol.whilesym;
	wsym[17]=symbol.writesym;
	/*设置指令名称*/
	 mnemonic[fct.lit.ordinal()]="lit";
	 mnemonic[fct.opr.ordinal()]="opr";
	 mnemonic[fct.lod.ordinal()]="lod";
	 mnemonic[fct.sto.ordinal()]="sto";
	 mnemonic[fct.cal.ordinal()]="cal";
	 mnemonic[fct.inte.ordinal()]="int";
	 mnemonic[fct.jmp.ordinal()]="jmp";
	 mnemonic[fct.jpc.ordinal()]="jpc";

	/*设置符号集*/
	for(i=0;i<symnum;i++)
	{
		declbegsys[i]=false;
		statbegsys[i]=false;
		facbegsys[i]=false;
	}

	/*设置声明开始符号集*/
	declbegsys[symbol.constsym.ordinal()]=true;
	declbegsys[symbol.varsym.ordinal()]=true;
	declbegsys[symbol.procsym.ordinal()]=true;
	/*设置语句开始符号集*/
	statbegsys[symbol.beginsym.ordinal()]=true;
	statbegsys[symbol.callsym.ordinal()]=true;
	statbegsys[symbol.ifsym.ordinal()]=true;
	statbegsys[symbol.whilesym.ordinal()]=true;
	/*设置因子开始符号集*/
	facbegsys[symbol.ident.ordinal()]=true;
	facbegsys[symbol.number.ordinal()]=true;
	facbegsys[symbol.lparen.ordinal()]=true;
	
}
/*
 *用数组实现集合的集合运算
 */
boolean inset(int e,boolean[] s)
{
    return s[e];
}
boolean[] addset(boolean[] sr,boolean[] s1,boolean[] s2,int n)
{
    int i;
    for(i=0;i<n;i++)
    {
       sr[i]=s1[i]||s2[i];  
    }
    return sr;
}

/*
 *出错处理,打印出错位置和错误编码
 */
void error(int n)
 
{
	char[] space=new char[81];
	for(int i=0;i<space.length;i++){
		space[i]=32;
	}
	System.out.printf("----------%c\n",ch);
	space[cc-1]=0;//出错时当前符号已经读完,所以cc-1
	System.out.println("****"+String.valueOf(space)+n);
	err++;
	
}
public  String contact(String TOKEN, char CHAR) {
    String tmpS = TOKEN + String.valueOf(CHAR);
    TOKEN = tmpS;
    return TOKEN;
  }
/*
 *  漏掉空格,读取一个字符
 *
 *  每次读一行,存入line缓冲区,line被getsym取空后再读一行
 *
 *  被函数getsym调用
 */
int getch()
{   if(cc==ll){
	ll=0;
	cc=0;
	System.out.printf("%d ",cx );
	ch=' ';
	while(ch!=10){
		try{
			ch=(char) randomAFile.readByte();
		} catch (IOException e) {
			line[ll]=0;
			break;
		}
	System.out.printf("%c",ch);
	line[ll]=ch;
	ll++;
	}
	System.out.printf("\n");
}
ch=line[cc];
cc++;
	return 0;
}

/*词法分析,获取一个符号
 */

int getsym()
{
	while(ch==' '|(byte)ch==13|(byte)ch==10|ch==9)
		getch();
	
	int i,j,k;
	if(ch>='a'&&ch<='z')
	{ String s="";
		k=0;
		do{
			if(k<al)
			{   s=contact(s,ch);
				k++;
			}
			getch(); 
		}while(ch>='a'&&ch<='z'||ch>='0'&&ch<='9');
		id=s;
		i=0;
		j=norw-1;
		do{
			k=(i+j)/2;
			if(id.compareToIgnoreCase(word[k])<=0)
			{
				j=k-1;
			}
			if(id.compareToIgnoreCase(word[k])>=0)
			{
				i=k+1;
			}

		}while(i<=j);
		if(i-1>j)
			sym=wsym[k];
		else
			sym=symbol.ident;
		
	}
	else if(ch>='0'&&ch<='9')
		{
			k=0;
			num=0;
			sym=symbol.number;
			do{
				num=10*num+ch-'0';
				k++;
				getch();
			}while(ch>='0'&&ch<='9'); /*获取数字的值*/
			k--;
			if(k>nmax)
			{
				error(30);
			}
		}
		else if(ch==':')             /*检测赋值符号*/
			{
				getch();
				if(ch=='=')
				{
					sym=symbol.becomes;
					getch();
				}
				else
				{
					sym=symbol.nul;            /*不能识别的符号*/
				}
			}
			else if(ch=='<')         /*检测小于或小于等于符号*/
				{
					getch();
					if(ch=='=')
					{
						sym=symbol.leq;
						getch();
					}
					else if(ch=='>')
						{ 
							sym=symbol.neq;
							getch();
						}
						else sym=symbol.lss;
				}
				else if(ch=='>')          /*检测大于或大于等于符号*/
					{
						getch();
						if(ch=='=')
						{
							sym=symbol.geq;
							getch();
						}
						else
						{
						    sym=symbol.gtr;
						}
					}
					else if(ch=='+')
						{
							getch();
							if(ch=='=')
							{
								sym=symbol.pluseql;
								getch();
							}
							else if(ch=='+')
								{
									sym=symbol.dplus;
									getch();
								}
								
							else sym=ssym['+'];

						}
						else if(ch=='-')
							{
								getch();
								if(ch=='=')
								{
									sym=symbol.minuseql;
									getch();
								}
								else if(ch=='-')
									{
										sym=symbol.dminus;
										getch();
									}
								else sym=ssym['-'];
							}
						else
						{
							sym=ssym[ch];/* 当符号不满足上述条件时,全部按照单字符号处理*/
						   if(sym!=symbol.period)
							{
								getch();
							}
						}
		return 0;
}

/*
*生成虚拟机代码
*x:instruction.f;
*y:instruction.l;
*z:instruction.a;
*/
int gen( fct x,int y,int z)
{
	if(cx>=cxmax)
	{
		System.out.printf("Program too long"); /*程序过长*/
		return -1;
	}
	code[cx].f=x;
	code[cx].l=y;
	code[cx].a=z;
	cx++;
	return 0;
}

/*
*测试当前符号是否合法
*
*在某一部分(如一条语句,一个表达式)将要结束时时我们希望下一个符号属于某集合
*(该部分的后跟符号) test 负责这项检测,并且负责当检测不通过时的补救措施
*程序在需要检测时指定当前需要的符号集合和补救用的集合(如之前未完成部分的后跟
*符号),以及不通过时的错误号
*
*S1:我们需要的符号
*s2:如果不是我们需要的,则需要一个补救用的集合
*n:错误号
*/


int test(boolean[] s1,boolean[] s2,int n)
{
    if(! inset(sym.ordinal(),s1))
    {
		error(n);
		/*当检测不通过时,不停获取符号,直到它属于需要的集合或补救的集合*/
		while((! inset(sym.ordinal(),s1))&&(! inset(sym.ordinal(),s2)))
		{
			getsym(); 
		}
    }
    return 0;
}

/*
 *编译程序主体
 *lev:当前分程序所在层
 *tx:名字表当前尾指针
 *fsys:当前模块后跟符号集合
 */
int block(int lev,int tx,boolean[] fsys)
{
    int i;
    int dx;                         /*名字分配到的相对地址*/
    int tx0;                        /*保留初始tx*/

⌨️ 快捷键说明

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