实现预测分析法的原理其实很简答,步骤如下:
1.判断文法有没有左递归,若有左递归,则对该文法消除左递归
2.对处理后的文法进行遍历,求出终结符号和非终结符号
3.求出first集合和follow集合
4.判断是不是LL(1)文法,若是,则构建预测分表
5.若是LL(1)文法,输入一个句子,模拟输出进栈出栈情况
截图如下:
代码如下:
package cn.mahui;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class Function {
public static List<String> oneFirstList=new ArrayList<>();
public static List<String> oneFollowList=new ArrayList<>();
/**
* 从指定文件中读取文法
* @param path(文件的路径)
* @return
* @throws IOException
*/
public static String readGrammarFile(String path) throws IOException{
StringBuilder grammar=new StringBuilder();
File file=new File(path);
@SuppressWarnings("resource")
BufferedReader bufferedReader=new BufferedReader(new FileReader(file));
String readline;
while((readline=bufferedReader.readLine())!=null){
grammar.append(readline+"\n");
}
return grammar.toString();
}
/**
* 获得文法的产生式
* @param scanner(输入的文法)
* @return
*/
public static List<String> getGrammar(String scanner){
List<String> oldList=new ArrayList<>();
String[] grammarItems=scanner.split(" |\n");
for(int i=0;i<grammarItems.length;i++){
oldList.add(grammarItems[i]);
}
return oldList;
}
/**
* 获得每一条产生式
* @param scanner(输入的文法)
* @return
*/
public static List<String> getGrammarItems(String scanner){
List<String> oldList=new ArrayList<>();
List<String> oldListItems=new ArrayList<>();
String[] grammarItems=scanner.split(" |\n");
for(int i=0;i<grammarItems.length;i++){
oldList.add(grammarItems[i]);
String[] items=grammarItems[i].split(">|\\|");
//添加每一条产生式
for(int k=1;k<items.length;k++)
oldListItems.add(grammarItems[i].charAt(0)+"-->"+items[k]);
}
return oldListItems;
}
/**
* 如果vn包含str,则返回真,不包含返回false
* @param vn
* @param ch(要判断的字符串)
* @return
*/
public static boolean isContain(List<String> vn,String str){
for(int i=0;i<vn.size();i++){
if(vn.get(i).equals(str)){
return true;
}
}
return false;
}
/**
* 获得所有非终结符
* @param grammarItem(输入的文法)
* @return
*/
public static List<String> getVN(String grammarItems){
List<String> vn=new ArrayList<>();
String[] string=grammarItems.split("\n");
for(int i=0;i<string.length;i++){
int index=string[i].indexOf("-");
String str=string[i].substring(0, index);
if(vn.size()==0){
vn.add(str);
}else{
if(!isContain(vn, str)){
vn.add(str);
}
}
}
return vn;
}
/**
* 消除文法的左递归
* @param oldListItems(未消除左递归的每一台产生式的集合)
* @return
*/
public static List<String> removeLeftRecursive(List<String> oldListItems){
List<String> newList=new ArrayList<>();
for(int i=0;i<oldListItems.size();i++){
if(oldListItems.get(i).charAt(0)==oldListItems.get(i).charAt(4)){
for(int j=0;j<oldListItems.size();j++){
if(oldListItems.get(j).startsWith(""+oldListItems.get(i).charAt(0))
&&oldListItems.get(j).length()==5){
newList.add(oldListItems.get(i).charAt(0)+"-->"+oldListItems.get(j).charAt(4)+oldListItems.get(i).charAt(0)+"’");
newList.add(oldListItems.get(i).charAt(0)+"’"+"-->"+oldListItems.get(i).substring(5, oldListItems.get(i).length())+oldListItems.get(i).charAt(0)+"’");
//~代表空
newList.add(oldListItems.get(i).charAt(0)+"’"+"-->"+"~");
}
}
}else{
int tag=0;
for(int k=0;k<newList.size();k++){
if(newList.get(k).contains(oldListItems.get(i).substring(1, oldListItems.get(i).length()))){
tag=1;
break;
}
}
if(tag==0){
newList.add(oldListItems.get(i));
}
}
}
return newList;
}
/**
* 获得非终结符号的first集合
* @param vn(非终结符号的集合)
* @param newList( 消除左递归后的文法)
* @return
*/
public static Map<String,List<String>> getFirst(List<String> vn,List<String> newList){
Map<String,List<String>> firstList=new HashMap<>();
for(int i=0;i<vn.size();i++){
oneFirstList.clear();
getOneFirst(vn.get(i),newList);
List<String> temp=new ArrayList<>();
for(int k=0;k<oneFirstList.size();k++){
temp.add(oneFirstList.get(k));
}
firstList.put(vn.get(i), temp);
}
return firstList;
}
/**
* 得到任意一个非终结符号的first集合
* @param vnItem(任意一个非终结符号)
* @param newList(消除左递归后的文法)
* @return
*/
public static void getOneFirst(String vnItem,List<String> newList){
for(int i=0;i<newList.size();i++){
if(vnItem.length()==1){