算符优先分析法
来源:互联网 发布:中国电信网络在线测速 编辑:程序博客网 时间:2024/06/05 07:48
测试数据:
6
S->#E#
P->i
F->P
T->F
E->T
E->E+T
输出结果:
源代码:
第一个类
public class WF { public String left=""; public List<String> right=new ArrayList<String>(); public WF(String string){ this.left=string; } public void insert(String string){ right.add(string); } public void print(){ System.out.printf("%s->%s",left,right.get(0).toString()); for(int i=1;i<right.size();i++){ System.out.printf("|%s",right.get(i).toString()); System.out.println(); } System.out.println(); }}
第二个类:
package 语法分析器;//import java.util.ArrayList;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Scanner;import java.util.Set;import java.util.Stack;//测试数据 1 构建关系表好着//8//E->E+T//E->T//T->T*F//T->F//F->P^F//F->P//P->(E)//P->i//测试数据2(默认输入串为i+i#)//6//S->#E#//P->i//F->P//T->F//E->T//E->E+Tpublic class suanfuyouxianwenfa1 { static int step=0;//记录第几步从第一步开始 static int MAX=507; char[][] relation=new char[MAX][MAX];//关系表数组 static List<Character> VT= new ArrayList<Character> ();//终结符集 static List<WF> VN_set=new ArrayList<WF>();//非终结符 用来分离并存储产生式左部和右部 static Map<String,Integer> VN_dic=new HashMap<String,Integer>();//记录VN非终结符 static int[] used=new int[MAX];//用来记录终结符为第几个终结符 static String s1;//产生式左部的引用变量 static String s2;//产生式右部的引用变量 static boolean[][] F;//firstvt集 static boolean[][] Fl;//lastvt集 static char[][] table;//文法优先表 static char currentRelation;//优先关系 static int index=-1;//当前符号所在下标 static Stack stack=new Stack();// static Stack stackl=new Stack(); String stackString=null; static String str2="i+i#"; static char a;//当前符号 static Stack<Character> S=new Stack<Character>(); //查找某VN(非终结符)所在的VN_set list中所在的位置 public static int findindexFromVN_set(char P){ for(int i=0;i<VN_set.size();i++){ if(VN_set.get(i).left.charAt(0)==P){ return i; } } return -1; } //查找某VT(终结符)所在的VT list中的位置 public static int findindexFromVT(char a){ return VT.indexOf(a); } //构建firstvt用,把(P,a)推进栈//书上91页右下角程序思路 public static void insert(char P,char a){// System.out.println("P->"+P+"|"+"findindexFromVN_set(P)->"+findindexFromVN_set(P));// System.out.println("a->"+a+"|"+"VT.indexOf(a)->"+VT.indexOf(a)); if(!F[findindexFromVN_set(P)][VT.indexOf(a)]){ F[findindexFromVN_set(P)][VT.indexOf(a)]=true; stack.push(""+'('+P+','+a+')');//把(P,a)推进stack栈end } } //构建lastvt集用,把(P,a)推进栈//书上91页右下角程序思路 public static void insertl(char P,char a){// System.out.println("P->"+P+"|"+"findindexFromVN_set(P)->"+findindexFromVN_set(P));// System.out.println("a->"+a+"|"+"VT.indexOf(a)->"+VT.indexOf(a)); if(!Fl[findindexFromVN_set(P)][VT.indexOf(a)]){ Fl[findindexFromVN_set(P)][VT.indexOf(a)]=true; stackl.push(""+'('+P+','+a+')');//把(P,a)推进stack栈end } } //构造(非终极符)的firstvt函数//书上91页右下角程序思路 public static void makefirst(){ F=new boolean[VN_set.size()][VT.size()]; //先初始化F集 for(int i=0;i<VN_set.size();i++){ for(int j=0;j<VT.size();j++){ F[i][j]=false; } } for(int i=0;i<VN_set.size();i++){ for(int j=0;j<VN_set.get(i).right.size();j++){ if(Character.isUpperCase(VN_set.get(i).left.charAt(0))&&!Character.isUpperCase(VN_set.get(i).right.get(j).charAt(0))) { insert(VN_set.get(i).left.charAt(0),VN_set.get(i).right.get(j).charAt(0) ); } if((VN_set.get(i).right.get(j).length()>2)&&Character.isUpperCase(VN_set.get(i).left.charAt(0))&&Character.isUpperCase(VN_set.get(i).right.get(j).charAt(0))&&!Character.isUpperCase(VN_set.get(i).right.get(j).charAt(1))){ insert(VN_set.get(i).left.charAt(0),VN_set.get(i).right.get(j).charAt(1) ); } } } while(!stack.isEmpty()){ String str=(String) stack.pop();//str=(P,a); char Q=str.charAt(1);char a=str.charAt(3); for(int i=0;i<VN_set.size();i++){ for(int j=0;j<VN_set.get(i).right.size();j++){ if(Character.isUpperCase(VN_set.get(i).left.charAt(0))&&VN_set.get(i).right.get(j).charAt(0)==Q){ insert(VN_set.get(i).left.charAt(0), a); } } } } for(int i=0;i<F.length;i++){ System.out.printf("%c :",VN_set.get(i).left.charAt(0)); for(int j=0;j<F[i].length;j++){ if(F[i][j]==true){ System.out.printf(" %c",VT.get(j)); } } System.out.println(); } } //构造(非终极符)的lastvt函数//书上91页右下角程序思路 public static void makelast(){ Fl=new boolean[VN_set.size()][VT.size()]; for(int i=0;i<VN_set.size();i++){ for(int j=0;j<VT.size();j++){ Fl[i][j]=false; } } for(int i=0;i<VN_set.size();i++){ for(int j=0;j<VN_set.get(i).right.size();j++){ if(Character.isUpperCase(VN_set.get(i).left.charAt(0))&&!Character.isUpperCase(VN_set.get(i).right.get(j).charAt(VN_set.get(i).right.get(j).length()-1))) { insertl(VN_set.get(i).left.charAt(0),VN_set.get(i).right.get(j).charAt(VN_set.get(i).right.get(j).length()-1) ); } if((VN_set.get(i).right.get(j).length()>2)&&Character.isUpperCase(VN_set.get(i).left.charAt(0))&&Character.isUpperCase(VN_set.get(i).right.get(j).charAt(VN_set.get(i).right.get(j).length()-1))&&!Character.isUpperCase(VN_set.get(i).right.get(j).charAt(VN_set.get(i).right.get(j).length()-2))){ insertl(VN_set.get(i).left.charAt(0),VN_set.get(i).right.get(j).charAt(VN_set.get(i).right.get(j).length()-2) ); } } } while(!stackl.isEmpty()){ String str=(String)stackl.pop();//str=(P,a); char Q=str.charAt(1);char a=str.charAt(3); for(int i=0;i<VN_set.size();i++){ for(int j=0;j<VN_set.get(i).right.size();j++){ if(Character.isUpperCase(VN_set.get(i).left.charAt(0))&&VN_set.get(i).right.get(j).charAt(VN_set.get(i).right.get(j).length()-1)==Q){ insertl(VN_set.get(i).left.charAt(0), a); } } } } for(int i=0;i<Fl.length;i++){ System.out.printf("%c :",VN_set.get(i).left.charAt(0)); for(int j=0;j<Fl[i].length;j++){ if(Fl[i][j]==true){ System.out.printf(" %c",VT.get(j)); } } System.out.println(); } } //构造文法优先表函数//书上92页左上角程序思路 public static void make_table(){ table=new char[VT.size()][VT.size()]; for(int i=0;i<VN_set.size();i++){ for(int j=0;j<VN_set.get(i).right.size();j++){ String right=VN_set.get(i).right.get(j); for(int t=0;t<VN_set.get(i).right.get(j).length()-1;t++){ char c1=right.charAt(t); char c2=right.charAt(t+1); if(!Character.isUpperCase(c1)&&!Character.isUpperCase(c2)){ table[findindexFromVT(c1)][findindexFromVT(c2)]='='; } if((t<(VN_set.get(i).right.get(j).length()-2)) &&!Character.isUpperCase(c1) &&Character.isUpperCase(c2) &&!Character.isUpperCase(right.charAt(t+2))){ table[findindexFromVT(c1)][findindexFromVT(right.charAt(t+2))]='='; } if(!Character.isUpperCase(c1)&&Character.isUpperCase(c2)){ for(int i1=0;i1<F[findindexFromVN_set(c2)].length;i1++){ if(F[findindexFromVN_set(c2)][i1]==true){ table[findindexFromVT(c1)][i1]='<'; } } } if(Character.isUpperCase(c1)&&!Character.isUpperCase(c2)){ for(int i1=0;i1<Fl[findindexFromVN_set(c1)].length;i1++){ if(Fl[findindexFromVN_set(c1)][i1]==true){ table[i1][findindexFromVT(c2)]='>'; } } } } } } System.out.println("*********************算符优先关系表***************************"); System.out.println("\n--------------------------------------------------------"); for(int i=-1;i<VT.size();i++){ for(int j=-1;j<VT.size();j++){ if(i==-1&&j==-1){ System.out.printf("| |"); continue; } if(i==-1){ System.out.printf("%4c |",VT.get(j)); }else{ if(j==-1){ System.out.printf("|%4c |",VT.get(i)); continue; } System.out.printf("%4c |",table[i][j]); } } System.out.println("\n--------------------------------------------------------"); } } //移进规约函数//书上93页右上角程序思路 public static void move_reduction(String str){//str="i+i#" char Q;//用来指向终结符 int k=0;//一开始让k=0,可以通过stack.get(k);查找到对应位置的元素 int j=0;//j用来指向优先级小于终结符Q的终结符 char c; //保存弹出来的字符 String s="";//用来保存待归约的串 S.push('#'); do{ index++;//当前符号后移 a=str.charAt(index); if(findindexFromVT((char)S.peek())!=-1){//判断栈顶是否是终结符 j=k; }else{ j=k-1; } while(table[findindexFromVT(S.get(j))][findindexFromVT(a)]=='>'){ currentRelation=table[findindexFromVT(S.get(j))][findindexFromVT(a)]; do{ Q=S.get(j);//Q指向j当前所指向的终结符 j指向离栈顶最远的且优先关系>当前符号的终结符 if(findindexFromVT(S.get(j-1))!=-1){ j=j-1; }else{ j=j-2; } //j指向优先级小于栈顶终结符Q的终结符则退出 }while(table[findindexFromVT(S.get(j))][findindexFromVT(Q)]!='<');// //归约前打印说明归约 step++; System.out.printf("%2s |%-5s%5s%10s%8s",step,printfStatck(),currentRelation,a,residue(str2)); //把S[j+1]。。。。S[k]规约为某个N //通过出栈,提炼S[k]到S[j+1]到s中 int key=k;//key从k移动到j s=""; do{ c=S.pop(); s=c+s; key--; }while(key!=j); int flag=0; //把S[j+1]。。。。S[k]规约为某个N //书上93页指出'N'是指那样一个产生式的左部符号,次产生式的右部和S[j+1]。。。S[k]构成如下一一对应的关系: //自左至右,终结符对终结符,非终结符对非终结符,而且对应的终结符相同。 for(int i=0;i<VN_set.size();i++){ for(int j1=0;j1<VN_set.get(i).right.size();j1++){ char left=VN_set.get(i).left.charAt(0); String right=VN_set.get(i).right.get(j1); if(Character.isUpperCase(left)&&right.equals(s)){ S.push(left); System.out.println(" 归约:"+left+"->"+right); s="";//清空 flag=1; break; }//长度一样 else if(Character.isUpperCase(left)&&check(right,s)){ S.push(left); System.out.println(" 归约:"+left+"->"+right); s="";//清空 flag=1; break; } } if(flag==1){ break; } } } if(table[findindexFromVT(S.get(j))][findindexFromVT(a)]=='<' ||table[findindexFromVT(S.get(j))][findindexFromVT(a)]=='='){ currentRelation=table[findindexFromVT(S.get(j))][findindexFromVT(a)]; k=k+1; step++; System.out.printf("%2s |%-5s%5s%10s%8s",step,printfStatck(),currentRelation,a,residue(str2)); S.push(a);//压栈 System.out.printf("%10s","移进:把"+a+"移进"); System.out.println(); }else{ System.out.println("出错了!"); } }while(a!='#'); } //检查两个字符串是否长度相同 private static boolean check(String right, String s3) { if(right.length()!=s3.length()){ return false; } // TODO Auto-generated method stub for(int i=0;i<right.length();i++){ if(Character.isUpperCase(right.charAt(i))!=Character.isUpperCase(s3.charAt(i))) return false; } return true; } **//main方法** public static void main(String[] args){ //初始化used(记录VT的表)赋初值为-1 表示其对应的值没有出现过 initused(); VT.clear(); String n;//统计文法的个数 String s = null;//用来暂时性存储当前输入的文法 Scanner reader=new Scanner(System.in); n=reader.nextLine(); for(int i=0;i<Integer.valueOf(n);i++){ s=reader.nextLine(); //分离当前输入的产生式 int i1=s.lastIndexOf('-'); s1=s.substring(0,i1);//产生式左部 s2=s.substring(i1+2);//产生式右部 if(!VN_dic.containsKey(s1)){ VN_set.add(new WF(s1.toString()));// VN_dic.put(s1.toString(),VN_set.size()-1);//用VN_dic记录非终结符 } int x=VN_dic.get(s1);//在VN_dic中查找当前输入的产生式左部对应的位置 VN_set.get(x).insert(s2);//在对应的产生式集合VN_set中保存对应产生式左部的右部 for(int k=0;k<s2.length();k++){ if(!Character.isUpperCase(s2.charAt(k))){ if(used[s2.charAt(k)]>-1)//初始化use[][]中的值为-1,如果大于-1则该字符被记录过 continue; VT.add(s2.charAt(k)); used[s2.charAt(k)]=VT.size()-1;//某vt第一个出现则记为0 } } } System.out.println("**********VT集的大小为:****************"); System.out.println(VT.size()); System.out.println("*********VT集**************"); for(int i=0;i<VT.size();i++){ System.out.printf("%c ",VT.get(i)); } System.out.println(); for(int i=0;i<VT.size();i++){ System.out.printf("%d ",used[VT.get(i)]); } System.out.println(); System.out.println("************VN集********************"); for(int i=0;i<VN_set.size();i++){ System.out.printf("%s ",VN_set.get(i).left); } System.out.println(); for(int i=0;i<VN_set.size();i++){ System.out.printf("%d ",VN_dic.get(VN_set.get(i).left)); } System.out.println(); System.out.println("**********产生式*****************"); for(int i=0;i<VN_set.size();i++){ VN_set.get(i).print(); } System.out.println("***********Firstvt集*********************"); makefirst(); System.out.println("***********Lastvt集*********************"); makelast(); make_table(); printstep(); move_reduction(str2); System.out.printf("归约结束! 默认输入串为:"+"'"+"%s"+"'"+" 算符优先分析规约后最后的栈中元素为:"+"'"+"%s"+"'",str2,printfStatck()); } //打印展示归约步鄹的格式 private static void printstep() { // TODO Auto-generated method stub System.out.printf("%2s|%-10s%10s%10s%10s%10s","步骤","栈中","优先关系","当前符号","剩余符号","动作"); System.out.println(); } //初始化use表使表中的值初始化为-1 private static void initused() { // TODO Auto-generated method stub for(int i=0;i<used.length;i++){ used[i]=-1; } } //剩余输入符号 public static String residue(String str){ String s=str.substring(index+1); return s; } /** * 集合遍历方式(输出顺序:从栈底到栈顶) * @return */ public static String printfStatck(){ // System.out.print("当前栈:"); String s=""; for (Character x : S) { // System.out.print(x); s=s+x; } return s; }}
参考资料:
程序设计语言编译原理(第3版)陈火旺 刘春林 谭庆平
参考博客:
地址一:http://blog.csdn.net/qq_24451605/article/details/50096487
地址二:http://blog.csdn.net/github_36601823/article/details/74090399
阅读全文
0 0
- 算符优先分析法
- 算符优先分析
- 算符优先分析
- 算符优先分析
- 算符优先分析 优先函数
- 编译原理(八) 算符优先分析法-分析过程
- 算符优先分析方法
- 编译原理(七) 算符优先分析法-构造算符优先关系表算法
- 自下而上的语法分析和算符优先分析法
- 编译原理实验3-算符优先分析法
- 算符优先分析表生成模拟
- 编译中的算符优先分析程序
- 编译原理算符优先分析算法
- 编译原理(七) 算符优先分析法(构造算符优先关系表算法及C++实现)
- 编译原理(七) 算符优先分析法(构造算符优先关系表算法及C++实现)
- 编译原理(七) 算符优先分析法(构造算符优先关系表算法及C++实现)
- 编译原理(八) 算符优先分析法(分析过程的算法和C++实现)
- 编译原理(八) 算符优先分析法(分析过程的算法和C++实现)
- java web mybatis 查询慢
- XGBoost解析系列-数据加载
- LRTimelapse Pro 4.8.3 Windows / Mac 简体中文 延时摄影处理软件
- 小而巧的bootstrap-wysiwyg 可以将任何一个div变成富文本编辑器
- 线程同步1 ------ 互斥锁
- 算符优先分析法
- 刷机软件-Duilib界面
- 机器学习---决策树算法
- JS用法之Object妙用一
- 音速启动-软件工具箱制作
- bond,team,br0
- 源码圈 300 胖友的书单整理(最后更新时间:2017.09.22)
- vue2.0之axios使用详解(一)
- 1056. Mice and Rice (25)