您的位置:首页 > 其它

编译作业——LR文法的语法分析器

2016-11-23 12:39 183 查看
依旧是编译的上机作业,第四次的了吧。

做一个LR的语法分析器。

文法是

E->E+T | T
T->T*F | F
F->(E) | id


然后如果用这个文法推LR(1)的状态,状态太多了,所以我换了一个,用

E->E+E|E*E|(E)|id


这个有二义性,左递归的文法推,只有10个状态,好手写分析表,同时里面还用了上一次作业的部分代码,以下是代码部分。

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.Set;

public class ThirdHW {
static String E="E",Ee="E'",T="T",Tt="T'",F="F",//代表各种非终结符
//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);
*/
}
//下面两个变量有违封装原则,不过东西小,看不出影响
static Integer timeForPutToMap=0;//全局变量用于下面的putToMap方法
static Map<String,Map<String,Action>> table=new HashMap<String,Map<String,Action>>();//全局变量,一个Action表
//用于构建诸如s3,r1,e1这样形式的一个类
static class  Action{
String SorR;
int state;
public Action(String SorR,Integer state){
this.SorR=SorR;
this.state=state;
}
public String getSorR(){
return SorR;
}
public int getState(){
return state;
}
@Override
public String toString(){
return SorR+" "+state;
}
}
public static Map<Integer,List<String>> produceEquation(){
Map<Integer,List<String>> ProduceEquation=new HashMap<Integer,List<String>>();
List<String> temp=new ArrayList<String>();
temp=fullList(new String[]{E,"+",E});
ProduceEquation.put(1,temp);
temp=fullList(new String[]{E,"*",E});
ProduceEquation.put(2,temp);
temp=fullList(new String[]{"(",E,")"});
ProduceEquation.put(3,temp);
temp=fullList(new String[]{id});
ProduceEquation.put(4,temp);
return ProduceEquation;
}
//goto表,没错,分析表action部分和goto部分是分开的,很奇葩
//原因是这样写方便(个人认为)
//Action的对象,不用和数字放在一个map里,泛型用起来舒服了
public static Map<String,Integer> GotoTable(){
Map<String,Integer> gotoTable=new HashMap<String,Integer>();
gotoTable.put("0",1);
gotoTable.put("2",6);
gotoTable.put("4",7);
gotoTable.put("5",8);
return gotoTable;
}
//action表,没错,分析表action部分和goto部分是分开的,很奇葩
public static Map<String,Map<String,Action>> ActionTable(){
Map<String,Action> tempList=null;
String s="s",e="e",r="r";
tempList=fullList(new Object[]{s,3,e,1,e,1,s,2,e,2,e,1});
putToMap(tempList);
tempList=fullList(new Object[]{e,3,s,4,s,5,e,3,e,2,"a",-1});
putToMap(tempList);
tempList=fullList(new Object[]{s,3,e,1,e,1,s,2,e,2,e,1});
putToMap(tempList);
tempList=fullList(new Object[]{r,4,r,4,r,4,r,4,r,4,r,4});
putToMap(tempList);
tempList=fullList(new Object[]{s,3,e,1,e,1,s,2,e,2,e,1});
putToMap(tempList);
putToMap(tempList);
tempList=fullList(new Object[]{e,3,s,4,s,5,e,3,s,9,e,4});
putToMap(tempList);
tempList=fullList(new Object[]{r,1,r,1,s,5,r,1,r,1,r,1});
putToMap(tempList);
tempList=fullList(new Object[]{r,2,r,2,r,2,r,2,r,2,r,2});
putToMap(tempList);
tempList=fullList(new Object[]{r,3,r,3,r,3,r,3,r,3,r,3});
putToMap(tempList);
return table;
}
//用于生成分析表的Action部分
//不想很傻地一个一个增添状态对应的条目,每次都写table.put((一个数字),tempList)干脆自动化一点
//缺点是引入了一个全局变量timeForPutToMap
public static void putToMap(Map<String,Action> tempList){
table.put(timeForPutToMap.toString(),tempList);
timeForPutToMap++;
}
/**
* 传入一个数组,填充成一个List,输入成对的String,int组合,每一对组合成一个Action
* @param object []args,注意,是偶数个,成对出现的的String、int
* @return List<Action>
*/
private static Map<String,Action> fullList(Object[] args){
Map<String,Action> temp=new HashMap<String,Action>();
String []SQE=new String[]{id,"+","*","(",")","$"};
for(int i=0;i<args.length;i+=2){
Action a=new Action((String)args[i], (Integer)args[i+1]);
temp.put(SQE[i/2],a);
}
return temp;
}
/**
* 传入一个数组,填充成一个List
* @param object []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, Action>> actionTable=ActionTable();
Map<String,Integer> gotoTable=GotoTable();
Map<Integer,List<String>> ProduceEquation=produceEquation();
LinkedList<String> stack=new LinkedList<String>();
stack.addFirst("0");
int point=0;
boolean successFlag=false;
/*
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,"$"};
//String[] test=new String[]{"(",")","$"};
//String[] test=new String[]{id,"*",id,"+",")",id,"$"};
//String[] test=new String[]{id,"*","+",")",id,id,"$"};
while(point<test.length){
Action a=actionTable.get(stack.getFirst()).get(test[point]);
//出错处理
//没有default处理
if(a.getSorR().equals("e")){
switch(a.getState()){
case 1:
System.out.println("缺少运算对象,可能是运算符输入过多,默认做‘移入一个id’处理");
error(test,point);
//point++;
stack.addFirst(id);
stack.addFirst("3");
break;
case 2:
System.out.println("不匹配的右括号");
error(test,point);
point++;
break;
case 3:
System.out.println("缺少算符,可能是运算对象输入过多,默认做‘移入一个+’处理");
error(test,point);
//point++;
stack.addFirst("+");
stack.addFirst("4");
break;
case 4:
System.out.println("缺少右括号");
error(test,point);
//point++;
stack.addFirst(")");
stack.addFirst("9");
break;
}
}else if(a.getSorR().equals("s")){//移进
System.out.println(stack.toString());
printString(test, point);
stack.addFirst(test[point]);
System.out.println("移进"+test[point]);
System.out.println("===========");
point++;
stack.addFirst(((Integer)a.getState()).toString());
}else if(a.getSorR().equals("r")){//归约
System.out.println(stack.toString());
printString(test, point);
//规约弹栈的操作
for(int i=0;i<ProduceEquation.get(a.getState()).size();){//缺省一条语句,没错,只有移出非终结符和终结符时i++,其他时候仅仅是移出,i不变
if(!stack.removeFirst().matches("[0-9]+")){
i++;
}
}
//记录栈顶状态的临时量
Integer state=Integer.parseInt(stack.getFirst());
//栈顶压入非终结符
stack.addFirst(E);
//通过非终结符和栈顶状态的临时量,定位新的栈顶状态,入栈
stack.addFirst(gotoTable.get(state.toString()).toString());
System.out.println("归约,使用产生式:E->"+ProduceEquation.get(a.getState()));
System.out.println("===========");
}else if(a.getSorR().equals("a")){//接受
successFlag=true;
System.out.println(stack.toString()+"->acc");
System.out.println("接受,识别结束");
break;
}
}
if(!successFlag){
System.out.println("识别结束,输入串有问题");
}
}
/**
* 用于从指定位置输出一个数组的一部分
* @param args 要输出的数组
* @param index 指定的输出起点
*/
public static void printString(String[] args,int index){
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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: