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