自上而下语法分析实验报告.docx
《自上而下语法分析实验报告.docx》由会员分享,可在线阅读,更多相关《自上而下语法分析实验报告.docx(20页珍藏版)》请在冰豆网上搜索。
自上而下语法分析实验报告
实验二:
自上而下语法分析
1、实验目的和要求
根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。
根据某一文法编制调试LL
(1)分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对自上而下分析法的理解,从而实现一个LL
(1)文法分析器。
2、实验容
(1)功能描述:
LL
(1)分析法的功能是利用LL
(1)控制程序根据显示栈栈顶容、向前看符号以LL
(1)预测分析表,对输入符号串自上而下的分析过程。
本程序是基于已构建好的某一个语法的预测分析表来对用户的输入字符串进行分析,判断输入的字符串是否属于该文法的句子。
(2)程序基本实现思想:
接收用户输入的字符串(字符串以“#”表示结束)后,对用做分析栈的一维数组和存放分析表的二维数组进行初始化。
然后取出分析栈的栈顶字符,判断是否为终结符,若为终结符则判断是否为“#”且与当前输入符号一样,若是则语法分析结束,输入的字符串为文法的一个句子,否则出错若不为“#”且与当前输入符号一样则将栈顶符号出栈,当前输入符号从输入字符串中除去,进入下一个字符的分析。
若不为“#”且不与当前输入符号一样,则出错。
若栈顶符号为非终结符时,查看预测分析表,看栈顶符号和当前输入符号是否构成产生式,若产生式的右部为ε,则将栈顶符号出栈,取出栈顶符号进入下一个字符的分析。
若不为ε,将产生式的右部逆序的入栈,取出栈顶符号进入下一步分析。
(3)程序要求:
程序输入/输出示例:
对下列文法,用LL
(1)分析法对任意输入的符号串进行分析:
E→TE’
E’→+TE’|ε
T→FT’
T’→*FT’|ε
F→i|(E)
该文法的预测分析表为:
输出的格式如下:
LL
(1)分析:
输入一以#结束的符号串(包括+—*/()i#):
在此位置输入符号串例如:
i+i*i#
输出结果:
显示步骤、分析栈、剩余输入串和所用产生式的分析推导过程,若出错,则显示出在哪一步出错,并显示i+i*i#为不合法符号串。
(4)程序流程图:
(5)程序结构描述:
publicbooleanjudge(){
StringinputChar=inputString.substring(0,1);//当前输入字符
booleanflage=false;
if(count1>=0){
for(inti=0;i<6;i++){
if(fenxi[count1].equals(Vt[i])){//判断分析栈栈顶的字符是否为终结符
flage=true;
break;}}}
if(flage){//为终结符时
if(fenxi[count1].equals(inputChar)){
if(fenxi[count1].equals("#")&&inputString.length()==1){//栈顶符号为结束标志时
Stringfenxizhan="";
for(inti=0;iif(fenxi[i]==null){
break;
}else{
fenxizhan=fenxizhan+fenxi[i];}}
//输出当前分析栈情况,输入字符串,所用产生式或匹配
System.out.print(""+count);
StringcountToString=Integer.toString(count);
intfarWay=12-countToString.length();
for(intk=0;kSystem.out.print("");}
System.out.print(newStringBuffer(fenxizhan).reverse());//输出分析栈
farWay=17-fenxizhan.length();
for(intk=0;kSystem.out.print("");}
System.out.print(inputString);
farWay=20-inputString.length();
for(intk=0;kSystem.out.print("");}
System.out.println("接受");
flag=true;
returntrue;
}else{//分析栈栈顶符号不为结束标志符号时
。
。
。
。
。
。
//将栈顶符号出栈,栈顶指针减一
fenxi[count1]=null;
count1-=1;
if(inputString.length()>1){//当当前输入字符串的长度大于1时,将当前输入字符从输入字符串中除去
inputString=inputString.substring(1,
inputString.length());
}else{//当前输入串长度为1时
inputChar=inputString;}
count++;
judge();
}}else{//判断与输入符号是否一样
System.out.println("分析到第"+count+"步时出错!
");
flag=false;
returnfalse;}
}else{//非终结符时
booleanfla=false;
for(inti=0;i<6;i++){//查询当前输入符号位于终结符集的位置
if(inputChar.equals(Vt[i])){
fla=true;
count2=i;//终结符位置
break;}}
if(!
fla){
System.out.println("分析到第"+count+"步时出错!
");
flag=false;
returnfalse;}
for(inti=0;i<5;i++){//查询栈顶的符号位于非终结符集的位置
if(fenxi[count1].equals(Vn[i])){
count3=i;//非终结符位置
break;}}
if(P[count3][count2]!
="error"){//栈顶的非终结符与输入的终结符存在产生式时
Stringp=P[count3][count2];
Strings1=p.substring(2,p.length());//获取对应的产生式
if(s1.equals("ε")){//产生式推出“ε”时
。
。
。
。
。
。
//将栈顶符号出栈,栈顶指针指向下一个元素
fenxi[count1]=null;
count1-=1;
count++;
judge();
}else{//产生式不推出“ε”时
intk=s1.length();
。
。
。
。
。
。
for(inti=1;i<=k;i++){//将产生式右部的各个符号入栈
Strings2=s1.substring(s1.length()-1,s1.length());//分析栈最后一个字符
s1=s1.substring(0,s1.length()-1);
if(s2.equals("'")){
s2=s2+s1.substring(s1.length()-1,s1.length());//,+倒数第二个字符
i++;
s1=s1.substring(0,s1.length()-1);}
fenxi[count1]=s2;
if(icount1++;}
count++;
judge();}
}else{
System.out.println("分析到第"+count+"步时出错!
");
flag=false;
returnfalse;}}
returnflag;}
3、实验结果
1、显示预测分析表,提示用户输入字符串
2、输入的字符串为正确的句子
测试数据:
输入字符串i*i+i#
3、输入的字符串中包含了不属于终结符集的字符
四、实验总结
这次实验让我更加熟悉了LL
(1)的工作流程以及LL
(1)预测分析表的构造方法,我加深了对预测分析LL
(1)分析法的理解,同时体验到了编译原理中一些算法的巧妙。
以前课堂上搞不懂的算法流程通过实验都能得到进一步的了解。
通过本次上机实验,由于LL
(1)分析法程序是一个相当复杂的程序,它需要利用到大量的编译原理,编程技巧和数据结构。
由于先前掌握的知识不够牢固深刻使之在实验过程中出现了大量的问题。
由于课前的充分准备,不断地调试最后顺利完成了实验。
5、源码
/**
*
*/
package.fgy.practice;
importjava.io.BufferedReader;
importjava.io.InputStreamReader;
/**
*authorguiyang
*/
publicclassLL{
StringVn[]={"E","'E","T","'T","F"};//非终结符集
StringVt[]={"i","+","*","(",")","#"};//终结符集
StringP[][]=newString[5][6];//预测分析表
Stringfenxi[];//分析栈
intcount=1;//步骤
intcount1=1;//’分析栈指针
intcount2=0,count3=0;//预测分析表指针
StringinputString="";//输入的字符串
booleanflag;
publicvoidsetCount(intcount,intcount1,intcount2,intcount3){
this.count=count;//1
this.count1=count1;//1
this.count2=count2;//0
this.count3=count3;//0
flag=false;
}
publicvoidsetFenxi(){//初始化分析栈
fenxi=newString[20];
fenxi[0]="#";
fenxi[1]="E";
}
publicvoidsetP(){//初始化预测分析表
for(inti=0;i<5;i++){
for(intj=0;j<6;j++){
P[i][j]="error";
}
}
P[0][0]="->TE'";
P[0][3]="->TE'";
P[1][1]="->+TE'";
P[1][4]="->ε";
P[1][5]="->ε";
P[2][0]="->FT'";
P[2][3]="->FT'";
P[3][1]="->ε";
P[3][2]="->*FT'";
P[3][4]="->ε";
P[3][5]="->ε";
P[4][0]="->i";
P[4][3]="->(E)";
//打印出预测分析表
System.out.println("已构建好的预测分析表");
System.out.println("----------------------------------------------------------------------");
for(inti=0;i<6;i++){
System.out.print(""+Vt[i]);//11
}
System.out.println();
System.out.println("----------------------------------------------------------------------");
for(inti=0;i<5;i++){
System.out.print(""+newStringBuffer(Vn[i]).reverse()+"");//9
for(intj=0;j<6;j++){
System.out.print(""+P[i][j]+"");
}
System.out.println();
}
System.out.println("----------------------------------------------------------------------");
}
publicvoidsetInputString(Stringinput){
inputString=input;
}
publicbooleanjudge(){
StringinputChar=inputString.substring(0,1);//当前输入字符
booleanflage=false;
if(count1>=0){
for(inti=0;i<6;i++){
if(fenxi[count1].equals(Vt[i])){//判断分析栈栈顶的字符是否为终结符
flage=true;
break;
}
}
}
if(flage){//为终结符时
if(fenxi[count1].equals(inputChar)){
if(fenxi[count1].equals("#")&&inputString.length()==1){//栈顶符号为结束标志时
Stringfenxizhan="";
for(inti=0;iif(fenxi[i]==null){
break;
}else{
fenxizhan=fenxizhan+fenxi[i];
}
}
//输出当前分析栈情况,输入字符串,所用产生式或匹配
System.out.print(""+count);
StringcountToString=Integer.toString(count);
intfarWay=12-countToString.length();
for(intk=0;kSystem.out.print("");
}
System.out.print(newStringBuffer(fenxizhan).reverse());//输出分析栈
farWay=17-fenxizhan.length();
for(intk=0;kSystem.out.print("");
}
System.out.print(inputString);
farWay=20-inputString.length();
for(intk=0;kSystem.out.print("");
}
System.out.println("接受");
flag=true;
returntrue;
}else{//分析栈栈顶符号不为结束标志符号时
Stringfenxizhan="";
for(inti=0;iif(fenxi[i]==null){
break;
}else{
fenxizhan=fenxizhan+fenxi[i];
}
}
//输出当前分析栈情况,输入字符串,所用产生式或匹配
System.out.print(""+count);
StringcountToString=Integer.toString(count);
intfarWay=12-countToString.length();
for(intk=0;kSystem.out.print("");
}
System.out.print(newStringBuffer(fenxizhan).reverse());//输出分析栈
farWay=17-fenxizhan.length();
for(intk=0;kSystem.out.print("");
}
System.out.print(inputString);
farWay=20-inputString.length();
for(intk=0;kSystem.out.print("");
}
System.out.println("\""+inputChar+"\""+"匹配");
//System.out.println(inputChar+"匹配");
//将栈顶符号出栈,栈顶指针减一
fenxi[count1]=null;
count1-=1;
if(inputString.length()>1){//当当前输入字符串的长度大于1时,将当前输入字符从输入字符串中除去
inputString=inputString.substring(1,
inputString.length());
}else{//当前输入串长度为1时
inputChar=inputString;
}
count++;
judge();
}
}else{//判断与输入符号是否一样
System.out.println("分析到第"+count+"步时出错!
");
flag=false;
returnfalse;
}
}else{
//非终结符时
booleanfla=false;
for(inti=0;i<6;i++){//查询当前输入符号位于终结符集的位置
if(inputChar.equals(Vt[i])){
fla=true;
count2=i;//终结符位置
break;
}
}
if(!
fla){
System.out.println("分析到第"+count+"步时出错!
");
flag=false;
returnfalse;
}
for(inti=0;i<5;i++){//查询栈顶的符号位于非终结符集的位置
if(fenxi[count1].equals(Vn[i])){
count3=i;//非终结符位置
break;
}
}
if(P[count3][count2]!
="error"){//栈顶的非终结符与输入的终结符存在产生式时
Stringp=P[count3][count2];
Strings1=p.substring(2,p.length());//获取对应的产生式
if(s1.equals("ε")){//产生式推出“ε”时
Stringfenxizhan="";
for(inti=0;iif(fenxi[i]==null){
break;
}else{
fenxizhan=fenxizhan+fenxi[i];
}
}
//输出当前分析栈情况,输入字符串,所用产生式或匹配
System.out.print(""+count);
StringcountToString=Integer.toString(count);
intfarWay=12-coun