• 语法设计——基于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("步骤			 " + "符号栈		        " + "	输入串 			" + "所用产生式 ");
    		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 + "			" + analyzeStatck.toString() + "			" + str + "			"
    						+ 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 + "			" + analyzeStatck.toString() + "			" + str + "			" + "“"
    						+ 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" + "		");
    		analyzeTable[0][0] = "Nv/Nt";
    		// 初始化首行
    		for (int i = 0; i < ntArray.length; i++) {
    			if (ntArray[i].equals('ε')) {
    				ntArray[i] = '#';
    			}
    			System.out.print(ntArray[i] + "		");
    			analyzeTable[0][i + 1] = ntArray[i] + "";
    		}
     
    		System.out.println("");
    		for (int i = 0; i < nvArray.length; i++) {
    			// 首列初始化
    			System.out.print(nvArray[i] + "		");
    			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("		");
    					analyzeTable[i + 1][j + 1] = "";
    				} else {
    					System.out.print(nvArray[i] + "->" + findUseExp + "		");
    					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)");
    			}
    
    }
    

    测试结果如下:

  • 相关阅读:
    如何构建一个优秀的移动网站?谷歌专家教你25招(三)[转]
    如何构建一个优秀的移动网站?谷歌专家教你25招(二)[转]
    如何构建一个优秀的移动网站?谷歌专家教你25招(一)[转]
    如何做到Zero Downtime重启Go服务?
    Go语言AST尝试
    Database Go and JSON
    "创业"半年
    打造完美的go开发环境
    [ReactiveCocoa]最简单的RAC入门操作
    [Node.js]expressjs简单测试连接mysql
  • 原文地址:https://www.cnblogs.com/ECJTUACM-873284962/p/10217985.html
Copyright © 2020-2023  润新知