import javax.imageio.plugins.tiff.ExifTIFFTagSet;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
public class Ex4 {
private String input;
private String lookahead;
private int nextIndex;
private final Map<String, String[]> map = new HashMap<>() {
{
// 匿名子类实例,中间添加静态代码块用于初始化
// 存储同步集合
put("F", new String[]{"(", "id", "+", "*", ")"});
put("E", new String[]{"(", "id", ")"});
put("E_sq", new String[]{"+", "ε", ")"});
put("T", new String[]{"+", ")", "(", "id"});
put("T_sq", new String[]{"+", ")", "*", "ε"});
}
};
public Ex4() {
input();
process();
}
private void process() {
// 递归算法,往后看产生子式,如果是非终结符,则匹配其 First
// 如果是终结符,则直接匹配
E();
}
public void input() {
Scanner scanner = new Scanner(System.in);
System.out.println("target grammar : \n"
+ "E -> TE'\n"
+ "E' -> +TE'|ε\n"
+ "T -> FT'\n"
+ "T' -> *FT'|ε\n"
+ "F -> (E)|id\n");
System.out.print("Please input a string to check:");
input = scanner.nextLine() + "$";
nextToken();
}
public void E() {
if (lookahead.equals("(") || lookahead.equals("id")) {
System.out.println("Use: E -> TE'");
T();
E_sq();
}else{
error("E");
}
}
public void E_sq() {
if (lookahead.equals("+")) {
System.out.println("Use: E' -> +TE'");
match("+");
T();
E_sq();
} else {
// 进入这个分支有两种可能,一、当前这个符号确实要交由下一个方法处理
// 二、当前这个符号是错误的....
// 暂时还没想出很好的解决方法
// 也许能设置一个标志位?标记当前这个符号是取空集过去的?
// 如果在最后监测这个标志位还在,说明这个符号始终没有解决?在回到这里?
System.out.println("Use: E' -> ε");
}
}
public void T() {
if (lookahead.equals("(") || lookahead.equals("id")) {
System.out.println("Use: T -> FT'");
F();
T_sq();
}else{
error("T");
}
}
public void T_sq() {
if (lookahead.equals("*")) {
System.out.println("Use: T' -> *FT'");
match("*");
F();
T_sq();
} else {
System.out.println("Use: T' -> ε");
}
}
public void F() {
if (lookahead.equals("(")) {
System.out.println("Use: F -> (E)");
match("(");
E();
match(")");
} else if (lookahead.equals("id")) {
System.out.println("Use: F -> id");
match("id");
} else {
error("F");
}
}
public void nextToken() {
lookahead = input.charAt(nextIndex) + "";
nextIndex++;
if (lookahead.equals("i")) {
lookahead = "id";
nextIndex++;
}
}
public void match(String terminal) {
if (lookahead.equals(terminal)) {
System.out.println("Match: " + "\"" + lookahead + "\"");
nextToken();
} else {
// 错误出现?多了除了丢还能咋地?
System.out.println("terminal matching error! Just drop \"" + lookahead + "\"!");
nextToken();
if (lookahead.equals("$")) {
System.out.println("terminal matching error repair failed!Exit!");
System.exit(0);
}
match(terminal);
}
if (lookahead.equals("$")) {
System.out.println("accept! System exit!");
System.exit(0);
}
}
public void error(String non_terminal) {
System.out.println("Something wrong!" + "Try to Recovery!");
// 不断跳过元素直到碰见同步记号
String[] sync = map.get(non_terminal);
do {
System.out.println("Recovery: Skip " + "\"" + lookahead + "\"");
nextToken();
} while (!lookahead.equals("$") && !Arrays.asList(sync).contains(lookahead));
// 由于读到结束标记退出,恢复失败!
if (lookahead.equals("$")) {
System.out.println("Recovery failed! Exit!");
System.exit(0);
}
// 读取到同步记号,有恢复成功的可能性
// 通过反射机制 在断点重新调用方法
Method method = null;
try {
method = this.getClass().getMethod(non_terminal);
method.invoke(this);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public void test(){
if(!lookahead.equals("$")){
System.out.println("accept after fixing!");
}
}
public static void main(String[] args) {
new Ex4().test();
}
}
Mess_LL(1)——递归下降的预测分析方法
最新推荐文章于 2022-01-13 08:00:00 发布