计算FIRST集、FOLLOW集和构造LL(1)分析表

基本思路

计算FIRST集、FOLLOW集和构造LL(1)分析表_第1张图片
计算FIRST集、FOLLOW集和构造LL(1)分析表_第2张图片
计算FIRST集、FOLLOW集和构造LL(1)分析表_第3张图片

数据结构

HashMap:用来实现非终结符和对应FIRST和FOLLOW集的映射
HashSet<Character>:用来保存的FIRST和FOLLOW集的集合
ArrayList<String>:用来保存将产生式根据|分割后各个候选式

文法

E->TZ
Z->+TZ|ε
T->FY
Y->*FY|ε
F->(E)|i

源代码

package compile;

import java.util.*;
import java.util.Map.Entry;

public class test {
     
	// 文法开始符
	public char S='E';
	// 存储终结符
	public String[] VT = new String[] {
      "i","+","*","(",")","#"};
	//public String[] VT;
	// 存储非终结符
	public String[] VN = new String[] {
      "E", "Z", "T", "Y", "F" };
	// 文法G[E]
	public String[] left = {
      "E", "Z", "T", "Y", "F" };
	public String[] grammer = {
      "TZ", "+TZ|ε", "FY", "*FY|ε", "(E)|i" };
	// first集
	public HashMap<Character, HashSet<Character>> firstSet = new HashMap<Character, HashSet<Character>>();
	// follow集
	public HashMap<Character, HashSet<Character>> followSet = new HashMap<Character, HashSet<Character>>();
	// 产生式
	public HashMap<Character, ArrayList<String>> experssionSet = new HashMap<>();
	// 分析表
	public String[][] chart;
	// 表的行数
	public int rows;
	// 表的列数
	public int cols;

	// 将各个候选式分开,保存在experssionSet
	public void init() {
     // 初始化experssionSet
		int i = 0;
		for (String s : grammer) {
     
			char key = left[i++].charAt(0);// 找到产生式左部
			//System.out.println(key);
			ArrayList<String> list = experssionSet.containsKey(key) ? experssionSet.get(key) : new ArrayList<>();// 获得相应key的ArrayList
			if (s.contains("|")) {
     
				String[] str = s.split("\\|");
				int len = str.length;
				for (int j = 0; j < len; j++) {
     // 根据|分割产生式
					//System.out.println(str[j] + ",");
					list.add(str[j]);
				}
			} else {
     
				//System.out.println(s + ",");
				list.add(s);
			}
			experssionSet.put(key, list);
		}
	}

	// 判断是否为终结符
	public boolean isVT(char c) {
     
		String s = String.valueOf(c);
		for (String temp : VT) {
     
			if (s.equals(temp))
				return true;
		}
		return false;
	}

	// 判断是否为空字
	public boolean isEmptyWord(char c) {
     
		if (c == 'ε')
			return true;
		return false;
	}

	// 判断是否为非终结符
	public boolean isVN(char c) {
     
		String s = String.valueOf(c);
		for (String temp : VN) {
     
			if (s.equals(temp))
				return true;
		}
		return false;
	}


	// 计算first集
	public void getFirst(char ch) {
     //求得字符的first集
		HashSet<Character> set = firstSet.containsKey(ch) ? firstSet.get(ch) : new HashSet<>();
		ArrayList<String> list = experssionSet.get(ch);// 得到ch对应的ArrayList

		for (String s : list) {
     
			char head = s.charAt(0);
			if (isVT(head)) {
     // 终结符时
				set.add(head);
				firstSet.put(ch, set);
			} else if (isEmptyWord(head)) {
     // 空字时
				set.add('ε');
				firstSet.put(ch, set);
			} else {
     // 非终结符时
				// whenVN(ch, list);
				int i = 0;
				// HashSet set = null;
				while (i < s.length()) {
     // 遍历s的字符
					char c = s.charAt(i);
					// System.out.println(c);
					HashSet<Character> tempset = null;
					if (firstSet.containsKey(c)) {
     // 得到第i个字符的first集
						tempset = firstSet.get(c);
					} else {
     
						if (ch == c)
							continue;// 如果求自身的first集,直接进行下一次循环
						getFirst(c);
						tempset = firstSet.get(c);
					}
					if (tempset.contains('ε')) {
     
						tempset.remove('ε');
						set.addAll(tempset);
						firstSet.put(ch, set);// 目的是去掉ε
						i++;
						continue;
					} else {
     
						// set.remove('ε');
						set.addAll(tempset);
						firstSet.put(ch, set);
						break;
					}
				}
				if (i == s.length()) {
     // 都存在ε,则把ε加入first集
					set.add('ε');
					firstSet.put(ch, set);
				}
			}
		}

	}

	public Set<Character> getFirst(String sentence) {
     // 求字符串的first集
		Set<Character> set = new HashSet<>();
		if (sentence.equals("ε")) {
     
			set.add('ε');
		} else {
     
			// 不为空字时,遍历整个句子的字符
			for (int i = 0; i < sentence.length(); i++) {
     
				if (isVT(sentence.charAt(i))) {
     // 为终结符时,直接加入first集
					set.add(sentence.charAt(i));
					break;
				} else {
     
					// 不为终结符时,获取该非终结符的first集合
					HashSet<Character> temp = firstSet.get(sentence.charAt(i));
					if (!temp.contains('ε')) {
     
						set.addAll(temp);
						break;
					} else {
     
						// 非终结符含空字时
						if (i == sentence.length() - 1) {
     
							set.addAll(temp);
						} else {
     
							temp.remove('ε');
							set.addAll(temp);
						}
					}
				}
			}
		}
		return set;
	}

	public void getFollow(char ch) {
     
		HashSet<Character> set = followSet.containsKey(ch) ? followSet.get(ch) : new HashSet<>();
		if (S == ch) {
     // 对于文法开始符,将#放在follow集
			set.add('#');
			followSet.put(ch, set);
		}
		for (Map.Entry<Character, ArrayList<String>> entry : experssionSet.entrySet()) {
     // 遍历experssionSet,找到出现字符ch的位置
			char key = entry.getKey();
			ArrayList<String> value = entry.getValue();
			for (String s : value) {
     // 对键值遍历
				for (int i = 0; i < s.length(); i++) {
     // 找到字符ch的位置
					if (s.charAt(i) == ch) {
     
						if (i == (s.length() - 1)) {
     // 非终结符后没有字符,使用规则3
							HashSet<Character> tempset = null;
							if (ch != key) {
     // 避免出现套娃求follow(ch)
								if (followSet.containsKey(key)) {
     // 得到follow(key)加入到set中
									tempset = followSet.get(key);
								} else {
     
									getFollow(key);
									tempset = followSet.get(key);
								}
								set.addAll(tempset);
								followSet.put(ch, set);
							}
						} else {
     // 非终结符后有字符,使用规则2
							int j = i + 1;
							String tempstr = s.substring(j);
							Set<Character> tempset = getFirst(tempstr);
							if (tempset.contains('ε')) {
     
								tempset.remove('ε');
								set.addAll(tempset);
								HashSet<Character> tempset3 = null;
								if (ch != key) {
     // 避免出现套娃求follow(ch)
									if (followSet.containsKey(key)) {
     
										tempset3 = followSet.get(key);
									} else {
     
										getFollow(key);
										tempset3 = followSet.get(key);
									}
									set.addAll(tempset3);
									// followSet.put(ch, set);
								}
							} else {
     // 不包含ε
								set.addAll(tempset);
							}
							followSet.put(ch, set);
						}
						// break;
					}

				}
			}
		}
	}

	public void print() {
     // 打印first集和follow集
		for (Entry<Character, HashSet<Character>> entry : firstSet.entrySet()) {
     /// first(A)
			char key = entry.getKey();
			System.out.print("FIRST(" + key + ")= ");
			HashSet<Character> set = firstSet.get(key);
			Iterator<Character> iterator = set.iterator();
			while (iterator.hasNext()) {
     
				System.out.print(iterator.next()+" ");
			}
			System.out.println();
		}
		for (Entry<Character, HashSet<Character>> entry : followSet.entrySet()) {
     
			char key = entry.getKey();
			System.out.print("FOLLOW(" + key + ")= ");
			HashSet<Character> set = followSet.get(key);
			Iterator<Character> iterator = set.iterator();
			while (iterator.hasNext()) {
     
				System.out.print(iterator.next()+" ");
			}
			System.out.println();
		}
	}

	public void LLChart() {
     // 定义分析表
		rows = VN.length + 1;
		cols = VT.length + 1;
		chart = new String[rows][cols];
		chart[0][0] = "VN/VT";
		for (int i = 1; i < rows; i++) {
     // 构造表的第一行
			chart[i][0] = VN[i - 1];
		}
		for (int j = 1; j < cols; j++) {
     // 构造表的第一列
			chart[0][j] = VT[j - 1];
		}
		initChart();
		printChart();
	}

	public void initChart() {
     // 构造分析表的内容
		for (int i = 1; i < rows; i++) {
     
			for (int j = 1; j < cols; j++) {
     
				char row = chart[i][0].charAt(0); // 非终结符,表行
				char col = chart[0][j].charAt(0); // 终结符,表列
				// 非终结符的first集合包含该终结符时
				if (firstSet.get(row).contains(col)) {
     
					ArrayList<String> list = experssionSet.get(row);
					if (list.size() == 1) {
     
						chart[i][j] = list.get(0);
					} else {
     
						// 非唯一候选式时,加入对应的候选式,对应的候选式即首字母为终结符的候选式
						for (String str : list) {
     
							if (str.indexOf(col) == 0) {
     
								chart[i][j] = str;
								break;
							}
						}
					}
				} else if (firstSet.get(row).contains('ε')) {
     
					HashSet<Character> set = followSet.get(row);
					// 若该follow集合包含该终结符时
					if (set.contains(col)) {
     
						chart[i][j] = "ε"; // 表元素添加推导空字的候选式
					}

				}
			}
		}
	}
	public void blank(String s) {
     
		int i;
		for(i=0;i<(8-s.length());i++) {
     
			System.out.print(" ");
		}
	}
	public void printChart() {
     
		System.out.println("LL(1)分析表为");
		for (int i = 0; i < rows; i++) {
     
			for (int j = 0; j < cols; j++) {
     
				if(chart[i][j]==null) {
     
					System.out.print("        ");
				}else {
     
					System.out.print(chart[i][j]);
					blank(chart[i][j]);
				}			
			}
			System.out.println();
		}
	}

	public static void main(String[] args) {
     
		test d = new test();
		d.init(); 
		for (String str : d.left) {
      
			char ch = str.charAt(0); 
			d.getFirst(ch); 
		}
		for (String str : d.left) {
      
			char ch = str.charAt(0);	
			d.getFollow(ch); 
		}
		d.print();
		d.LLChart();
	}
}

实验结果

FIRST(T)= ( i 
FIRST(E)= ( i 
FIRST(F)= ( i 
FIRST(Y)= ε * 
FIRST(Z)= ε + 
FOLLOW(T)= # ) + 
FOLLOW(E)= # ) 
FOLLOW(F)= # ) * + 
FOLLOW(Y)= # ) + 
FOLLOW(Z)= # ) 
LL(1)分析表为
VN/VT   i       +       *       (       )       #       
E       TZ                      TZ                      
Z               +TZ                     ε       ε       
T       FY                      FY                      
Y               ε       *FY             ε       ε       
F       i                       (E)                     

你可能感兴趣的:(编译器)