import java.io.*;
import java.lang.*;
import java.util.*;
/*错误号
0 ,"缺少左括号"
1 ,"非法字符:赋值符号:="
2 ,"等号后的字符为非法字符"
3 ,"缺少等号"
4 ,"声明过程中遇到的字符不是标识符"
5 ,"缺少分号"
6 ,"非法语句"
7 ,"整数大小越界"
8 ,"整数位数越界"
9 ,"缺少右括号"
10 ,"语句和语句之间没有分号"
11 ,"标识符不存在"
12 ,"标识符不是变量名"
13 ,"缺少赋值符号"
14 ,"call后不是标识符"
15 ,"call后不是过程名"
16 ,"if后不是then"
17 ,"没有遇到end"
18 ,"while循环缺少do"
19 ,"标识符长度越界"
20 ,"缺少逻辑运算符"
21 ,"标识符为过程名"
22 ,"缺少右括号"
*/
/**
*第一大类主类
*主程序*/
public class pl0
{
public static void main(String [] args)
{
String filename=" ";
new pl0();//初始化一个PL0对象
System.out.print("请输入PL源程序的文件名:");
try
{
InputStreamReader fin=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(fin);
filename=br.readLine();
}
catch(IOException e)
{
System.out.println("错误!请输入源程序文件名");
}
//声明一个词法分析类,获得源程序的第一个词(token)
CiFaAnalyse Cifa=new CiFaAnalyse(filename);
YuFaAnalyse YuFa=new YuFaAnalyse(Cifa);
int errorNumber=Cifa.getErroNumber()+YuFa.getErroNumber();
if(errorNumber==0)
{
YuFa.printCode();
System.out.println("错误总数为"+errorNumber);
YuFa.interpret();
}
else {System.out.println("错误总数为"+errorNumber);}
//YuFa.printCode();
//YuFa.printName();
}
}
class erro //错误处理类
{
String[] err={" 缺少左括号"
,"非法字符:赋值符号:="
,"等号后的字符为非法字符"
,"缺少等号"
,"声明过程中遇到的字符不是标识符"
,"缺少分号"
,"非法语句"
,"整数大小越界"
,"整数位数越界"
,"缺少右括号"
,"语句和语句之间没有分号"
,"标识符不存在"
,"标识符不是变量名"
,"缺少赋值符号"
,"call后不是标识符"
,"call后不是过程名"
,"if后不是then"
,"没有遇到end"
,"while循环缺少do"
,"标识符长度越界"
,"缺少逻辑运算符"
,"标识符为过程名"
,"缺少右括号"
};
erro(int linenumber,int t)
{
System.out.println("行:"+linenumber+" 错误号"+t+" "+err[t]);
}
}
//用于表示符号类,存放于符号表中
class nameClass
{
String name=null;
String kind=null;
int val;
int level;
int adr;
public nameClass(String a,String b,int c,int d,int e)
{
name=a;
kind=b;
val=c;
level=d;
adr=e;
}
public void setAdr(int cx0)
{
adr=cx0;
}
public int getAdr()
{
return adr;
}
public String getKind()
{
return kind;
}
public int getVal()
{
return val;
}
public String getNam()
{
return name;
}
public int getLev()
{
return level;
}
}
/**p-code指令*/
class pcode//pcode类 表示pcode指令
{
String f=" ";//第一个参数:操作码
int l; //第二个参数:层次差
int a; //
public pcode(String x,int y,int z)
{
f=x;
l=y;
a=z;
}
public void setA(int t)
{
a=t;
}
public String getF()
{return f;}
public int getL()
{return l;}
public int getA()
{return a;}
}
/**字符串*/
class token//token类 用于存放读取的token单词
{
private String sym="原来的"; //保存token的类型
private String name="原来的"; //保存token的内容
public int lineNum;
token(String name1,String sym1)
{
name=name1;
sym=sym1;
}
token(String name1,String sym1,int l)
{
name=name1;
sym=sym1;
lineNum=l;
}
public void setLineNum(int l)
{
lineNum=l;
}
public int getLineNum()
{return lineNum;}
public String getNam()
{
return name;
}
public String getSym()
{
return sym;
}
}
/*第三大类:
*带有词法分析的接口
*语法分析类*/
class YuFaAnalyse
{
public CiFaAnalyse CiFa;//参数传递给语法
public token word;
public String id=null; //用于登录名字表时的token名字
public int lineNum; //用于错误处理时的行数记录
public int errorNumber=0; //用于保存语法分析中的错误数目
int cx;
int cx0;
int dx;
int lev=-1;
int errorNum=0;
public int t=-1; //堆栈顶指针
final public int stacksize =500;
public int p=0; //下一条指令位置
public int b=0; //基地址指针
public pcode i; //指令
public int []s=new int[501];
Vector pcodeArray= new Vector(); ; //生成一个vector矢量! // 此矢量用作存放pcode代码的数组
Vector nameArray=new Vector();//生成一个存放矢量 作为名字表;
public YuFaAnalyse(CiFaAnalyse CF)//语法分析构造函数
{
CiFa=CF;//从主程序传入一个词法分析对象,将其赋给CiFa
word=CiFa.GetToken(); //获得一个token
analyse(); //然后调用分析程序
}
public int getErroNumber()
{return errorNumber;}
public void printCode()//pcode的显示方法,如果没有错误,则打印pcode代码
{
for(int n=0;n<pcodeArray.size();n++)
{
pcode code=(pcode)pcodeArray.get(n);
System.out.println(n+" "+code.getF()+" "+code.getL()+" "+code.getA());
}
}
public void analyse()
{
int tx0;
lev++;
dx=3;
tx0=nameArray.size(); //用tx0保存当前层的符号在符号表中的起始位置
nameArray.addElement(new nameClass(" "," ",0,0,0));//在这里给符号表填加一个元素,否则下一条代码会运行出界
((nameClass)nameArray.get(tx0)).setAdr(pcodeArray.size());//在上面加的那个元素里的私有字段adr里保存当前层代码的开始位置
pcodeArray.addElement(new pcode("jmp",0,0)); //生成跳转指令 由于跳转位置未知 暂时添0
while(word.getSym().equals("constsym")||word.getSym().equals("varsym")||word.getSym().equals("procsym"))
{
if(word.getSym().equals("constsym"))//常量处理
{
word=CiFa.GetToken();
delcaration(); //调用常量声明,常量声明完毕时再次读取一个token
while(word.getSym().equals("comma"))//若在常量声明后读取的token为逗号,则要继续进行常量声明,这里采用while循环,直到token不是逗号
{
word=CiFa.GetToken();
delcaration(); //调用常量声明,常量声明完毕时再次读取一个token
}
if(word.getSym().equals("semicolon"))//若token不是逗号,则应该是分号了,标志常量声明结束
{
word=CiFa.GetToken();
}
else
{
errorNumber++;new erro(word.getLineNum(),5);//如果常量声明完毕后没有遇到分号;则抛出15号错误
}
}
//变量处理
else if(word.getSym().equals("varsym"))
{
word=CiFa.GetToken();//读取一个token,应该是一个ident标识符
vardeclaration(); //调用变量声明,常量声明完毕时还要再次读取一个token
while(word.getSym().equals("comma"))
{
word=CiFa.GetToken();
vardeclaration(); //调用变量声明,常量声明完毕时还要再次读取一个token
}
if(word.getSym().equals("semicolon"))
{
word=CiFa.GetToken();
}
else
{
errorNumber++;new erro(word.getLineNum(),5);//如果变量声明完毕后没有遇到分号;则调用错误处理程序抛出5号错误
}
}
//循环声明各个子过程
while(word.getSym().equals("procsym"))
{
word=CiFa.GetToken();
if(word.getSym().equals("ident"))
{
id=word.getNam();
enter("procedure");
word=CiFa.GetToken();
}
else
{
errorNumber++;new erro(word.getLineNum(),4);//过程名不是标识符,抛出4号错误
}
if(word.getSym().equals("semicolon"))
{
word=CiFa.GetToken();
}
else {errorNumber++;new erro(word.getLineNum(),5);}//过程名后没有分号
// System.out.println(dx);
int dxxxxx=dx;
int levv=lev;
analyse();//递归调用下一层的分程序段分析
dx=dxxxxx;
lev=levv;
// System.out.println(dx);
if(word.getSym().equals("semicolon"))
{
word=CiFa.GetToken();
//test程序 若end;后的符号不在ident,procsym,begin,call,if,while中,则调用6号错误
String sym=word.getSym();
if(!(sym.equals("ident")||sym.equals("procsym")||sym.equals("beginsym")||sym.equals("callsym")||sym.equals("ifsym")||sym.equals("while")))
{
errorNumber++;new erro(word.getLineNum(),6);
}
}
else { errorNumber++;new erro(word.getLineNum(),5);}
//test程序 当前符号不在ident,begin,call,if,while中,则调用7号错误
}
}
((pcode)pcodeArray.get(((nameClass)nameArray.get(tx0)).getAdr())).setA(pcodeArray.size());//把前面生成的跳转指令的跳转位置改成当前位置
((nameClass)nameArray.get(tx0)).setAdr(pcodeArray.size());//在符号表中,对于过程名,adr应填入编译该过程所生成的pcode指令序列的入口地址
cx0=pcodeArray.size();//在cx0中保存当前代码的分配地址
pcodeArray.addElement(new pcode("int",0,dx));//生成空间分配指令,分配dx个空间(3个空间+变量的数目)
statement1();//处理当前遇到的语句;
pcodeArray.addEl
![avatar](https://profile-avatar.csdnimg.cn/9d774e17dae94b1287526d89d7503a61_weixin_42659194.jpg!1)
刘良运
- 粉丝: 81
- 资源: 1万+
最新资源
- 胖东来:关于“红色内裤掉色、过敏以及部门处理过程”的调查报告
- Python 实现DBN深度置信网络多输入分类预测的详细项目实例(含完整的程序,GUI设计和代码详解)
- Python 实现基于CNN-GRU-KDE卷积门控循环单元多变量时间序列区间预测的详细项目实例(含完整的程序,GUI设计和代码详解)
- Python 实现CNN-BiGRU卷积双向门控循环单元多输入单输出回归预测的详细项目实例(含完整的程序,GUI设计和代码详解)
- Python 实现PSO-CNN粒子群算法优化卷积神经网络的数据多输入单输出回归预测的详细项目实例(含完整的程序,GUI设计和代码详解)
- Python 实现PSO-DBN粒子群优化深度置信网络多输入分类预测的详细项目实例(含完整的程序,GUI设计和代码详解)
- Python 实现基于CNN-GRU-Multihead-Attention-KDE多变量时间序列区间预测的详细项目实例(含完整的程序,GUI设计和代码详解)
- Python 实现GA-GRU遗传算法优化门控循环单元的数据多输入分类预测的详细项目实例(含完整的程序,GUI设计和代码详解)
- Python 实现INFO-ELM向量加权算法优化极限学习机时间序列预测的详细项目实例(含完整的程序,GUI设计和代码详解)
- Python 实现GA-LSTM遗传算法优化长短期记忆网络的数据多输入分类预测(含完整的程序,GUI设计和代码详解)
- “基于DSP F2812技术的多功能光伏并网逆变器设计,包括DC AC逆变、控制及显示功能”,基于DSP F2812的2KW光伏并网逆变器设计与实现:逆变、控制、保护及监控一体化方案,2KW光伏并网逆
- 联想BIOS配置工具(ThinkBIOS Config)
- Python 实现NARX非线性自回归外生模型时间序列预测(含完整的程序,GUI设计和代码详解)
- 西门子828D CNC机床的UG后处理技术解析:工厂实战应用与自用经验分享,深入探讨UG后处理技术:CNC与西门子828D后处理的实践应用与工厂实战自用策略,UG后处理-CNC-西门子828D后处理
- Python 实现GA-BiLSTM遗传算法优化双向长短期记忆网络的数据多输入分类预测(含完整的程序,GUI设计和代码详解)
- Python 实现基于CNN-BiLSTM-KDE多变量时间序列区间预测(含完整的程序,GUI设计和代码详解)
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
![feedback](https://img-home.csdnimg.cn/images/20220527035711.png)
![feedback](https://img-home.csdnimg.cn/images/20220527035711.png)
![feedback-tip](https://img-home.csdnimg.cn/images/20220527035111.png)