語法設計——基於LL(1)文法的預測分析表法


實驗二、語法設計——基於LL(1)文法的預測分析表法

一、實驗目的

通過實驗教學,加深學生對所學的關於編譯的理論知識的理解,增強學生對所學知識的綜合應用能力,並通過實踐達到對所學的知識進行驗證。通過對基於LL(1)文法的預測分析表法DFA模擬程序實驗,使學生掌握確定的自上而下的語法分析的實現技術,及具體實現方法。通過本實驗加深對語詞法分析程序的功能及實現方法的理解 。

二、實驗環境

供Windows系統的PC機,可用C++/C#/Java等編程工具編寫

三、實驗內容

1、自己定義一個LL(1)文法

示例如(僅供參考) G[E]:E →TE' E' → +TE' | ε

T →FT' T' → *FT' | ε F → i | ( E )

2、構造其預測分析表,如

img
3、LL(1)文法的預測分析表的模型示意圖

img

4、預測分析控制程序的算法流程

img

5、運行結果,示例如下

img

四、實驗方式與要求

1、設計的下推自動機具有通用性,上機編程實現;

2、實驗報告格式要求書寫要點:概要設計(總體設計思想);詳細設計(程序主流程、自動機的存儲格式、關鍵函數的流程圖);結果分析(輸入與輸出結果、存在問題及有待改進善的地方、實驗心得);

3、實驗報告限4頁內。

設計思路:我就講解一下核心部分代碼,首先,進棧函數在 298 行處左右,我們用 ArrayList 去定義一個動態數組 analyzeProduces ,我們定義了一個棧 analyzeStatck ,而這個棧在我們在定義 Analyzer 類中初始化化過了,所以在創建 analyzeStatck 中首先會進行初始化操作, push 了一個 # ,所以 analyzeStatck 棧中會存在 # 這個字符(以這個 # 作為標記),然后 302 行,我們向 analyzeStack 中推入開始符號,也就是我們在主函數設置的字符 E ,然后打印出開始符號以及一些格式要求(步驟,符號棧,輸入串,產生式等等),設置 index 的值來記錄走過的步驟次數 。

308 行開始,我們開始對棧進行分析。我們設置一個判斷棧 analyzeStatck 是否為空,由前面可知,棧中存在 #E 兩個字符,顯然字符是非空的,通過 index++ 記錄當前的步數,然后我們去通過 peek 函數去彈出當前棧頂元素的第一個字符,通過和剩余輸入串 str 的第一個字符進行匹配。

如果棧頂元素與當前輸入串的第一個字符不可以匹配,我們就去分析表 TextUtil 中利用函數 findUseExp 去找到這個產生式,而 findUseExp 函數我們通過去定義了一個哈希表去存儲查找出來的棧頂元素,用一個集合 keySet 去存儲哈希表的所有鍵值,通過 for 循環,利用定義一個紅黑樹 treeSet 去存取表達式,然后去進行匹配,如果在紅黑樹中包含了當前查找的字符,我們就返回當前從哈希表中所獲取到的表達式。將當前所找到的產生式存入到 nowUseExpStr 中,打印出此時所進行到的步驟值,符號棧,輸入棧,產生式。316 行,我們創建一個分析棧 produce 去記錄上一步的值(位置,符號棧,輸入串),判斷當前的產生式是否為空,如果不為空,設置下當前分析棧的產生式,將整個分析棧加入到動態數組 analyzeProduces 中,再將之前的分析棧中的棧頂彈出,如果當前的表達式不為空且第一個字符不是空字符,我們再將需要用到的表達式進行反序入棧。

如果棧頂元素與當前輸入串的第一個字符可以匹配,分析棧出棧,串去掉一位,創建一個新的分析棧 produce ,記錄上一步的值(位置,符號棧,輸入串),設置當前產生式為當前輸入串的第一個字符可以匹配,將整個分析棧加入到動態數組 analyzeProduces 中,再將之前的分析棧中的棧頂彈出,將剩余的字符串記錄在 str 字符串中。

注:produce 相當於是一個持久化存儲中間參數的一個分析棧

實驗代碼如下:

package python;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet; 
import java.util.Stack;

/**
 * @author Angel_Kitty
 * @createTime 2018年11月24日 上午0:46:33
 */

class TextUtil {
	/**
	 * (3)B->aA,=Follow(B)
	 * 
	 * @param nvSet
	 * @param itemCharStr
	 * @param a
	 * @param expressionMap
	 * @return
	 */
	public static boolean containsbA(TreeSet<Character> nvSet, String itemCharStr, Character a,
			HashMap<Character, ArrayList<String>> expressionMap) {
		String aStr = a.toString();
		String lastStr = itemCharStr.substring(itemCharStr.length() - 1);
		if (lastStr.equals(aStr)) {
			return true;
		}
		return false;
 
	}
 
	/**
	 * 形如aBb,b=空
	 * 
	 * @param nvSet
	 * @param itemCharStr
	 * @param a
	 * @param expressionMap
	 * @return
	 */
	public static boolean containsbAbIsNull(TreeSet<Character> nvSet, String itemCharStr, Character a,
			HashMap<Character, ArrayList<String>> expressionMap) {
		String aStr = a.toString();
		if (containsAB(nvSet, itemCharStr, a)) {
			Character alastChar = getAlastChar(itemCharStr, a);
			System.out.println("----------------+++++++++++++++++++--" + expressionMap.toString());
			ArrayList<String> arrayList = expressionMap.get(alastChar);
			if (arrayList.contains("ε")) {
				System.out.println(alastChar + "  contains('ε')" + aStr);
				return true;
			}
		}
		return false;
 
	}
 
	/**
	 * 是否包含這種的字符串<Br>
	 * (2)Ab,=First(b)-ε,直接添加終結符
	 * 
	 * @param str
	 * @param a
	 * @return
	 */
	public static boolean containsAb(TreeSet<Character> ntSet, String itemCharStr, Character a) {
		String aStr = a.toString();
		if (itemCharStr.contains(aStr)) {
			int aIndex = itemCharStr.indexOf(aStr);
			String findStr;
			try {
				findStr = itemCharStr.substring(aIndex + 1, aIndex + 2);
			} catch (Exception e) {
				return false;
			}
			if (ntSet.contains(findStr.charAt(0))) {
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}
 
	/**
	 * 是否包含這種的字符串<Br>
	 * (2).2Ab,=First(b)-ε
	 * 
	 * @param str
	 * @param a
	 * @return
	 */
	public static boolean containsAB(TreeSet<Character> nvSet, String itemCharStr, Character a) {
		String aStr = a.toString();
		if (itemCharStr.contains(aStr)) {
			int aIndex = itemCharStr.indexOf(aStr);
			String findStr;
			try {
				findStr = itemCharStr.substring(aIndex + 1, aIndex + 2);
			} catch (Exception e) {
				return false;
			}
			if (nvSet.contains(findStr.charAt(0))) {
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}
 
	/**
	 * 獲取A后的字符
	 * 
	 * @param itemCharStr
	 * @param a
	 * @return
	 */
	public static Character getAlastChar(String itemCharStr, Character a) {
		String aStr = a.toString();
		if (itemCharStr.contains(aStr)) {
			int aIndex = itemCharStr.indexOf(aStr);
			String findStr = "";
			try {
				findStr = itemCharStr.substring(aIndex + 1, aIndex + 2);
			} catch (Exception e) {
				return null;
			}
			return findStr.charAt(0);
		}
		return null;
	}
 
	/**
	 * 是否為ε開始的
	 * 
	 * @param selectExp
	 * @return
	 */
	public static boolean isEmptyStart(String selectExp) {
		char charAt = selectExp.charAt(0);
		if (charAt == 'ε') {
			return true;
		}
		return false;
	}
 
	/**
	 * 是否是終結符開始的
	 * 
	 * @param ntSet
	 * @param selectExp
	 * @return
	 */
	public static boolean isNtStart(TreeSet<Character> ntSet, String selectExp) {
		char charAt = selectExp.charAt(0);
		if (ntSet.contains(charAt)) {
			return true;
		}
		return false;
	}
 
	/**
	 * 是否是非終結符開始的
	 * 
	 * @param nvSet
	 * @param selectExp
	 * @return
	 */
	public static boolean isNvStart(TreeSet<Character> nvSet, String selectExp) {
		char charAt = selectExp.charAt(0);
		if (nvSet.contains(charAt)) {
			return true;
		}
		return false;
	}
 
	/**
	 * 查找產生式
	 * 
	 * @param selectMap
	 * @param peek
	 *            當前Nv
	 * @param charAt
	 *            當前字符
	 * @return
	 */
	public static String findUseExp(TreeMap<Character, HashMap<String, TreeSet<Character>>> selectMap, Character peek,
			char charAt) {
		try {
			HashMap<String, TreeSet<Character>> hashMap = selectMap.get(peek);
			Set<String> keySet = hashMap.keySet();
			for (String useExp : keySet) {
				TreeSet<Character> treeSet = hashMap.get(useExp);
				if (treeSet.contains(charAt)) {
					return useExp;
				}
			}
		} catch (Exception e) {
			return null;
		}
		return null;
	}
}

class Analyzer {
 
	public Analyzer() {
		super();
		analyzeStatck = new Stack<Character>();
		// 結束符進棧
		analyzeStatck.push('#');
	}
 
	private ArrayList<AnalyzeProduce> analyzeProduces;
 
	/**
	 * LL(1)文法
	 */
	private Gs ll1Gs;
 
	public Gs getLl1Gs() {
		return ll1Gs;
	}
 
	public void setLl1Gs(Gs ll1Gs) {
		this.ll1Gs = ll1Gs;
	}
 
	/**
	 * 開始符
	 */
	private Character startChar;
 
	/**
	 * 分析棧
	 */
	private Stack<Character> analyzeStatck;
	/**
	 * 剩余輸入串
	 */
	private String str;
	/**
	 * 推導所用產生或匹配
	 */
	private String useExp;
 
	public ArrayList<AnalyzeProduce> getAnalyzeProduces() {
		return analyzeProduces;
	}
 
	public void setAnalyzeProduces(ArrayList<AnalyzeProduce> analyzeProduces) {
		this.analyzeProduces = analyzeProduces;
	}
 
	public Character getStartChar() {
		return startChar;
	}
 
	public void setStartChar(Character startChar) {
		this.startChar = startChar;
	}
 
	public Stack<Character> getAnalyzeStatck() {
		return analyzeStatck;
	}
 
	public void setAnalyzeStatck(Stack<Character> analyzeStatck) {
		this.analyzeStatck = analyzeStatck;
	}
 
	public String getStr() {
		return str;
	}
 
	public void setStr(String str) {
		this.str = str;
	}
 
	public String getUseExp() {
		return useExp;
	}
 
	public void setUseExp(String useExp) {
		this.useExp = useExp;
	}
 
	/**
	 * 分析
	 */
	//進棧 flag is here
	public void analyze() {
		analyzeProduces = new ArrayList<AnalyzeProduce>();
 
		// 開始符進棧
		analyzeStatck.push(startChar);
		System.out.println("開始符:" + startChar);
		System.out.println("步驟\t\t\t " + "符號棧\t\t        " + "\t輸入串 \t\t\t" + "所用產生式 ");
		int index = 0;
		// 開始分析
		// while (analyzeStatck.peek() != '#' && str.charAt(0) != '#') {
		while (!analyzeStatck.empty()) {
			index++;
			//返回棧頂元素
			if (analyzeStatck.peek() != str.charAt(0)) {
				// 到分析表中找到這個產生式
				String nowUseExpStr = TextUtil.findUseExp(ll1Gs.getSelectMap(), analyzeStatck.peek(), str.charAt(0));
				System.out.println(index + "\t\t\t" + analyzeStatck.toString() + "\t\t\t" + str + "\t\t\t"
						+ analyzeStatck.peek() + "->" + nowUseExpStr);
				AnalyzeProduce produce = new AnalyzeProduce();
				produce.setIndex(index);
				produce.setAnalyzeStackStr(analyzeStatck.toString());
				produce.setStr(str);
				if (null == nowUseExpStr) {
					produce.setUseExpStr("無法匹配!");
				} else {
					produce.setUseExpStr(analyzeStatck.peek() + "->" + nowUseExpStr);
				}
				analyzeProduces.add(produce);
				// 將之前的分析棧中的棧頂出棧
				analyzeStatck.pop();
				// 將要用到的表達式入棧,反序入棧
				if (null != nowUseExpStr && nowUseExpStr.charAt(0) != 'ε') {
					for (int j = nowUseExpStr.length() - 1; j >= 0; j--) {
						char currentChar = nowUseExpStr.charAt(j);
						analyzeStatck.push(currentChar);
					}
				}
				continue;
			}
			// 如果可以匹配,分析棧出棧,串去掉一位
			if (analyzeStatck.peek() == str.charAt(0)) {
				System.out.println(index + "\t\t\t" + analyzeStatck.toString() + "\t\t\t" + str + "\t\t\t" + "“"
						+ str.charAt(0) + "”匹配");
				AnalyzeProduce produce = new AnalyzeProduce();
				produce.setIndex(index);
				produce.setAnalyzeStackStr(analyzeStatck.toString());
				produce.setStr(str);
				produce.setUseExpStr("“" + str.charAt(0) + "”匹配");
				analyzeProduces.add(produce);
				analyzeStatck.pop();
				str = str.substring(1);
				continue;
			}
		}
 
	}
 
}

class AnalyzeProduce implements Serializable{
	private static final long serialVersionUID = 10L;
	private Integer index;
	private String analyzeStackStr;
	private String str;
	private String useExpStr;
 
	public Integer getIndex() {
		return index;
	}
 
	public void setIndex(Integer index) {
		this.index = index;
	}
 
	public String getAnalyzeStackStr() {
		return analyzeStackStr;
	}
 
	public void setAnalyzeStackStr(String analyzeStackStr) {
		this.analyzeStackStr = analyzeStackStr;
	}
 
	public String getStr() {
		return str;
	}
 
	public void setStr(String str) {
		this.str = str;
	}
 
	public String getUseExpStr() {
		return useExpStr;
	}
 
	public void setUseExpStr(String useExpStr) {
		this.useExpStr = useExpStr;
	}
 
}

class Gs implements Serializable {
 
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
 
	public Gs() {
		super();
		gsArray = new ArrayList<String>();
		nvSet = new TreeSet<Character>();
		ntSet = new TreeSet<Character>();
		firstMap = new HashMap<Character, TreeSet<Character>>();
		followMap = new HashMap<Character, TreeSet<Character>>();
		selectMap = new TreeMap<Character, HashMap<String, TreeSet<Character>>>();
	}
 
	private String[][] analyzeTable;
 
	/**
	 * Select集合
	 */
	private TreeMap<Character, HashMap<String, TreeSet<Character>>> selectMap;
	/**
	 * LL(1)文法產生集合
	 */
	private ArrayList<String> gsArray;
	/**
	 * 表達式集合
	 */
	private HashMap<Character, ArrayList<String>> expressionMap;
	/**
	 * 開始符
	 */
	private Character s;
	/**
	 * Vn非終結符集合
	 */
	private TreeSet<Character> nvSet;
	/**
	 * Vt終結符集合
	 */
	private TreeSet<Character> ntSet;
	/**
	 * First集合
	 */
	private HashMap<Character, TreeSet<Character>> firstMap;
	/**
	 * Follow集合
	 */
	private HashMap<Character, TreeSet<Character>> followMap;
 
	public String[][] getAnalyzeTable() {
		return analyzeTable;
	}
 
	public void setAnalyzeTable(String[][] analyzeTable) {
		this.analyzeTable = analyzeTable;
	}
 
	public TreeMap<Character, HashMap<String, TreeSet<Character>>> getSelectMap() {
		return selectMap;
	}
 
	public void setSelectMap(TreeMap<Character, HashMap<String, TreeSet<Character>>> selectMap) {
		this.selectMap = selectMap;
	}
 
	public HashMap<Character, TreeSet<Character>> getFirstMap() {
		return firstMap;
	}
 
	public void setFirstMap(HashMap<Character, TreeSet<Character>> firstMap) {
		this.firstMap = firstMap;
	}
 
	public HashMap<Character, TreeSet<Character>> getFollowMap() {
		return followMap;
	}
 
	public void setFollowMap(HashMap<Character, TreeSet<Character>> followMap) {
		this.followMap = followMap;
	}
 
	public HashMap<Character, ArrayList<String>> getExpressionMap() {
		return expressionMap;
	}
 
	public void setExpressionMap(HashMap<Character, ArrayList<String>> expressionMap) {
		this.expressionMap = expressionMap;
	}
 
	public ArrayList<String> getGsArray() {
		return gsArray;
	}
 
	public void setGsArray(ArrayList<String> gsArray) {
		this.gsArray = gsArray;
	}
 
	public Character getS() {
		return s;
	}
 
	public void setS(Character s) {
		this.s = s;
	}
 
	public TreeSet<Character> getNvSet() {
		return nvSet;
	}
 
	public void setNvSet(TreeSet<Character> nvSet) {
		this.nvSet = nvSet;
	}
 
	public TreeSet<Character> getNtSet() {
		return ntSet;
	}
 
	public void setNtSet(TreeSet<Character> ntSet) {
		this.ntSet = ntSet;
	}
 
	/**
	 * 獲取非終結符集與終結符集
	 * 
	 * @param gsArray
	 * @param nvSet
	 * @param ntSet
	 */
	public void getNvNt() {
		for (String gsItem : gsArray) {
			String[] nvNtItem = gsItem.split("->");
			String charItemStr = nvNtItem[0];
			char charItem = charItemStr.charAt(0);
			// nv在左邊
			nvSet.add(charItem);
		}
		for (String gsItem : gsArray) {
			String[] nvNtItem = gsItem.split("->");
			// nt在右邊
			String nvItemStr = nvNtItem[1];
			// 遍歷每一個字
			for (int i = 0; i < nvItemStr.length(); i++) {
				char charItem = nvItemStr.charAt(i);
				if (!nvSet.contains(charItem)) {
					ntSet.add(charItem);
				}
			}
		}
	}
 
	/**
	 * 初始化表達式集合
	 */
	public void initExpressionMaps() {
		expressionMap = new HashMap<Character, ArrayList<String>>();
		for (String gsItem : gsArray) {
			String[] nvNtItem = gsItem.split("->");
			String charItemStr = nvNtItem[0];
			String charItemRightStr = nvNtItem[1];
			char charItem = charItemStr.charAt(0);
			if (!expressionMap.containsKey(charItem)) {
				ArrayList<String> expArr = new ArrayList<String>();
				expArr.add(charItemRightStr);
				expressionMap.put(charItem, expArr);
			} else {
				ArrayList<String> expArr = expressionMap.get(charItem);
				expArr.add(charItemRightStr);
				expressionMap.put(charItem, expArr);
			}
		}
	}
 
	/**
	 * 獲取First集
	 */
	public void getFirst() {
		// 遍歷所有Nv,求出它們的First集合
		Iterator<Character> iterator = nvSet.iterator();
		while (iterator.hasNext()) {
			Character charItem = iterator.next();
			ArrayList<String> arrayList = expressionMap.get(charItem);
			for (String itemStr : arrayList) {
				boolean shouldBreak = false;
				// Y1Y2Y3...Yk
				for (int i = 0; i < itemStr.length(); i++) {
					char itemitemChar = itemStr.charAt(i);
					TreeSet<Character> itemSet = firstMap.get(charItem);
					if (null == itemSet) {
						itemSet = new TreeSet<Character>();
					}
					shouldBreak = calcFirst(itemSet, charItem, itemitemChar);
					if (shouldBreak) {
						break;
					}
				}
			}
		}
	}
 
	/**
	 * 計算First函數
	 * 
	 * @param itemSet
	 * @param charItem
	 * @param itemitemChar
	 * @return
	 */
	private boolean calcFirst(TreeSet<Character> itemSet, Character charItem, char itemitemChar) {
		// get ago
		// TreeSet<Character> itemSet = new TreeSet<Character>();
		// 將它的每一位和Nt判斷下
		// 是終結符或空串,就停止,並將它加到FirstMap中
		if (itemitemChar == 'ε' || ntSet.contains(itemitemChar)) {
			itemSet.add(itemitemChar);
			firstMap.put(charItem, itemSet);
			// break;
			return true;
		} else if (nvSet.contains(itemitemChar)) {// 這一位是一個非終結符
			ArrayList<String> arrayList = expressionMap.get(itemitemChar);
			for (int i = 0; i < arrayList.size(); i++) {
				String string = arrayList.get(i);
				char tempChar = string.charAt(0);
				calcFirst(itemSet, charItem, tempChar);
			}
		}
		return true;
	}
 
	/**
	 * 獲取Follow集合
	 */
	public void getFollow() {
		for (Character tempKey : nvSet) {
			TreeSet<Character> tempSet = new TreeSet<Character>();
			followMap.put(tempKey, tempSet);
		}
		// 遍歷所有Nv,求出它們的First集合
		Iterator<Character> iterator = nvSet.descendingIterator();
		// nvSet.descendingIterator();
 
		while (iterator.hasNext()) {
			Character charItem = iterator.next();
			System.out.println("charItem:" + charItem);
			Set<Character> keySet = expressionMap.keySet();
			for (Character keyCharItem : keySet) {
				ArrayList<String> charItemArray = expressionMap.get(keyCharItem);
				for (String itemCharStr : charItemArray) {
					System.out.println(keyCharItem + "->" + itemCharStr);
					TreeSet<Character> itemSet = followMap.get(charItem);
					calcFollow(charItem, charItem, keyCharItem, itemCharStr, itemSet);
				}
			}
		}
	}
 
	/**
	 * 計算Follow集
	 * 
	 * @param putCharItem
	 *            正在查詢item
	 * @param charItem
	 *            待找item
	 * @param keyCharItem
	 *            節點名
	 * @param itemCharStr
	 *            符號集
	 * @param itemSet
	 *            結果集合
	 */
	private void calcFollow(Character putCharItem, Character charItem, Character keyCharItem, String itemCharStr,
			TreeSet<Character> itemSet) {
		///////
		// (1)A是S(開始符),加入#
		if (charItem.equals(s)) {
			itemSet.add('#');
			System.out.println("---------------find S:" + charItem + "   ={#}+Follow(E)");
			followMap.put(putCharItem, itemSet);
			// return;
		}
		// (2)Ab,=First(b)-ε,直接添加終結符
		if (TextUtil.containsAb(ntSet, itemCharStr, charItem)) {
			Character alastChar = TextUtil.getAlastChar(itemCharStr, charItem);
			System.out.println("---------------find Ab:" + itemCharStr + "    " + charItem + "   =" + alastChar);
			itemSet.add(alastChar);
			followMap.put(putCharItem, itemSet);
			// return;
		}
		// (2).2AB,=First(B)-ε,=First(B)-ε,添加first集合
		if (TextUtil.containsAB(nvSet, itemCharStr, charItem)) {
			Character alastChar = TextUtil.getAlastChar(itemCharStr, charItem);
			System.out.println(
					"---------------find AB:" + itemCharStr + "    " + charItem + "   =First(" + alastChar + ")");
			TreeSet<Character> treeSet = firstMap.get(alastChar);
			itemSet.addAll(treeSet);
			if (treeSet.contains('ε')) {
				itemSet.add('#');
			}
			itemSet.remove('ε');
			followMap.put(putCharItem, itemSet);
			///////////////////////
			if (TextUtil.containsbAbIsNull(nvSet, itemCharStr, charItem, expressionMap)) {
				char tempChar = TextUtil.getAlastChar(itemCharStr, charItem);
				System.out.println("tempChar:" + tempChar + "  key" + keyCharItem);
				if (!keyCharItem.equals(charItem)) {
					System.out.println("---------------find tempChar bA: " + "tempChar:" + tempChar + keyCharItem
							+ "   " + itemCharStr + "    " + charItem + "   =Follow(" + keyCharItem + ")");
					Set<Character> keySet = expressionMap.keySet();
					for (Character keyCharItems : keySet) {
						ArrayList<String> charItemArray = expressionMap.get(keyCharItems);
						for (String itemCharStrs : charItemArray) {
							calcFollow(putCharItem, keyCharItem, keyCharItems, itemCharStrs, itemSet);
						}
					}
				}
			}
		}
		// (3)B->aA,=Follow(B),添加followB
		if (TextUtil.containsbA(nvSet, itemCharStr, charItem, expressionMap)) {
			if (!keyCharItem.equals(charItem)) {
				System.out.println("---------------find bA: " + keyCharItem + "   " + itemCharStr + "    " + charItem
						+ "   =Follow(" + keyCharItem + ")");
				Set<Character> keySet = expressionMap.keySet();
				for (Character keyCharItems : keySet) {
					ArrayList<String> charItemArray = expressionMap.get(keyCharItems);
					for (String itemCharStrs : charItemArray) {
						calcFollow(putCharItem, keyCharItem, keyCharItems, itemCharStrs, itemSet);
					}
				}
			}
		}
	}
 
	/**
	 * 獲取Select集合
	 */
	public void getSelect() {
		// 遍歷每一個表達式
		// HashMap<Character, HashMap<String, TreeSet<Character>>>
		Set<Character> keySet = expressionMap.keySet();
		for (Character selectKey : keySet) {
			ArrayList<String> arrayList = expressionMap.get(selectKey);
			// 每一個表達式
			HashMap<String, TreeSet<Character>> selectItemMap = new HashMap<String, TreeSet<Character>>();
			for (String selectExp : arrayList) {
				/**
				 * 存放select結果的集合
				 */
				TreeSet<Character> selectSet = new TreeSet<Character>();
				// set里存放的數據分3種情況,由selectExp決定
				// 1.A->ε,=follow(A)
				if (TextUtil.isEmptyStart(selectExp)) {
					selectSet = followMap.get(selectKey);
					selectSet.remove('ε');
					selectItemMap.put(selectExp, selectSet);
				}
				// 2.Nt開始,=Nt
				// <br>終結符開始
				if (TextUtil.isNtStart(ntSet, selectExp)) {
					selectSet.add(selectExp.charAt(0));
					selectSet.remove('ε');
					selectItemMap.put(selectExp, selectSet);
				}
				// 3.Nv開始,=first(Nv)
				if (TextUtil.isNvStart(nvSet, selectExp)) {
					selectSet = firstMap.get(selectKey);
					selectSet.remove('ε');
					selectItemMap.put(selectExp, selectSet);
				}
				selectMap.put(selectKey, selectItemMap);
			}
		}
	}
 
	/**
	 * 生成預測分析表
	 */
	public void genAnalyzeTable() throws Exception {
		Object[] ntArray = ntSet.toArray();
		Object[] nvArray = nvSet.toArray();
		// 預測分析表初始化
		analyzeTable = new String[nvArray.length + 1][ntArray.length + 1];
 
		// 輸出一個占位符
		System.out.print("Nv/Nt" + "\t\t");
		analyzeTable[0][0] = "Nv/Nt";
		// 初始化首行
		for (int i = 0; i < ntArray.length; i++) {
			if (ntArray[i].equals('ε')) {
				ntArray[i] = '#';
			}
			System.out.print(ntArray[i] + "\t\t");
			analyzeTable[0][i + 1] = ntArray[i] + "";
		}
 
		System.out.println("");
		for (int i = 0; i < nvArray.length; i++) {
			// 首列初始化
			System.out.print(nvArray[i] + "\t\t");
			analyzeTable[i + 1][0] = nvArray[i] + "";
			for (int j = 0; j < ntArray.length; j++) {
				String findUseExp = TextUtil.findUseExp(selectMap, Character.valueOf((Character) nvArray[i]),
						Character.valueOf((Character) ntArray[j]));
				if (null == findUseExp) {
					System.out.print("\t\t");
					analyzeTable[i + 1][j + 1] = "";
				} else {
					System.out.print(nvArray[i] + "->" + findUseExp + "\t\t");
					analyzeTable[i + 1][j + 1] = nvArray[i] + "->" + findUseExp;
				}
			}
			System.out.println();
		}
	}
}

/*主程序*/
public class LL1_modify {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		// // LL(1)文法產生集合
				ArrayList<String> gsArray = new ArrayList<String>();
				// // Vn非終結符集合
				// TreeSet<Character> nvSet = new TreeSet<Character>();
				// // Vt終結符集合
				// TreeSet<Character> ntSet = new TreeSet<Character>();
				Gs gs = new Gs();
				initGs(gsArray);
				gs.setGsArray(gsArray);
				// getNvNt(gsArray, gs.getNvSet(), gs.getNtSet());
				gs.getNvNt();
				gs.initExpressionMaps();
				gs.getFirst();
				// 設置開始符
				gs.setS('E');
				gs.getFollow();
				gs.getSelect();
				// 創建一個分析器
				Analyzer analyzer = new Analyzer();
				analyzer.setStartChar('E');
				analyzer.setLl1Gs(gs);
				analyzer.setStr("i+i*i#");
				analyzer.analyze();
				gs.genAnalyzeTable();
				System.out.println("");
			}
		 
			/**
			 * 獲取非終結符集與終結符集
			 * 
			 * @param gsArray
			 * @param nvSet
			 * @param ntSet
			 */
			private static void getNvNt(ArrayList<String> gsArray, TreeSet<Character> nvSet, TreeSet<Character> ntSet) {
				for (String gsItem : gsArray) {
					String[] nvNtItem = gsItem.split("->");
					String charItemStr = nvNtItem[0];
					char charItem = charItemStr.charAt(0);
					// nv在左邊
					nvSet.add(charItem);
				}
				for (String gsItem : gsArray) {
					String[] nvNtItem = gsItem.split("->");
					// nt在右邊
					String nvItemStr = nvNtItem[1];
					// 遍歷每一個字
					for (int i = 0; i < nvItemStr.length(); i++) {
						char charItem = nvItemStr.charAt(i);
						if (!nvSet.contains(charItem)) {
							ntSet.add(charItem);
						}
					}
				}
		 
			}
		 
			/**
			 * 初始化LL(1)文法
			 * 
			 * @param gsArray
			 */
			private static void initGs(ArrayList<String> gsArray) {
				// Z相當於E',Y相當於T'
				gsArray.add("E->TZ");
				gsArray.add("Z->+TZ");
				gsArray.add("Z->ε");
				gsArray.add("Z->+TZ");
				gsArray.add("T->FY");
				gsArray.add("Z->+TZ");
				gsArray.add("Y->*FY");
				gsArray.add("Y->ε");
				gsArray.add("F->i");
				gsArray.add("F->(E)");
			}

}

測試結果如下:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM