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

📄 pl0.java

📁 pl0的好的编译程序,通过这个程序可以很好的了解编译的过程,掌握编译器的运行原理!
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package pl0Compiler;

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


public class Pl0 {
	final int tableMax =100;   
	final int numLength = 14;   
	final int identLength =10;    
	final int levMax =3;    
	final int codeMax=200;     
    final int stackSize=500;
    final int symnum=32;
enum Symbol{
	 nul,    ident,     number,     plus,     minus,
	 multiply,   divide,   oddsym,   eql,     neq,
	 lss,     leq,      gtr,     geq,     lparen,
	 rparen,  comma,   semicolon,period,  assign,
	 beginsym, endsym, ifsym,    thensym,  whilesym,
	 writesym, readsym,  dosym,  callsym,  constsym,
	 varsym,  proceduresym	
};
enum Object{
	   constant,
	   variable,
	   procedure,
	};
enum Function{
	lit, opr,  lod,  sto,  cal,  inte,  jmp,  jpc,
};
class Instruction
{
  Function f;
  int l;//层差,标识符引用层减去定义层
  int a;
};
class TableStruct
{
   String name;          
   Object kind;                      
   int val;                            
   int level;                         
   int adr;                         
   int size;                          
};
char ch;
Symbol sym;
String token="";
int  num;
int cc,ll;
int cx;
char[] line=new char[81];
Instruction[] code=new Instruction[codeMax];
Symbol[] kwsym={Symbol.beginsym,Symbol.callsym,Symbol.constsym,Symbol.dosym,Symbol.endsym,Symbol.ifsym,
		Symbol.oddsym,Symbol.proceduresym,Symbol.readsym,Symbol.thensym,Symbol.varsym,Symbol.whilesym,Symbol.writesym};
TableStruct[] table=new TableStruct[tableMax];            
File SourceFile;
RandomAccessFile randomAFile; 
String SourceFileName="E:/三年级课程/编译原理/编译原理实验/pl02.txt";//"E:/三年级课程/编译原理/PL0源码C语言版/pl0.txt";
int err;                              

public static void  main(String args[])
{
	Pl0 pl=new Pl0();
   	pl.init();                                         
    pl.getsym();
	pl.block(0,0);			
	if(pl.sym!=Symbol.period)
			pl.error(9);
		System.out.println("The ultimate code is following:");
	pl.listcode(0);
	if(pl.err==0)
    	pl.interpret();
	else
	   System.out.printf("Errors in pl/0 program");

}


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();
     err=0;
     cc=0;
     cx=0;
     ll=0;
     ch=' ';

}
void error(int n)
 
{
	
	System.out.printf("----------%c\n",ch);
	
	System.out.println("**********"+n);
	err++;
	
}
String contact(String token, char ch) {
	token= token + String.valueOf(ch);
      return token;
  }

void 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++;

}
void getsym()
{
	while(ch==' '|(byte)ch==13|(byte)ch==10|ch==9)
		getch();
	
	int i,k;
	if(ch>='a'&&ch<='z')
	{ String s="";
		k=0;
		do{
			if(k<identLength)
			{   s=contact(s,ch);
				k++;
			}
			getch(); 
		}while(ch>='a'&&ch<='z'||ch>='0'&&ch<='9');
		token=s;
		s=s+"sym";
		for(i=0;i<kwsym.length;i++){
			
			if(s.equalsIgnoreCase(kwsym[i].name()))
			{    sym=kwsym[i];
        		break;
			}
		}
			
			if(i==kwsym.length)
				sym=Symbol.ident;

	}
	else if(ch>='0'&&ch<='9')
		{  String s="";
			num=0;
			sym=Symbol.number;
			do{
				s=contact(s,ch);
				getch();
			}while(ch>='0'&&ch<='9'); 
			num=Integer.parseInt(s);
			if(s.length()>numLength)
			{
				error(30);
			}
		}
	else if(ch==':')             
	{
		getch();
	if(ch=='=')
	{
		sym=Symbol.assign;
		getch();
		}
	else
		sym=Symbol.nul;           
	}
	else if(ch=='<')         
	{     getch();
		if(ch=='=')
		{
			sym=Symbol.leq;
			getch();
		}
					
		else sym=Symbol.lss;
	}
	else if(ch=='>')          
	{
		getch();
		if(ch=='=')	
		{
			sym=Symbol.geq;
			getch();
			}
		else
		{
			sym=Symbol.gtr;
		}
	}
	else
	{  switch(ch){
	case '+': 
		sym=Symbol.plus;
		break;
	case '-': 
		sym=Symbol.minus;
		break;
	case '*':
		sym=Symbol.multiply;
		break;
	case '/':
		sym=Symbol.divide;
		break;
	case '(': 
		sym=Symbol.lparen;
		break;
	case ')':
		sym=Symbol.rparen;
		break;
	case '=': 
		sym=Symbol.eql;
		break;
	case ',':
		sym=Symbol.comma;
		break;
	case '.': 
		sym=Symbol.period;
		break;
    case '#':
    	sym=Symbol.neq;
    	break;
	case ';': 
		sym=Symbol.semicolon;
		break;
	  }
	if(sym!=Symbol.period)
			getch();
    }
		
}

void gen(Function x,int y,int z)
{
	if(cx>=codeMax)
	{
		System.out.printf("Program is too long!"); 
		System.exit(0);
	}
	code[cx].f=x;
	code[cx].l=y;
	code[cx].a=z;
	cx++;
	
}


void block(int lev,int tx)
{
	
    int i;
    int dx; //名字分配到的相对地址
    int tx0; //保留本过程名在名字表中的位置
    int cx0; //保留本过程目标代码的起始位置
 
    int[] x=new int[2];
    dx=3;    //为该过程变量分配存储空间的起始位置,也就是相对基地址的偏移量
    tx0=tx;    //保留当前table表指针值,是该过程名在table表中的位置
    table[tx].adr=cx;//保留当前code指针值到过程名的adr域
    gen(Function.jmp,0,0);//生成转向过程体入口的指令,地址待回填
    if(lev > levMax)
    {
		error(32);                                                                                                                                         
    }
    do{
        if(sym==Symbol.constsym)        
        {
			getsym();
			do{
                x=constdeclaration(tx,lev,dx);  
                tx=x[0];
                dx=x[1];
                while(sym==Symbol.comma)
                {
                   getsym();
                   x=constdeclaration(tx,lev,dx);
                   tx=x[0];
                   dx=x[1];
                }
                if(sym==Symbol.semicolon)
                    getsym();
			    else
					error(5); /*漏掉了逗号或者分号*/
				
			}while(sym==Symbol.ident);
		}
        if(sym==Symbol.varsym)
		{
			getsym();
			do{
				x=vardeclaration(tx,lev,dx);
				tx=x[0];
				dx=x[1];
				while(sym==Symbol.comma)
				{
					getsym();
					x=vardeclaration(tx,lev,dx);
					tx=x[0];
					dx=x[1];
				}
				if(sym==Symbol.semicolon)
					getsym();
				
				else
				    error(5);
				
			}while(sym==Symbol.ident);
		}
		while(sym==Symbol.proceduresym)     
		{
			getsym();
			if(sym==Symbol.ident)
			{
				x=enter(Object.procedure,tx,lev,dx);
				tx=x[0];
				dx=x[1];
				getsym();
			}
			else
			   error(4);//procedure后应为标识符
			
			if(sym==Symbol.semicolon)
				getsym();
			
			else
				error(5);//漏掉了分号
				
			block(lev+1,tx);//递归进入分程序
			
		   if(sym==Symbol.semicolon)
             getsym();
           else
                error(5); /*漏掉了分号*/
            
		}
		
    }while(sym==Symbol.constsym|sym==Symbol.varsym|sym==Symbol.proceduresym);              
    
    code[table[tx0].adr].a=cx;//回填过程入口地址到code的a中
    table[tx0].adr=cx; //记录过程在code的入口到table中的adr域

    table[tx0].size=dx;//过程占的空间填 写在table中,声明部分中每增加一条声明都会给dx增加1,声明部分已经结束,dx就是当前过程数据的size
        
    cx0=cx;//保留过程在code中的入口地址,打印目标代码用
    gen(Function.inte,0,dx);//生成过程入口指令
 
    System.out.print("TABLE:\n");
    if(tx0+1>tx)
        {
			System.out.printf("NULL\n");
        }
        for(i=tx0+1;i<=tx;i++)
        {
            switch(table[i].kind)
            {
                case constant:
                	System.out.println(i+" NAME:"+table[i].name+"  KIND:"+
                			Object.constant+"   VALUE:"+table[i].val);
					break;
                case variable:
                	System.out.println(i+" NAME:"+table[i].name+"  KIND:"+
                			Object.variable+"   LEVEL:"+table[i].level+"  ADDRESS:"+table[i].adr);
                               break;
                case procedure:
                	System.out.println(i+" NAME:"+table[i].name+"  KIND:"+
                			Object.procedure+"  LEVEL:"+table[i].level+"  ADDRESS:"+table[i].adr+"  SIZE:"+table[i].size);
					break;
			}
		}
  
        
	tx=statement(tx,lev);
	gen(Function.opr,0,0); //过程出口都要释放数据段
	listcode(cx0);                
	
}
int[] enter (Object k,int ptx,int lev, int pdx)
{ int[]x=new int[2];
	ptx++;
	table[ptx].name=token;      
	table[ptx].kind=k;
	switch(k)
	{
		case constant:                     
			table[ptx].val=num;
			break;
		case variable:                    
			table[ptx].level=lev;
			table[ptx].adr=pdx;
			pdx++;
			break;                        
		case procedure:
			table[ptx].level=lev;
			break;
	}
	x[0]=ptx;
	x[1]=pdx;
	return x;

}

int position(String idt,int  tx)
{
	int i;
	
	table[0].name=idt;
	i=tx;
	while(table[i].name.compareToIgnoreCase(idt)!=0)
		i--;
	return i;
}

int[] constdeclaration(int ptx,int lev,int  pdx)
{ int[]x=new int[2];
	if(sym==Symbol.ident)
	{
		getsym();
		if(sym==Symbol.eql )
		{			
			getsym();
			if(sym==Symbol.number)
			{
				x=enter(Object.constant,ptx,lev,pdx);
				ptx=x[0];
				pdx=x[1];
				getsym();
			}
			else
			   error(2);                 
			         
		}
		else
			error(3);                       
		
	}
	else
		error(4);                       
	
	return x;
}

int[] vardeclaration(int ptx,int lev,int pdx)
{
	int[]x=new int[2];

⌨️ 快捷键说明

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