语法设计——基于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、构造其预测分析表,如
3、LL(1)文法的预测分析表的模型示意图
4、预测分析控制程序的算法流程
5、运行结果,示例如下
四、实验方式与要求
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)");
}
}
测试结果如下:
语法设计——基于LL(1)文法的预测分析表法的更多相关文章
- FIRST集合、FOLLOW集合、SELECT集合以及预测分析表地构造
FIRST集合.FOLLOW集合.SELECT集合以及预测分析表地构造 FIRST集合的简单理解就是推导出的字符串的开头终结符的集合. FOLLOW集合简单的理解就对于非终结符后面接的第一个终结符. ...
- 基于Office 365 无代码工作流分析-表单基本需求分析!
3.2表单的制作 基于下图的需求,我们须要定义例如以下的表单列表:
- 基于UML的毕业设计管理系统的分析与设计
基于UML的毕业设计管理系统的分析与设计 <本段与标题无关,自行略过 最近各种忙,天气不错,导师心情不错:“我们要写一个关于UML的专著”,一句话:“一个完整的系统贯穿整个UML的知识”:我:“ ...
- JavaScript笔记 – 程序语法设计
一.基础语法设计 JavaScript是可以与HTML标记语言混合.用于网页交互式的解释型脚本语言.由国际标准ECMAScript提供核心语言功能.文档对象模型(DOM)提供访问和操作网页内容的方法和 ...
- ANTLR 语法设计
下面学习如何编写语法. 如何定义语法规则 一种语言模式就是一种递归的语法结构. 我们需要从一系列有代表性的输入文件中归纳出一门语言的结构.在完成这样的归纳工作后,我们就可以正式使用ANTLR语法来表达 ...
- 业务接口+UI层的设计(基于Castle实现的Repository)
业务接口+UI层的设计(基于Castle实现的Repository) Repository层设计的文章见:[http://www.cnblogs.com/yomho/p/3297042.html] ...
- 多租户通用权限设计(基于casbin)
多租户通用权限设计(基于 casbin) 所谓权限控制, 概念并不复杂, 就是确认某个操作是否能做, 本质上仅仅就是个bool判断. 权限几乎是每个系统必不可少的功能, 和具体业务结合之后, 在系统中 ...
- 基于 Keras 用深度学习预测时间序列
目录 基于 Keras 用深度学习预测时间序列 问题描述 多层感知机回归 多层感知机回归结合"窗口法" 改进方向 扩展阅读 本文主要参考了 Jason Brownlee 的博文 T ...
- 树形结构的数据库表Schema设计-基于左右值编码
树形结构的数据库表Schema设计 程序设计过程中,我们常常用树形结构来表征某些数据的关联关系,如企业上下级部门.栏目结构.商品分类等等,通常而言,这些树状结构需要借助于数据库完 成持久化.然而目前的 ...
随机推荐
- 虚拟机中安装Virtualbox,嵌套的虚拟机不能运行64位系统
https://www.quora.com/Can-I-install-Virtualbox-in-a-virtual-machine Here is a previous question on Q ...
- Django 配置文件settings注解(含静态文件和上传文件配置)
基于Django1.11配置文件settings.py import os import sys # Build paths inside the project like this: os.path ...
- 产品经理说| AIOps 让告警变得更智能 (下)
AIOps 人工智能和IT运营支撑 Ops 之间的故事,愈演愈烈,已经成为当今运维圈的热门话题,我打算从2篇文档分享我们在 AIOps 上一些探索和实践.(上篇)主要介绍了为什么事件(告警)处理需要 ...
- 腾讯云Centos安装gitlab
参考了网上很多人写的安装教程,结果并不好,最后阅读了官方的英文api,才安装成功,这里记录下来,方便以后使用.我的安装环境为腾讯云主机Centos7.3 64bit gitlab官方api地址点我试试 ...
- mssql sqlserver 验证整型函数分享
转自:http://www.maomao365.com/?p=6227 摘要: 下文将制作一个isnumber验证整型的函数,供在sql脚本中做数值判断,如下所示: 例: 实现原理:判断 是否包含特殊 ...
- sql视图显示数据不对应
出现这样的原因是修改了表的结构,没有重新编译视图,这种情况出现的几率很少,并不是没有. 解决方法:重新编译一下该视图. 视图是一个虚表,是从一个或几个基本表(或视图)中导出的表,在系统的数据字典中仅存 ...
- 6. svg学习笔记-路径
路径相比于多边形<polygon>元素具有更强绘图能力,<polygon>元素可以绘制任意的多边形,而路径可以绘制任意的轮廓线,是线段,曲线,圆弧的组合形式.svg中可以使用& ...
- P1279 字串距离 dp 洛谷
题目描述 设有字符串X,我们称在X的头尾及中间插入任意多个空格后构成的新字符串为X的扩展串,如字符串X为”abcbcd”,则字符串“abcb□cd”,“□a□bcbcd□”和“abcb□cd□”都是X ...
- 在 Linux 中自动配置 IPv6 地址
在 Linux 中自动配置 IPv6 地址 在本文中,我们将学习如何为 ULA 自动配置 IP 地址. 何时使用唯一本地地址 唯一本地地址unique local addresses(ULA)使用 f ...
- UVA1471-Defense Lines(思维+STL)
Problem UVA1471-Defense Lines Accept: 297 Submit: 2776Time Limit: 9000 mSec Problem Description Aft ...