📄 pl02.java
字号:
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 + -