package com.wang;
import java.util.Stack;
public class LL1 {
// 加入同步符号的LL(1)分析表
private String[][] analysisTable = new String[][] {
{ "synch", "synch", "synch", "A", "A", "synch" },
{ "synch", "synch", "synch", "BE", "BE", "synch" },
{ "iBE", "synch", "ε", "synch", "synch", "ε" },
{ "synch", "synch", "synch", "CF", "CF", "synch" },
{ "ε", "+CF", "ε", "synch", "synch", "ε" },
{"synch","synch","synch","(",")A*","synch"}};
// 存储终结符
private String[] VT = new String[] { "i", "+", "*", "(", ")", "#" };
// 存储非终结符
private String[] VN = new String[] { "S", "A", "E", "B", "F","C" };//E表示A',F表示B'
// 输入串
private StringBuilder strToken;
// 分析栈4
private Stack stack = new Stack();
// a保存从输入串中读取的一个输入符号,当前符号
private String a = null;
// X中保存stack栈顶符号
private String X = null;
// flag标志预测分析是否成功
private boolean flag = true;
// 记录输入串中当前字符的位置
private int cur = 0;
// 记录步数
private int count = 1;
public LL1(StringBuilder strToken) {
this.strToken = strToken;
init();
totalControlProgram();
printf();
}
// 初始化
protected void init() {
strToken.append("#");
stack.push("#");
System.out.println("步骤\t" + "符号栈\t\t" + " 输入串 \t" + " 产生式 ");
stack.push("S");
curCharacter();
System.out.printf("%-6d %-20s %6s \n", count, stack.toString(), strToken.substring(cur, strToken.length()));
}
// 读取当前栈顶符号
protected String stackPeek() {
X = stack.peek();//栈顶元素(size-1)
return X;
}
// 返回输入串中当前位置的字母
private String curCharacter() {
a = String.valueOf(strToken.charAt(cur));//默认0位为第一个字符
return a;
}
// 判断X是否是终结符
protected boolean XisVT() {
for (int i = 0; i < (VT.length - 1); i++) {
if (VT[i].equals(X)) {
return true;
}
}
return false;
}
// 查找X在非终结符中分析表中的横坐标
protected String VNTI() {
int Ni = 0, Tj = 0;
for (int i = 0; i < VN.length; i++) {
//if(VN[i]=="’"){VN[i]=VN[i-1]+VN[i];}
if (VN[i].equals(X)) {//非终结符非终结符行比较栈顶元素
Ni = i;//记录行号
}
}
for (int j = 0; j < VT.length; j++) {
if (VT[j].equals(a)) {//终结符矩阵列比对缓冲区首字符
Tj = j;//记录列号
}
}
return analysisTable[Ni][Tj];//得到行号列号,找到矩阵上唯一的元素,即表达式,推进栈顶
}
// 判断M[A,a]={X->X1X2...Xk}
// 把X1X2...Xk推进栈
// X1X2...Xk=ε,不推什么进栈
protected boolean productionType() {
if (VNTI() != "") {
return true;
}
return false;
}
// 推进stack栈
protected void pushStack() {
stack.pop();//当前元素出栈,加入新的元素
String M = VNTI();
String ch;
for (int i = (M.length() - 1); i >= 0; i--) {
ch = String.valueOf(M.charAt(i));//字符串变成字符依次加入栈,反向,极为栈顶
stack.push(ch);
}
System.out.printf("%-6d %-20s %6s %-1s->%-12s\n", (++count), stack.toString(),
strToken.substring(cur, strToken.length()), X, M);
}
// 总控程序
protected void totalControlProgram() {
while (flag == true) {//无限循环直至,最终栈空间为#
stackPeek();//得到栈顶元素X有值了E
if (XisVT() == true) {//判断是终结符
if (X.equals(a)) {//栈顶元素与缓冲区首字符匹配
cur++;//缓冲区首位元素+1
a = curCharacter();//得到下一位字符
stack.pop();//缓冲区元素为终结符切等于栈顶字符,那么直接pop,打印信息
System.out.printf("%-6d %-20s %6s \n", (++count), stack.toString(),
strToken.substring(cur, strToken.length()));
} else {
ERROR();
}
} else if (X.equals("#")) {//判断是否为最后一个#
if (X.equals(a)) {//缓冲区元素也是#那么匹配成功
flag = false;
} else {
ERROR();
}
} else if (productionType() == true) {//判断矩阵定位的地方有元素
if (VNTI().equals("synch")) {//判断是否为同步字符
ERROR();//无法分析
} else if (VNTI().equals("ε")) {//判断是否为空
stack.pop();//是空则,直接把这个pop出,用下一个栈顶元素求
System.out.printf("%-6d %-20s %6s %-1s->%-12s\n", (++count), stack.toString(),
strToken.substring(cur, strToken.length()), X, VNTI());
} else {//有值,且就是这条线
pushStack();
}
} else {//什么都不是则,文法错误,不可分析
ERROR();
}
}
}
// 出现错误5
protected void ERROR() {
System.out.println("输入串错误,分析中断");
System.exit(0);
}
// 打印存储分析表
protected void printf() {
if (flag == false) {
System.out.println("========分析成功");
} else {
System.out.println("========分析失败");
}
}
public static void main(String[] args) {
StringBuilder strToken = new StringBuilder("(i(");
new LL1(strToken);
}
}