编译作业——LL(1)文法的语法分析器
2016-11-17 14:40
579 查看
又一次的编译上机作业,做了些修改和注释,放到博客上来
注意:
以下代码的分析表是写死了的,所以仅仅只能针对文法:
代码可能还有漏洞,使用还请通读
注意:
以下代码的分析表是写死了的,所以仅仅只能针对文法:
E->TE'(1) T->FT'(2) E'->+TE'|e (3) T'->*FT'|e (4) F->(E)|id (5) e代表空串
代码可能还有漏洞,使用还请通读
package SecondHW; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Scanner; import java.util.Set; public class SecondHw { static String E="E",Ee="E'",T="T",Tt="T'",F="F",//代表各种非终结符 e="e",//表示空串 synch="synch",//同步记号,用于标记错误 id="id";//一个终结符 static Set<String> unLimitedSign=new HashSet<String>(); static{//初始化 非终结符的集合 unLimitedSign.add(E); unLimitedSign.add(Ee); unLimitedSign.add(T); unLimitedSign.add(Tt); unLimitedSign.add(F); } //创建分析预测表 public static Map<String,Map<String,List<String>>> staticTable(){ Map<String,Map<String,List<String>>> table=new HashMap<String, Map<String,List<String>>>(); Map<String,List<String>> tempMap=new HashMap<String, List<String>>(); List<String> tempList=null; //表的第一行 //第一个、第二个 tempList=fullList(new String[]{T,Ee}); tempMap.put(id, tempList);//加入id列 tempMap.put("(",tempList);//加入(列 tempList=fullList(new String[]{synch}); tempMap.put(")",tempList); tempMap.put("$",tempList); table.put(E,tempMap);//加到E行 //表的第二行 tempMap=new HashMap<String, List<String>>(); tempList=fullList(new String[]{"+",T,Ee}); tempMap.put("+", tempList); tempList=fullList(new String[]{e}); tempMap.put(")",tempList); tempMap.put("$",tempList); table.put(Ee,tempMap); //第三行 tempMap=new HashMap<String, List<String>>(); tempList=fullList(new String[]{F,Tt}); tempMap.put(id,tempList); tempMap.put("(",tempList); tempList=fullList(new String[]{synch}); tempMap.put(")",tempList); tempMap.put("$",tempList); tempMap.put("+", tempList); table.put(T,tempMap); //第四行 tempMap=new HashMap<String, List<String>>(); tempList=fullList(new String[]{e}); tempMap.put("+", tempList); tempMap.put(")",tempList); tempMap.put("$",tempList); tempList=fullList(new String[]{"*",F,Tt}); tempMap.put("*",tempList); table.put(Tt,tempMap); //第五行 tempMap=new HashMap<String, List<String>>(); tempList=fullList(new String[]{"id"}); tempMap.put(id,tempList); tempList=fullList(new String[]{"(",E,")"}); tempMap.put("(",tempList); tempList=fullList(new String[]{synch}); tempMap.put(")",tempList); tempMap.put("$",tempList); tempMap.put("+", tempList); tempMap.put("*", tempList); table.put(F,tempMap); return table; } //废弃方法 本来是想实现Map的级联put,简化staticTable,发现不可能,如果要写需要创建新类覆盖Map方法或者包装Map private static Map<String,List<String>> fullMap(String key,List<String> value){ Map<String,List<String>> temp=new HashMap<String, List<String>>(); temp.put(key,value); return temp; } /** * 传入一个数组,填充成一个List * @param String []args * @return List<String> */ private static List<String> fullList(String[] args){ List<String> temp=new ArrayList<String>(); for(String s: args){ temp.add(s); } return temp; } public static void main(String[] args){ Map<String,Map<String,List<String>>> analysisTable=staticTable(); LinkedList<String> stack=new LinkedList<String>(); stack.addFirst("$"); stack.addFirst(E); /* Scanner sc=new Scanner(System.in); System.out.println("输入一个记号流的串,注意每个终结符需要以空格隔开 "); String[] test=sc.nextLine().split(" "); sc.close(); */ //输入记号流 //三个测试用例 //String[] test=new String[]{id,"*",id,"+",id,"$"}; //String[] test=new String[]{id,"*",id,"+",")",id,"$"}; String[] test=new String[]{id,"*","+",")",id,"$"}; List<String> temp=new ArrayList<String>(); int point=0; while((!stack.getFirst().equals("$")||stack.isEmpty())&&point<test.length){//循环终止的情况+出错的情况(栈空、输入记号流指针到头了) if(stack.getFirst().equals(e)){//检测空串 stack.removeFirst(); System.out.println("弹出空串 ,栈内元素:"+stack); }else if(stack.getFirst().equals(test[point])){//终结符匹配,弹出 且point++ System.out.println("匹配弹出"+stack.removeFirst()+" ,栈内元素:"+stack); point++; printString(test,point); }else if(!unLimitedSign.contains(stack.getFirst())){//如果是终结符,且没有在上一步处理,说明出错 //对于右括号的特殊处理 //针对记号流中只有左括号,没有右括号的情况,将栈中右括号弹出 if(stack.getFirst().equals(")")){ System.out.println("出错1,没有匹配的括号,指出错误位置并略过"); error(test,point); stack.removeFirst(); }else{ System.out.println("出错2,不能识别的终结符,略过这一个输入记号:"+test[point]); error(test,point); point++; } continue; }else{//对非终结符进行推导+入栈 temp=analysisTable.get(stack.getFirst()).get(test[point]); if(temp==null){//取得分析预测表对应记录,如果得到的是空集,代表出错了 System.out.println("出错3,没有匹配的产生式,略过这一个输入记号: "+test[point]); error(test,point); point++; continue; } //处理匹配错误,这里比书上多加了对右括号的特殊处理 //针对输入记号流只有右括号的情况,略过右括号 //如果不将右括号单独处理,遇到右括号的同步记号,极有可能输入记号流经过若干次到e的推导,直接识别结束 else if(temp.get(0).equals("synch")){ if(test[point].equals(")")){ System.out.println("出错4,不匹配的),略过终结符:)"); error(test,point); point++; }else{ System.out.println("出错5,不能识别的终结符,弹出栈顶:"+stack.removeFirst()); error(test,point); } }else{ stack.removeFirst(); for(int i=temp.size()-1;i>=0;i--){ stack.addFirst(temp.get(i)); } System.out.println("产生式推导,新栈内 :"+stack); } } } //这是记号流没识别完 if(point<test.length-1){ System.out.println("记号流输入有误,此后串不再识别"); error(test,point); } //这是栈没弹完 if(!stack.getFirst().equals("$")){ System.out.println("记号流输入有误,栈中还剩元素"); System.out.println(stack); } System.out.println("记号流已经识别完毕"); } /** * 用于从指定位置输出一个数组的一部分 * @param args 要输出的数组 * @param index 指定的输出起点 */ public static void printString(String[] args,int index){ System.out.print("串中还剩:"); for(int i=index;i<args.length;i++){ System.out.print(args[i]); } System.out.println(); } /** * 用于展示输入记号流的出错位置 * @param args 输入的记号流,终结符的数组 * @param index 出错的位置 */ public static void error(String[] args,int index){ for(int i=0;i<args.length;i++){ System.out.print(args[i]+"\t"); } System.out.println(); for(int i=0;i<args.length;i++){ if(i==index){ System.out.print("↑这里有错"); }else System.out.print("\t"); } System.out.println(); } }
相关文章推荐
- 编译原理:LL(1)文法 语法分析器(预测分析表法)
- 【编译原理】LL1文法语法分析器
- 编译原理:LL(1)文法 语法分析器(预测分析表法)
- 编译作业——LR文法的语法分析器
- 编译原理FIRST集、FOLLOW集、SELECT集求法通俗解释 & LL(1)文法判定
- 编译原理:first集合和follow集合的求法及LL(1)文法判定
- 编译原理LL(1)文法实验报告
- 编译原理(五) LL(1)文法分析法(预测分析表的构造算法C++实现)
- 编译原理_简单优先文法_语法分析器_Java
- 编译原理之LL(1)文法分析(使用分析表)
- 计算机编译原理习作——LL(1)语法分析器
- 编译原理上机作业2——LL(1)语法分析
- 编译原理 实验2 语法分析器的构造 LL(1)
- 编译原理实验4——LL(1)文法分析
- 编译原理之LL(1) 、LR(0)、SLR、LR(1)、LALR文法的对比
- 编译原理之ll(1)文法判断和左递归问题
- 编译原理 LL1文法First集算法实现
- 编译原理(六) LL(1)文法分析法(分析过程的C++实现)
- 【编译原理】LL(1)文法分析全过程(FIRST/FLLOW/SELECT集等)实现(c++语言)
- 编译原理LL(1)文法