LL(1)语法分析(java)
LL(1)语法分析(java)
转:http://blog.csdn.net/new_one_object/article/details/50670624
一、程序设计题目与说明
通过运用编译原理课程所学知识,实现LL(1)文法的语法分析程序,当任意输入一个文法符号串,通过程序中先设定好确定的LL(1)预测分析表,按照预测分析算法对输入串进行语法分析,判断其是否为符合文法规范的一个句子。如果符合文法规范则输出符号串、剩余输入串、规则等信息,否则输出错误信息
(自己加的,便于理解整个流程)简述:
init(),--》根节点E进栈,打印一行信息,不再用
totalControlProgram();,--》
1》第一步判断flag是true 则证明栈区有值,继续往下走,为false则栈区没有元素,退出
2》第二步判断栈顶元素是否是终结符,是终结符则直接pop出栈,缓冲区首字符也移除,打印输出信息
3》第三部判断栈顶元素是否为#有则匹配成功,flag设为false退出程序
4》第三步判断当前元素不为空,(如果到了这步,代表前面已经不是终结符#)把栈顶出栈,然后把得到的矩阵元素字符化后入栈
然后一步步往下走,遇见终结符就到《2》,遇到#就到《3》,遇到非终结符到《4》
二、全部代码
package downloadtest;
import java.util.Stack;
public class analyse {
// 加入同步符号的LL(1)分析表
private String[][] analysisTable = new String[][] { { "TZ", "", "", "TZ", "synch", "synch" },
{ "", "+TZ", "", "", "ε", "ε" }, { "FY", "synch", "", "FY", "synch", "synch" },
{ "", "ε", "*FY", "", "ε", "ε" }, { "i", "synch", "synch", "(E)", "synch", "synch" } };
// 存储终结符
private String[] VT = new String[] { "i", "+", "*", "(", ")", "#" };
// 存储非终结符
private String[] VN = new String[] { "E", "Z", "T", "Y", "F" };
// 输入串
private StringBuilder strToken;
// 分析栈
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 = 0;
public analyse(StringBuilder strToken) {
this.strToken = strToken;
init();
totalControlProgram();
printf();
}
// 初始化
protected void init() {
strToken.append("#");
stack.push("#");
System.out.println("步骤\t " + "符号栈\t\t " + "输入串 \t" + "所用产生式 ");
stack.push("E");
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].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();
}
}
}
// 出现错误
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*i+i");
new analyse(strToken);
}
}
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
1641
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
三、测试数据和实验结果分析
当输入串为 “i+)+i*i”时,可知输入串存在非法符号“)”,程序分析结果如下图所示:
当输入串为“i+i+i*i”时,程序分析结果如下图所示:
LL(1)语法分析(java)相关教程