import java.io.*;
import java.util.*;
public class YCFXF {
BufferedReader reader = null;
private List<String> wf = new ArrayList<String>();
private List<String> N = new ArrayList<String>();
private List<String> V = new ArrayList<String>();
private Map<String,List<String>> first = new HashMap<String, List<String>>();
private Map<String,List<String>> follow = new HashMap<String, List<String>>();
private Map<String,String> waitAdd = new HashMap<String, String>();
private Scanner scanner = null;
public YCFXF() throws FileNotFoundException {
scanner = new Scanner(System.in);
reader = new BufferedReader(
new InputStreamReader(new FileInputStream(new File("F:\Workplace\IDEA_Workplace\SchoolProect\软件构造实验4\wf.txt")))
);
}
public void getWf() throws IOException {
System.out.println("所有的文法:");
String temp;
while (!(temp = reader.readLine()).equals("#")){
wf.add(temp);
System.out.println(temp);
}
}
public void getN() throws IOException {
System.out.println("所有的非终结符:");
String temp;
while (!(temp = reader.readLine()).equals("#")){
N.add(temp);
System.out.println(temp);
}
}
public void getV() throws IOException {
System.out.println("所有的终结符:");
String temp;
while (!(temp = reader.readLine()).equals("#")){
V.add(temp);
System.out.println(temp);
}
}
public void getFirst(){
String wfStr;
Collections.reverse(wf);
for (int i = 0; i < wf.size(); i++) {
List<String> wfFirst = new ArrayList<String>();
wfStr = wf.get(i);
//前后分割
String[] strings = wfStr.split("->");
//文法产生的式子
String[] split = strings[1].split("\|");
//计算first集合
for (int j = 0; j < split.length; j++) {
String firstChar = String.valueOf(split[j].charAt(0));
if (N.contains(firstChar)){
wfFirst.addAll(first.get(firstChar));
}else {
wfFirst.add(firstChar);
}
}
first.put(strings[0],wfFirst);
}
Collections.reverse(wf);
}
//获取follow集和
public void getFollow(){
for (int i = 0; i < N.size(); i++) {
String n = N.get(i);
List<String> wfFollow = new ArrayList<String>();
if (n.equals("E")){
wfFollow.add("#");
}
List<String> hasGet = new ArrayList<String>();
//每个文法都遍历
for (int j = 0; j < wf.size(); j++) {
String wfStr = wf.get(j);
String[] split = wfStr.split("->");
String[] strings = split[1].split("\|");
for (int k = 0; k < strings.length; k++) {
if (strings[k].contains(n)){
int indexOf = strings[k].indexOf(n);
//如果不为最后一位
if (indexOf != (strings[k].length()-1) ){
String followChar = String.valueOf(strings[k].charAt(indexOf + 1));
if (hasGet.contains(followChar)){
continue;
}
if (V.contains(followChar) && !followChar.equals("^")){
//如果后方接的是终结符
wfFollow.add(String.valueOf(strings[k].charAt(indexOf + 1)));
}
else if (N.contains(followChar)){
//如果接的是非终结符
wfFollow.addAll(first.get(followChar));
hasGet.add(followChar);
if (haveK(followChar)){
try {
wfFollow.addAll(follow.get(split[0]));
}catch (NullPointerException e){
waitAdd.put(n,split[0]);
}
}
}
}else {
//如果是最后一位
if (!n.equals(split[0])){
try {
wfFollow.addAll(follow.get(split[0]));
}catch (NullPointerException e){
waitAdd.put(n,split[0]);
}
}
}
}
}
}
follow.put(n,wfFollow);
}
//再将添加失败的添加进去
Set<String> keySet = waitAdd.keySet();
for (String s : keySet) {
String s1 = waitAdd.get(s);
List<String> stringList = follow.get(s);
stringList.addAll(follow.get(s1));
follow.remove(s);
follow.put(s,stringList);
}
}
//判断该文法是否有空
private boolean haveK(String c) {
boolean haveK = false;
List<String> strings = first.get(c);
if (strings.contains("^")){
haveK = true;
}
return haveK;
}
//显示follow集
public void showFirst(){
System.out.println("First集合:");
Set<String> strings = first.keySet();
for (String key : strings) {
System.out.println(key + ":" + first.get(key));
}
}
//显示follow集
public void showFollow(){
System.out.println("Follow集合:");
Set<String> strings = follow.keySet();
for (String key : strings) {
System.out.println(key + ":" + follow.get(key));
}
}
//处理follow集,清除相同元素及空
public void chandleMap(){
Set<String> keySet = follow.keySet();
for (String s : keySet) {
List<String> stringList = follow.get(s);
Set set = new HashSet(stringList);
set.remove("^");
stringList.clear();
stringList.addAll(set);
}
}
//构建预测分析表
public String[][] buildTable(){
String[][] table = new String[N.size()][V.size()+1];
for (int i = 0; i < wf.size(); i++) {
//当前的文法
String wfStr = wf.get(i);
String[] split = wfStr.split("->");
//当前的非终结符
String NStr = split[0];
//当前的产生式
String tuidaoStr = split[1];
//分割多个产生式
String[] tuidao = tuidaoStr.split("\|");
//如果是一个产生式,那么该产生式就是所有的first集的产生式
if (tuidao.length == 1){
List<String> Nfirst = first.get(NStr);
for (String s : Nfirst) {
int charIndex = getCharIndex(s);
table[i][charIndex] = N.get(i) + "->" + tuidao[0];
}
}else {
for (int j = 0; j < tuidao.length; j++) {
String s = tuidao[j];
String startChar = String.valueOf(s.charAt(0));
//如果是空的话
if (startChar.equals("^")){
List<String> nFollow = follow.get(NStr);
for (String follow : nFollow) {
table[i][getCharIndex(follow)] = N.get(i) + "->^";
}
continue;
}
int charIndex = getCharIndex(startChar);
table[i][charIndex] = N.get(i) + "->" + s;
}
}
}
System.out.println("预测分析表:");
System.out.println(" + - * / ( ) i #");
for (int i = 0; i < N.size(); i++) {
System.out.printf(N.get(i)+" ");
for (int j = 0; j < V.size()+1; j++) {
System.out.print(table[i][j] + " ");
}
System.out.println();
}
return table;
}
//获取终结符在预测表中的位置
public int getCharIndex(String c){
if (c.equals("#")){
return V.size();
}
return V.indexOf(c);
}
public void fx(String[][] table, String s) {
Stack<String> stack = new Stack<String>();
List<String> stackStr = new ArrayList<String>();
stack.push("#");
stack.push("E");
stackStr.add("#");
stackStr.add("E");
String sy = s;
System.out.println("分析栈 剩余串 产生式");
while (!sy.equals("")){
String fxChar = String.valueOf(sy.charAt(0));
String peek = stack.peek();
System.out.printf("%-10s%10s ",stackStr.toString(), sy);
//如果和栈顶元素相等
if (fxChar.equals(peek)){
System.out.println(fxChar + "匹配");
stack.pop();
stackStr.remove(stackStr.size()-1);
String[] split = sy.split("|");
sy = "";
for (int i = 1; i < split.length; i++) {
sy+=split[i];
}
continue;
}
//如果和栈顶元素不相等
int i = N.indexOf(peek);
int j = getCharIndex(fxChar);
try {
String s1 = table[i][j];
System.out.println(s1);
String[] split = s1.split("->");
String[] strings = split[1].split("|");
//先出栈,再替换
stack.pop();
stackStr.remove(stackStr.size()-1);
for (int k = (strings.length-1); k >=0 ; k--) {
if (strings[k].equals("^")){
continue;
}
stack.push(strings[k]);
stackStr.add(strings[k]);
}
}catch (NullPointerException e){
System.err.printf("分析错误!");
System.exit(1);
}
}
System.out.println("分析成功!");
}
public void useYcfxf(String s) throws IOException {
getWf();
getN();
getV();
getFirst();
showFirst();
getFollow();
chandleMap();
showFollow();
String[][] table = buildTable();
fx(table,s);
}
}