一、实验原理
对文法中的每个非终结符(语法成分)编写一个子程序,而子程序的代码结构由相应非终结符的产生式右部所决定:
- 产生式右部的终结符与输入符号相匹配
- 非终结符与相应的子程序调用对应
二、表达式文法的递归下降分析器设计
文法:
G[E]:
E->E+T|T
T->T*F|F
F->(E)|i
消除左递归:
G’[E]:
E->TE’
E’->+TE’|ε
T->FT’
T’->*FT’|ε
F->(E)|i
可以通过G’[E]文法构造递归下降分析器:
文法G’[E])无左递归,E 、 T 、F的两个产生式的推导出的第一个字符无交集
三、代码
public class Parse {
// 输入的字符串
private String exp;
// 当前扫描到的字符串下标
private int index = 0;
public Parse(String exp) {
this.exp = exp;
}
public void match(char token) {
if (index == (exp.length() - 1)) {
System.out.println("合法!");
// System.exit(0); 这里退出程序的话,就不能进行多组数据验证
} else if (exp.charAt(index) == token) {
index++;
} else {
error();
}
}
public void error() {
System.out.println("Syntax error!");
System.exit(0);
}
// E->TE'
public void E() {
System.out.println("E->TE'");
T();
E1();
}
// E'->+TE'|ε
public void E1() {
if (exp.charAt(index) == '+') {
match('+');
System.out.println("E'->+TE'");
T();
E1();
} else {
System.out.println("E'->ε");
}
}
// T->FT'
private void T() {
System.out.println("T->FT'");
F();
T1();
}
// T'->*FT'|ε
private void T1() {
if (exp.charAt(index) == '*') {
match('*');
System.out.println("T'->*FT'");
F();
T1();
} else {
System.out.println("T'->ε");
}
}
// F->(E)|i
private void F() {
if (exp.charAt(index) == '(') {
match('(');
E();
if (exp.charAt(index) == ')') {
match(')');
System.out.println("F->(E)");
} else {
error();
}
} else if (exp.charAt(index) == 'i') {
match('i');
System.out.println("F->i");
} else {
error();
}
}
public static void main(String[] args) {
// 测试数据第一行为合法数据,第二行为非法数据
String [] tests = {
"i*i*i", "i+i+i", "i+i*i", "i*i+i",
"i**i", "i++i"};
for (int i = 0; i < tests.length; i++) {
Parse parse = new Parse(tests[i]);
parse.E();
}
}
}
四、递归子程序法的优缺点
优点:
- 构造方法非常简单
- 程序结构清晰
缺点:
- 递归调用较多,占用内存多、速度慢
- 如果所采用的高级语言不允许递归,则不能使用此方法