今天老师要让我们写一个语法分析器,,布置的内容是,给一个已经消除了左递归和回溯的文法,
让我们写出整个语法分析过程,,我竟然记错了,,花了几个小时写了个,消除左递归
《直接递归的消除》 时间有点紧,写的有点乱,(关键是没按照命名标准来命名),以后再改吧,,没用什么数据结构,都是java内部lang.string中的方法,
若有道友写出C语言版本的,可以分享出来(谢谢)
《循环左递归》以后再写,时间好紧
文件:D:\\text.txt
内容:(可以自行修改),我是按照这个来的,,其他的也都可以
E=E+T/T
T=T*F/F
F=(E)/i
结果:
O=+TO/ε
E=TO
K=*FK/ε
T=FK
F=(E)/i
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
public class yufafenxi {
public yufafenxi() {
// TODO Auto-generated constructor stub
try {
readFile();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int length=0;
//读取文件,得到每行的内容
public ArrayList<String> readFile() throws Exception{
FileInputStream fileInputStream=new FileInputStream("D:\\text.txt");
InputStreamReader reader=new InputStreamReader(fileInputStream);
BufferedReader bufferedReader=new BufferedReader(reader);
String text=null;
ArrayList<String> all=new ArrayList<>();
while((text=bufferedReader.readLine())!=null){
all.add(text);
}
length=all.size();
return all;
}
//得到P非终结字符的字符数组{S T F}
public char[] getP(ArrayList<String> list){
char[] state=new char[1024];
for(int i=0;i<list.size();i++){
String current=list.get(i);
state[i]=current.toCharArray()[0];//得到状态S T F
}
return state;
}
//得到候选集合{E+T,T,T*F,F,(E),i}
public ArrayList<String> getHouxuanstring(ArrayList<String> list){
ArrayList<String> houxuanAll=new ArrayList<>();
for(int i=0;i<list.size();i++){
String current=list.get(i);
String waitcurrent=current.substring(2, current.length());
houxuanAll.add(waitcurrent);
}
return houxuanAll;
}
//得到候选分割的集合{E+T,T}{T*F,F}{(E),i}
public String[] getJihe(String text){
String waitcurrent=text.substring(2, text.length());
String[] currentAll=waitcurrent.split("/");//得到候选式存入字符串数组
return currentAll;
}
//得到原始首符集{E,T,T,F,(,i}
public HashMap<Integer, String> getHouxuanshi(ArrayList<String> list){
HashMap<Integer, String>map=new HashMap<>();
for(int i=0;i<list.size();i++){
String current=list.get(i);
String waitcurrent=current.substring(2, current.length());
String[] currentAll=waitcurrent.split("/");//得到候选式存入字符串数组,,后续会转变为字符数组
String word="";
for(int j=0;j<currentAll.length;j++){
word+=currentAll[j].charAt(0);//得到首位字符
}
map.put(i,word);//得到首符集,每行的首字符(合起来存为一个字符串,以后可以分割)
}
return map;
}
/**
* P与原始首符集匹配,相等则存在左递归,消除左递归,生成新的文法
* @param p 文法左端非终结符
* @param map p的first集合
* @param list 每行的文法
*/
public ArrayList<String> removeLeftDigui(char[] p,HashMap<Integer, String> map,ArrayList<String> list){
ArrayList<String> newList=new ArrayList<>();
String longText="";
String aChange="";
//先比较左端非终结符和各自的FIRSE集合,此处为一对多的匹配
char[] needChar={'Q','W','P','L','M','N','K','O'};//新的左端非终结符
//生成新的文法是,每次从中拿一个作为左端非终结符
ArrayList<String> Char=new ArrayList<>();
for(int i=0;i<needChar.length;i++){
Char.add(needChar[i]+"");
}
for(int i=0;i<length;i++){
//再次循环达到一对F(1)匹配,一对F(2)匹配...
char[] houxuanshi=map.get(i).toCharArray();//每行的first集合
String houxuanText=new String(houxuanshi);
char use=Char.get(Char.size()-1).charAt(0);//新的非终结符
Char.remove(Char.size()-1);//移除已经用过的字符
String hang=list.get(i);//i行的文法
for(int j=0;j<houxuanshi.length;j++){
//i行存在左递归,则
if(houxuanText.contains(p[i]+"")){
String[] allHouxuanshi=getJihe(hang);
/**
* 候选式FIRSE与P的比较
* 1:不相同
* 2:相同
*/
if(p[i]==houxuanshi[j]){
/**
* 生成新的候选式,如E+T
* +T——>allHouxuanshi[j].substring(1, allHouxuanshi[j].length())
* O——>use
* longText为新生成的一行文法
*/
String newText=allHouxuanshi[j].substring(1, allHouxuanshi[j].length())+use;
longText=longText+newText+"/";
}
if(p[i]!=houxuanshi[j]){
String newText=allHouxuanshi[j]+use;
aChange=aChange+newText+"/";
}
}
}
if(longText.equals(""))continue;
//新文法存入list中
//得到新生成的文法行,候选式中需要添加空字符
String AllLongText=use+"="+longText+"ε";
newList.add(AllLongText);
/**
* 两个字符串变量每经一轮循环都置空,因为已经生成了一行新的文法
* 下一轮循环会生成新的文法,所以需要置空
*/
AllLongText="";
longText="";
//得到改变的文法行,候选式中不需要空字符
String AllaChange=p[i]+"="+aChange;
newList.add(AllaChange);
/**
* 同上
*/
AllaChange="";
aChange="";
//将存在左递归的行置空,省下来的都是不存在左递归的行,直接添加到新文法中
list.set(i, "");
}
//去掉最后的/字符
for(int i=0;i<newList.size();i++){
String CurrentElement=newList.get(i);
if(CurrentElement.endsWith("/")){
CurrentElement=CurrentElement.substring(0, CurrentElement.length()-1);
newList.set(i, CurrentElement);
}
}
//将不存在左递归的行,添加到新文法
for(int i=0;i<list.size();i++){
if(!list.get(i).equals("")){
newList.add(list.get(i));
}
}
return newList;
}
//输出新的文法
public void printNewWenfa(ArrayList<String> arrayList){
for(int i=0;i<arrayList.size();i++){
System.out.println(arrayList.get(i));
}
}
public static void main(String[] args) throws Exception {
yufafenxi yufafenxi=new yufafenxi();//初始化程序
ArrayList<String> list=yufafenxi.readFile();//读取文件,得到所有行的字符串
char[] p=yufafenxi.getP(list);//得到左端非终结符
yufafenxi.getHouxuanstring(list);//得到候选集合(未使用)
HashMap<Integer, String> map=yufafenxi.getHouxuanshi(list);//得到首符集即各行的FIRST集合
ArrayList<String> arrayList=yufafenxi.removeLeftDigui(p, map, list);//消除直接左递归
yufafenxi.printNewWenfa(arrayList);//打印新的文法
}
}