语法分析器
实验步骤
1.2.1 1. 文法
- E->TE’
- E’->+TE’|ε
- T->FT’
- T’->*FT’|ε
- F->(E)|i
1.2.2 2. 程序描述(LL(1)文法)
本程序是基于已构建好的某一个语法的预测分析表来对用户的输入字符串进行分析,判断输入的字符串是否属于该文法的句子。
基本实现思想:接收用户输入的字符串(字符串以“#”表示结束)后,对用做分析栈的一维数组和存放分析表的二维数组进行初始化。然后取出分析栈的栈顶字符,判断是否为终结符,若为终结符则判断是否为“#”且与当前输入符号一样,若是则语法分析结束,输入的字符串为文法的一个句子,否则出错若不为“#”且与当前输入符号一样则将栈顶符号出栈,当前输入符号从输入字符串中除去,进入下一个字符的分析。若不为“#”且不与当前输入符号一样,则出错。
1.2.3 3.判断是否LL(1)文法
要判断是否为LL(1)文法,需要输入的文法G有如下要求:
- 具有相同左部的规则的SELECT集两两不相交,即: SELECT(A→?)∩ SELECT(A→?)= ?
- 如果输入的文法都符合以上的要求,则该文法可以用LL(1)方法分析。
- 算法描述如下:
把第一条产生式的SELECT(0)集放到一个临时数组temp[]中,for(i=1;i<=产生式总数-1;i++)
求temp的长度length
if
i指向的当前产生式的左部等于上一条产生式的左部
then
把SELECT(i)并入到temp数组中,
If (temp的长度小于length加上SELECT (i)的长度)
返回0
else
把temp清空
把SELECT (i)存放到temp中
结果返回1;
预测分析表
实验内容
流程图
程序代码
public class LL1_Deque {
//预测分析表
private String[][] analysisTable = new String[][]{
{"TE'","","","TE'","",""},
{"","+TE'","","","ε","ε"},
{"FT'","","","FT'","",""},
{"","ε","*FT'","","ε","ε"},
{"i","","","(E)","",""}
};
//终结符
private String[] VT = new String[]{"i","+","*","(",")","#"};
//非终结符
private String[] VN = new String[]{"E","E'","T","T'","F"};
//输入串strToken
private static StringBuilder strToken = new StringBuilder("i*(i+()i)");
//分析栈stack
private Deque stack = new ArrayDeque<>();
//shuru1保存从输入串中读取的一个输入符号,当前符号
private String shuru1 = null;
//X中保存stack栈顶符号
private String X = null;
//flag标志预测分析是否成功
private boolean flag = true;
//记录输入串中当前字符的位置
private int cur = 0;
//记录步数
private int count = 0;
public static void main(String[] args) {
System.out.println("所输入的表达式为:" + strToken );
LL1_Deque ll1 = new LL1_Deque();
ll1.init();
ll1.totalControlProgram();
ll1.printf();
}
//初始化
private void init() {
strToken.append("#");
stack.push("#");
System.out.printf("%-20s %-80s %-40s %s\n", "步骤 ", "符号栈 ", "输入串 ", "所用产生式 ");
stack.push("E");
curCharacter();
System.out.printf("%-10d %-30s %-20s\n", count, stack.toString(), strToken.substring(cur, strToken.length()));
}
//读取当前栈顶符号
private void stackPeek() {
X = (String) stack.peekFirst();
}
//返回输入串中当前位置的字母
private String curCharacter() {
shuru1 = String.valueOf(strToken.charAt(cur));
return shuru1;
}
//判断X是否是终结符
private boolean XisVT() {
for (int i = 0; i < (VT.length - 1); i++) {
if (VT[i].equals(X)) {
return true;
}
}
return false;
}
//查找X在非终结符中分析表中的横坐标
private String VNTI() {
int Ni = 0, Tj = 0;
for (int i = 0; i < VN.length; i++) {
if (VN[i].equals(X)) {
Ni = i;
}
}
for (int j = 0; j < VT.length; j++) {
if (VT[j].equals(shuru1)) {
Tj = j;
}
}
return analysisTable[Ni][Tj];
}
// 判断M[A,a]={X->X1X2...Xk}
// 把X1X2...Xk推进栈
// X1X2...Xk=ε,不推什么进栈
private boolean productionType() {
return VNTI() != "";
}
//推进stack栈
private void pushStack() {
stack.pop();
String M = VNTI();
String ch;
//处理TE' FT' *FT'特殊情况
switch (M) {
case "TE'":
stack.push("E'");
stack.push("T");
break;
case "FT'":
stack.push("T'");
stack.push("F");
break;
case "*FT'":
stack.push("T'");
stack.push("F");
stack.push("*");
break;
case "+TE'":
stack.push("E'");
stack.push("T");
stack.push("+");
break;
default:
for (int i = (M.length() - 1); i >= 0; i--) {
ch = String.valueOf(M.charAt(i));
stack.push(ch);
}
break;
}
System.out.printf("%-10d %-30s %-20s %s->%s\n", (++count), stack.toString(), strToken.substring(cur, strToken.length()), X, M);
}
//总控程序
private void totalControlProgram() {
while (flag) {
stackPeek();
//读取当前栈顶符号 令X=栈顶符号
if (XisVT()) {
if (X.equals(shuru1)) {
cur++;
shuru1 = curCharacter();
stack.pop();
System.out.printf("%-10d %-30s %-20s \n", (++count), stack.toString(), strToken.substring(cur, strToken.length()));
} else {
ERROR();
}
} else if (X.equals("#")) {
if (X.equals(shuru1)) {
flag = false;
} else {
ERROR();
}
} else if (productionType()) {
if (VNTI().equals("")) {
ERROR();
} else if (VNTI().equals("ε")) {
stack.pop();
System.out.printf("%-10d %-30s %-20s %s->%s\n", (++count), stack.toString(), strToken.substring(cur, strToken.length()), X, VNTI()); } else {
pushStack();
}
} else {
ERROR();
}
}
}
//出现错误
private void ERROR() {
// System.out.println("输入串出现错误,无法进行分析");
System.out.println( false );
System.exit(0);
}
//打印存储分析表
private void printf() {
if (!flag) {
System.out.println( true );
// System.out.println("****分析成功啦!****");
} else {
// System.out.println("****分析失败了****");
System.out.println( false );
}
}
}
运行结果
实验总结
- 基于LL1算法构造语法树
- 对于输入的字符串进行语法分析,本实验只针对于加法、乘法、括号做了判断
- 返回:
a) 分析正确,返回true
b) 分析错误,返回false
源代码下载:https://download.csdn.net/download/Simple__Code/12817517