编译原理 实验二 简单计算器的设计与实现

书读的越多而不加思考,你就会觉得你知道得很多;而当你读书而思考得越多的时候,你就会越清楚地看到,你知道得很少。

导读:本篇文章讲解 编译原理 实验二 简单计算器的设计与实现,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文



实验二 简单计算器的设计与实现 

一、实验目的

  综合运行词法分析器、语法分析器等原理实现一个具有加、乘功能的简单计算器,该计算器满足乘法优先级高于加法优先级,且仅处理非负整数。

二、实验内容

  1. 对输入的符号串首先进行词法分析,提取操作数及操作符,以输出的单词符号为输入进行语法分析。
  2. 要求以算符优先分析的方法完成语法分析工作,识别输入串是否是文法描述语言的句子。
  3. 对句子进行求值,求值方式可以是遍历语法树或者是建立一个逆波兰式,对逆波兰式进行求值。

三、实验要求

  1. 从文件读入算术表达式/或者从终端输入;
  2. 词法分析,用二元组表示输出结果;
  3. 语法分析,算符优先分析方法进行自下而上的语法分析并构造语法树;
  4. 识别出的句子进行求值,遍历语法树求值或者先建立逆波兰式再求值;

四、输出

P -> (E) | i
T -> T*F | F
E -> E+T | T
F -> PF | P
非终结符: P T E F 
终结符: ( ) i * +firstVt(E) : + , * ,, ( , i
firstVt(T) : * ,, ( , i
firstVt(F) :, ( , i
firstVt(P) : ( , i
lastVt(E) : + , * ,, ) , i
lastVt(T) : * ,, ) , i
lastVt(F) :, ) , i
lastVt(P) : ) , i
优先关系表:
- ( ) i * + ↑ # 
( < = < < < < - 
) - > - > > > > 
i - > - > > > > 
* < > < > > < > 
+ < > < < > < >< > < > > < > 
# < - < < < < = 


常量 : 6
界符 : (
运算符 : *
常量 : 5
运算符 : +
常量 : 4
界符 : )
带判断的产生式: i*(i+i)
规约串为: i
归约到: P
规约串为: i
归约到: P
规约串为: i
归约到: P
规约串为: P+P
归约到: P
规约串为: (P)
归约到: P
规约串为: P*P
归约到: P
恭喜你,该文法是算符优先文法
语法树:
i -> P
i -> P
i -> P
P+P -> P
(P) -> P
P*P -> P
表达式的值为: 54


下面是构造形象语法树:
是否进行手动构建 > 

五、代码 (使用Maven,因为用到了Lombok依赖)

词法分析器代码链接:词法分析器

下面是算符优先分析法代码
目前实现计算FirstVt和LastVt集合, 构造优先关系表, 规约过程,简单语法树

代码中有手动构建语法树,如果选择自动构建,输入n 或者 N即可

package main.experiment2;

import lombok.Getter;
import main.experiment1.Pair;
import main.experiment1.WordAnalysis;

import java.util.*;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

/**
 * @author Diminish
 * @version 1.0
 * @since 17
 */
@Getter
public class Grammar {

    /**
     * firstVt 集合
     * Key : 非终结符
     * Value : 集合内容
     * */
    private final Map<String, List<String>> firstTerminators = new TreeMap<>();

    /**
     * lastVt 集合
     * Key : 非终结符
     * Value : 集合内容
     * */
    private final Map<String, List<String>> lastTerminators = new TreeMap<>();

    /**
     * 非终结符集合
     * */
    private List<String> nonTerminators = new ArrayList<>();

    /**
     * 终结符集合
     * */
    private List<String> terminators = new ArrayList<>();

    /**
     * <p>语法</p>
     * */
    private final Map<String, List<String>> grammar = new HashMap<>();

    /**
     * 语法开始符号
     * */
    private String startTerminator = null;

    /**
     * 优先关系表
     * */
    private String[][] precedenceRelationList;

    /**
     * 语法树
     * */
    private Node root;

    /**
     * <p>默认语法:</p>
     *      <p>A -> A+B | B</p>
     *      <p>B -> B*C | C</p>
     *      <p>C -> i</p>
     * */
    Grammar () {
        grammar.put("A", List.of("A+B", "B"));
        grammar.put("B", List.of("C*C", "C"));
        grammar.put("C", List.of("i"));
        startTerminator = "A";
        initializeGrammar();
    }

    /**
     * <p>构造指定语法</p>
     * @param start 每个句型的开始符号
     * @param generateExpression 每个开始符号对应的表达式
     * */
    Grammar (List<String> start, List<List<String>> generateExpression) {
        for (int i = 0; i < start.size(); i++) {
            grammar.put(start.get(i), generateExpression.get(i));
            if (startTerminator == null) {
                startTerminator = start.get(i);
            }
        }
        initializeGrammar();
    }

    /**
     * 构造终结符 非终结符 firstVt lastVt集合
     * */
    private void initializeGrammar () {
        constructNonTerminator(this);
        constructTerminator(this);
        constructFirstTerminator();
        constructLastTerminator();
        initializePrecedenceRelationList();
        constructPrecedenceRelationList();
    }

    /**
     * 打印输出语法
     * */
    public void showGrammar () {
        for (var i : grammar.entrySet()) {
            System.out.print(i.getKey() + " -> ");
            for (var v = 0 ; v < i.getValue().size(); v++) {
                if (v + 1 == i.getValue().size()) {
                    System.out.println(i.getValue().get(v));
                } else {
                    System.out.print(i.getValue().get(v) + " | ");
                }

            }
        }
    }

    /**
     * 打印输出非终结符
     * */
    public void showNonTerminator () {
        System.out.print("非终结符: ");
        for (var v : nonTerminators) {
            System.out.print(v + " ");
        }
        System.out.println();
    }

    /**
     * 打印输出终结符
     * */
    public void showTerminator () {
        System.out.print("终结符: ");
        for (var v : terminators) {
            System.out.print(v + " ");
        }
        System.out.println();
    }

    /**
     * 打印输出 firstVt集合
     * */
    public void showFirstTerminators () {
        var entryArrayList = sort(firstTerminators);
        for (var firstTerminator : entryArrayList) {
            System.out.print("firstVt(" + firstTerminator.getKey() + ")" + " : ");
            show(firstTerminator);
        }
    }

    /**
     * 打印输出 lastVt集合
     * */
    public void showLastTerminators () {
        var entryArrayList = sort(lastTerminators);
        for (var lastTerminator : entryArrayList) {
            System.out.print("lastVt(" + lastTerminator.getKey() + ")" + " : ");
            show(lastTerminator);
        }
    }

    private void show (Map.Entry<String, List<String>> lastTerminator) {
        int length = lastTerminator.getValue().size();
        for (int i = 0; i < length; i++) {
            if (i + 1 >= length) {
                System.out.print(lastTerminator.getValue().get(i));
            } else {
                System.out.print(lastTerminator.getValue().get(i) + " , ");
            }
        }
        System.out.println();
    }

    /**
     * 打印优先关系表
     * */
    public void showPrecedenceRelationList () {
        System.out.println("优先关系表:");
        for (String[] strings : precedenceRelationList) {
            for (int column = 0; column < precedenceRelationList.length; column++) {
                if (strings[column] == null) {
                    System.out.print("- ");
                } else {
                    System.out.print(strings[column] + " ");
                }
            }
            System.out.println();
        }
        System.out.println("\n");
    }

    /**
     * 初始化优先关系表
     * */
    private void initializePrecedenceRelationList () {
        // 创建新的终结符集合, 加入 #
        var terminatorsWithSharp = new ArrayList<>(terminators);
        terminatorsWithSharp.add("#");
        int length = terminatorsWithSharp.size() + 1;
        precedenceRelationList = new  String[length][length];
        for (int line = 0; line < length; line++) {
            for (int column = 0; column < length; column++) {
                // (0, 0) 位置空出来
                if (line == 0 && column == 0) {
                    precedenceRelationList[line][column] = "-";
                    continue;
                }
                if (line == 0 && line < terminatorsWithSharp.size()) {
                    precedenceRelationList[line][column] = terminatorsWithSharp.get(column - 1);
                } else if (column == 0 && column < terminatorsWithSharp.size()) {
                    precedenceRelationList[line][column] = terminatorsWithSharp.get(line - 1);
                }
            }
        }
    }

    /**
     * 构造优先关系表
     * */
    private void constructPrecedenceRelationList () {
        // 初始化优先关系表
        initializePrecedenceRelationList();
        //构造优先关系表
        constructList();
    }

    private void constructList () {
        // 带#号的终结符符号集
        var terminatorsWithSharp = new ArrayList<>(terminators);
        terminatorsWithSharp.add("#");
        // 带#的语法
        var grammarWithSharp = new HashMap<>(grammar);
        grammarWithSharp.put("J", List.of("#" + startTerminator + "#"));
        for (var i : grammarWithSharp.entrySet()) {
            // 获取第一个句型的产生式
            var generateExpressions = i.getValue();
            // for循环遍历每一个候选式子
            for (var generateExpression : generateExpressions) {
                // 计算产生式的长度, 如果不为1, 则分析, 否则直接到下一个产生式
                if (!(generateExpression.length() <= 1)) {
                    // 计算等价
                    calculateEquality(generateExpression, terminatorsWithSharp);
                    // 计算小于
                    calculateLess(generateExpression, terminatorsWithSharp);
                    //计算大于
                    calculateGreater(generateExpression, terminatorsWithSharp);
                }
            }
        }
    }

    /**
     * 计算优先关系表中的等价关系
     * @param generateExpression 待判断的产生式
     * @param terminatorsWithSharp 带有#的终结符集合
     * */
    private void calculateEquality(String generateExpression, ArrayList<String> terminatorsWithSharp) {
        // 长度为2
        if (generateExpression.length() == 2) {
            for (int j = 0; j < generateExpression.length() - 1; j++) {
                // 判断 P -> ...ab...
                P_ab_(generateExpression, terminatorsWithSharp);
            }
        }
        // 产生式长度大于2 即3以上
        else {
            for (int j = 0; j < generateExpression.length() - 1; j++) {
                // 判断 P -> ...ab...
                P_ab_(generateExpression, terminatorsWithSharp);
                // 判断 P -> ...aAb...
                P_aQb_(generateExpression, terminatorsWithSharp);
            }
        }
    }

    /**
     * 计算优先关系表中的低等关系
     * @param generateExpression 待判断的产生式
     * @param terminatorsWithSharp 带有#的终结符集合
     * */
    private void calculateLess(String generateExpression, ArrayList<String> terminatorsWithSharp) {
        for (int i = 0; i < generateExpression.length() - 1; i++) {
            // 判断 P -> ...aR...
            // 取第一个
            String a = generateExpression.substring(i, i + 1);
            // 取第二个
            String R = generateExpression.substring(i + 1, i + 2);
            // 是否满足 P -> ...aR...
            // 即 a 是终结符, R 是非终结符
            boolean aIsTerminator = terminatorsWithSharp.stream().anyMatch(t -> t.equals(a));
            boolean RIsNonTerminator = nonTerminators.stream().anyMatch(t -> t.equals(R));
            if (aIsTerminator && RIsNonTerminator) {
                // a < firstVt(R)
                var firstVtR = firstTerminators.get(R);
                // 遍历将对应位置 置为小于
                for (var eInFirstVtR : firstVtR) {
                    less(a, eInFirstVtR);
                }
            }
        }
    }

    /**
     * 计算优先关系表中的优先关系
     * @param generateExpression 待判断的产生式
     * @param terminatorsWithSharp 带有#的终结符集合
     * */
    private void calculateGreater(String generateExpression, ArrayList<String> terminatorsWithSharp) {
        for (int i = 0; i < generateExpression.length() - 1; i++) {
            // 判断 P -> ...Rb...
            // 取第一个
            String R = generateExpression.substring(i, i + 1);
            // 取第二个
            String b = generateExpression.substring(i + 1, i + 2);
            // 是否满足 P -> ...Rb...
            // 即 R 是非终结符, b 是终结符
            boolean RIsNonTerminator = nonTerminators.stream().anyMatch(t -> t.equals(R));
            boolean bIsTerminator = terminatorsWithSharp.stream().anyMatch(t -> t.equals(b));
            if (RIsNonTerminator && bIsTerminator) {
                // 满足
                // lastVt(R) > b
                var lastVtR = lastTerminators.get(R);
                // 遍历将对应位置 置为大于
                for (var eInLastVtR : lastVtR) {
                    greater(eInLastVtR, b);
                }
            }
        }
    }

    /**
     * 将优先关系表中的 a b 的关系变为 等价
     * @param a 列
     * @param b 行
     * */
    private void equal (String a, String b) {
        operatePrecedenceRelationList(a, b, (x, y) -> {
            precedenceRelationList[x][y] = "=";
            return true;
        });
    }

    /**
     * 将优先关系表中的 a b 的关系变为 小于
     * @param a 列
     * @param b 行
     * */
    private void less (String a, String b) {
        operatePrecedenceRelationList(a, b, (x, y) -> {
            precedenceRelationList[x][y] = "<";
            return true;
        });
    }

    /**
     * 将优先关系表中的 a b 的关系变为 大于
     * @param a 列
     * @param b 行
     * */
    private void greater (String a, String b) {
        operatePrecedenceRelationList(a, b, (x, y) -> {
            precedenceRelationList[x][y] = ">";
            return true;
        });
    }

    /**
     * 将优先关系表中的 a b 关系变为 {@code sign}
     * @param a 列
     * @param b 行
     * @param function 自定义的赋值函数
     * */
    private boolean operatePrecedenceRelationList(String a, String b, BiFunction<Integer, Integer, Boolean> function) {
        int x = 0;
        int y = 0;
        for (int line = 1; line < precedenceRelationList.length; line++) {
            if (precedenceRelationList[line][0].equals(a)) {
                x = line;
            }
        }
        for (int column = 1; column < precedenceRelationList.length; column++) {
            if (precedenceRelationList[0][column].equals(b)) {
                y = column;
            }
        }
        if (x == 0 && y == 0) {
            throw new RuntimeException("小于错误");
        } else {
            return function.apply(x, y);
//            precedenceRelationList[x][y] = "sign"
        }
    }

    /**
     * 用于判断 P -> ...ab...
     * @param generateExpression 待判断的产生式
     * @param terminatorsWithSharp 带有#的终结符集合
     * */
    private void P_ab_ (String generateExpression, List<String> terminatorsWithSharp) {
        for (int j = 0; j < generateExpression.length() - 1; j++) {
            // 取第一个符
            String a = generateExpression.substring(j, j + 1);
            // 取第二个
            String b = generateExpression.substring(j + 1, j + 2);
            // 是否满足 P -> ...ab...
            // 即 a 和 b 都是终结符
            boolean aIsTerminator = terminatorsWithSharp.stream().anyMatch(t -> t.equals(a));
            boolean bIsTerminator = terminatorsWithSharp.stream().anyMatch(t -> t.equals(b));
            if (aIsTerminator && bIsTerminator) {
                // 满足说明 a 等价与 b
                equal(a, b);
            }
        }
    }

    /**
     * 用于判断 P -> ...aQb...
     * @param generateExpression 待判断的产生式
     * @param terminatorsWithSharp 带有#的终结符集合
     * */
    private void P_aQb_ (String generateExpression, List<String> terminatorsWithSharp) {
        for (int j = 0; j < generateExpression.length() - 2; j++) {
            // 取第一个符
            String a = generateExpression.substring(j, j + 1);
            // 取第二个符
            String Q = generateExpression.substring(j + 1, j + 2);
            // 取第三个符
            String b = generateExpression.substring(j + 2, j + 3);
            // 是否满足 P -> ...aQb...
            // 即 a 和 b 都是终结符, Q是非终结符
            boolean aIsTerminator = terminatorsWithSharp.stream().anyMatch(t -> t.equals(a));
            boolean QIsNonTerminator = nonTerminators.stream().anyMatch(t -> t.equals(Q));
            boolean bIsTerminator = terminatorsWithSharp.stream().anyMatch(t -> t.equals(b));
            // 判断是否满足
            if (aIsTerminator && QIsNonTerminator && bIsTerminator) {
                // 满足说明 a 等价与 b
                equal(a, b);
            }
        }
    }

    /**
     * 排序, 根据值的长度排序, 按照值的长度从大到小排序
     * @return 排好序的链表
     */
    private List<Map.Entry<String, List<String>>> sort (Map<String, List<String>> firstOrLastTerminators) {
        var entryArrayList = new ArrayList<>(firstOrLastTerminators.entrySet());
        entryArrayList.sort((o1, o2) -> o2.getValue().size() - o1.getValue().size());
        return entryArrayList;
    }

    /**
     * 判断是不是终结符
     * @param c 需要判断的符号
     * @return 判断结果
     * */
    private boolean isTerminator (String c) {
        return terminators.stream().anyMatch(terminator -> terminator.equals(c));
    }

    /**
     * 判断是不是非终结符
     * @param c 需要判断的符号
     * @return 判断结果
     * */
    private boolean isNonTerminator (String c) {
        return nonTerminators.stream().anyMatch(nonTerminator -> nonTerminator.equals(c));
    }

    /**
     * 构造非终结符
     * */
    private void constructNonTerminator(Grammar grammar) {
        for (var i : grammar.grammar.entrySet()) {
            nonTerminators.add(i.getKey());
        }
        nonTerminators = nonTerminators.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 构造终结符, 除大写字母以外的字符都是终结符
     * */
    private void constructTerminator(Grammar grammar) {
        for (var i : grammar.grammar.entrySet()) {
            for (var v : i.getValue()) {
                for (int index = 0; index < v.length(); index++) {
                    if (v.substring(index, index + 1).matches("[^A-Z]|")) {
                        terminators.add(v.substring(index, index + 1));
                    }
                }
            }
        }
        terminators = terminators.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 构造 firstVt 集合
     * */
    private void constructFirstTerminator() {
        // 求出来的firstVt集合
        Map<String, List<String>> firstTerminators = this.firstTerminators;
        List<String> nonTerminators = this.nonTerminators;
        // 初始化firstVt集合
        for (var i : nonTerminators) {
            firstTerminators.put(i, new ArrayList<>());
        }
        // 记录是否完成
        boolean isFinished = false;
        // 集合表示对应的非终结符是否求出了firstVt集合, 求出后对应的元素置为true
        Map<String, Boolean> flags = new HashMap<>(8);
        // 初始化集合, 表示开始时所有的非终结符的firstVt集合没有求出, 所有默认是false
        for (var i : firstTerminators.entrySet()) {
            flags.put(i.getKey(), false);
        }
        int index = 0;
        while (!isFinished) {
            // 记录一个产生式是否计算完了firstVt
            boolean isBreak = false;
            // index循环
            if (index > nonTerminators.size() - 1) {
                index = 0;
            }
            // 获取index位置上的非终结符Vn
            String Vn = nonTerminators.get(index);
            // 判断Vn对应的flag值, 不为true进行计算, 为true表示计算出来了
            if (!flags.get(Vn)) {
                // 获取Vn的产生式
                List<String> generateExpressions = grammar.get(Vn);
                // 逐一进行判断
                for (String generateExpression : generateExpressions) {
                    // P -> a...
                    // 判断文法产生式是不是以终结符开头,是的话就把该终结符加入 firstVt集合
                    // a是第一个位置的元素
                    String a = generateExpression.substring(0, 1);
                    // 判断 a是不是终结符
                    if (isTerminator(a)) {
                        // 是, 即 P 的产生式以终结符开头
                        // 满足 P -> a.. 把 a 加入 firstVt(P)集合
                        firstTerminators.get(Vn).add(a);
                    }
                    // 如果产生式不是以终结符开头
                    // 判断 P -> Qa... 成立
                    // 即 判断文法产生式是不是以 非终结符 终结符 开头,是的话就把该终结符加入 firstVt(P)集合
                    else {
                        // Q 是产生式第一个元素
                        String Q = generateExpression.substring(0, 1);
                        // a 是产生式第二个元素
                        // 判断一下是否有第二个元素, 即判断是否越界
                        try {
                            a = generateExpression.substring(1, 2);
                        } catch (Exception e) {
                            a = "";
                        }
                        // 判读 P -> Qa... 成立
                        boolean pCanGetQa = isNonTerminator(Q) && isTerminator(a);
                        // 如果 P 的产生式以 Qa开头
                        if (pCanGetQa) {
                            // 将 a加入到firstVt(P)中
                            firstTerminators.get(Vn).add(a);
                        }
                        // 匹配第二条件
                        // 若 a ∈ firstVt(Q) 且 P -> Q... 则 a ∈ firstVt(P)
                        // 判断 P != Q
                        if (!Q.equals(Vn)) {
                            // 判断 P -> Q... 中, Q是非终结符
                            boolean QisNotTerminator = isNonTerminator(Q);
                            // 判读 Q 的 firstVt(Q) 是否已经算出来
                            boolean qFirstVtIsDone = flags.get(Q);
                            // Q 是 非终结符
                            if (QisNotTerminator) {
                                // Q 的 firstVt(Q) 是否已经算出来
                                if (qFirstVtIsDone) {
                                    // 算出来了
                                    // 将 firstVt(Q) 中的元素加入 firstVt(P)
                                    List<String> firstVtQ = firstTerminators.get(Q);
                                    List<String> firstVtP = firstTerminators.get(Vn);
                                    firstVtP.addAll(firstVtQ);
                                }
                                // 没有算出来直接到下一个进行计算
                                else {
                                    isBreak = true;
                                    break;
                                }
                            }
                        }
                    }
                }
                // 没有计算出来就会调到这里
                // index++ 后直接下一个产生式扫描
                index++;
                if (isBreak) {
                    continue;
                }
                // 计算出了 firstVt
                flags.put(Vn, true);
            } else {
                index++;
            }
            // 判断是不是都计算完了firstVt集合
            boolean result = true;
            for (var flag : flags.entrySet()) {
                result = result && flag.getValue();
            }
            isFinished = result;
        }
        // 去重
        for (var i : firstTerminators.entrySet()) {
            i.setValue(i.getValue().stream().distinct().collect(Collectors.toList()));
        }
    }

    /**
     * 构造 lastVt 集合
     * */
    private void constructLastTerminator() {
        // 求出来的lastVt集合
        Map<String, List<String>> lastTerminators = this.lastTerminators;
        List<String> nonTerminators = this.nonTerminators;
        // 初始化lastVt集合
        for (var i : nonTerminators) {
            lastTerminators.put(i, new ArrayList<>());
        }
        // 记录是否完成
        boolean isFinished = false;
        // 集合表示对应的非终结符是否求出了firstVt集合, 求出后对应的元素置为true
        Map<String, Boolean> flags = new HashMap<>(8);
        // 初始化集合, 表示开始时所有的非终结符的firstVt集合没有求出, 所有默认是false
        for (var i : lastTerminators.entrySet()) {
            flags.put(i.getKey(), false);
        }
        int index = 0;
        while (!isFinished) {
            // 记录一个产生式是否计算完了lastVt
            boolean isBreak = false;
            // index循环
            if (index > nonTerminators.size() - 1) {
                index = 0;
            }
            // 获取index位置上的非终结符Vn
            String Vn = nonTerminators.get(index);
            // 判断Vn对应的flag值, 不为true进行计算, 为true表示计算出来了
            if (!flags.get(Vn)) {
                // 获取Vn的产生式
                List<String> generateExpressions = grammar.get(Vn);
                // 逐一进行判断
                for (String generateExpression : generateExpressions) {
                    // P -> ...a
                    // 判断文法产生式是不是以终结符结尾,是的话就把该终结符加入 lastVt集合
                    // a是最后一个位置的元素
                    String a = generateExpression.substring(generateExpression.length() - 1);
                    // 判断 a是不是终结符
                    if (isTerminator(a)) {
                        // 是, 即 P 的产生式以终结符结尾
                        // 满足 P -> ...a 把 a 加入 lastVt(P)集合
                        lastTerminators.get(Vn).add(a);
                    }
                    // 如果产生式不是以终结符开头
                    // 判断 P -> ...aQ 成立
                    // 即 判断文法产生式是不是以 终结符 非终结符 结尾,是的话就把该终结符加入 lastVt(P)集合
                    else {
                        // Q 是产生式最后一个元素
                        String Q = generateExpression.substring(generateExpression.length() - 1);
                        // a 是产生式倒数第二个元素
                        // 判断一下是否有倒数第二个元素, 即判断是否越界
                        try {
                            a = generateExpression.substring(generateExpression.length() - 2, generateExpression.length() - 1);
                        } catch (Exception e) {
                            a = "";
                        }
                        // 判读 P -> ...aQ 成立
                        boolean pCanGetaQ = isNonTerminator(Q) && isTerminator(a);
                        // 如果 P 的产生式以 aQ 结尾
                        if (pCanGetaQ) {
                            // 将 a加入到 lastVt(P)中
                            lastTerminators.get(Vn).add(a);
                        }
                        // 匹配第二条件
                        // 若 a ∈ lastVt(Q) 且 P -> ...Q 则 a ∈ lastVt(P)
                        // 判断 P != Q
                        if (!Q.equals(Vn)) {
                            // 判断 P -> ...Q中, Q是非终结符
                            boolean QisNotTerminator = isNonTerminator(Q);
                            // 判读 Q 的 lastVt(Q) 是否已经算出来
                            boolean qLastVtIsDone = flags.get(Q);
                            // Q 是 非终结符
                            if (QisNotTerminator) {
                                // Q 的 lastVt(Q) 是否已经算出来
                                if (qLastVtIsDone) {
                                    // 算出来了
                                    // 将 lastVt(Q) 中的元素加入 lastVt(P)
                                    List<String> lastVtQ = lastTerminators.get(Q);
                                    List<String> lastVtP = lastTerminators.get(Vn);
                                    lastVtP.addAll(lastVtQ);
                                }
                                // 没有算出来直接到下一个进行计算
                                else {
                                    isBreak = true;
                                    break;
                                }
                            }
                        }
                    }
                }
                // 没有计算出来就会调到这里
                // index++ 后直接下一个产生式扫描
                index++;
                if (isBreak) {
                    continue;
                }
                // 计算出了 lastVt
                flags.put(Vn, true);
            } else {
                index++;
            }
            // 判断是不是都计算完了lastVt集合
            boolean result = true;
            for (var flag : flags.entrySet()) {
                result = result && flag.getValue();
            }
            isFinished = result;
        }
        // 去重
        for (var i : lastTerminators.entrySet()) {
            i.setValue(i.getValue().stream().distinct().collect(Collectors.toList()));
        }
    }
    /**
     * 上课老师讲的分析方法
     * @param expression 待分析的产生式
     * */
    public boolean analyze(String expression) {
        System.out.println("带判断的产生式: " + expression);
        expression = expression + "#";
        int j;
        var terminatorsWithSharp = new ArrayList<>(terminators);
        terminatorsWithSharp.add("#");
        // 读入的字符
        String a;
        // 指向栈顶元素的指针
        int k = 1;
        // 用数组模拟栈
        String[] S = new String[(int) Math.pow(2, terminators.size())];
        S[k] = "#";
        // 从 0 开始 逐一读入expression的每一个字符
        int index = 0;
        do {
            // 把下一个输入符号读到a中
            a = expression.substring(index, index + 1);
            index++;
            // 消除 Variable used in lambda expression should be final or effectively final
            int finalK = k;
            if (terminatorsWithSharp.stream().anyMatch(t -> t.equals(S[finalK]))) {
                j = k;
            } else {
                j = k - 1;
            }
            while (greatest(S[j], a)) {
                String Q;
                do {
                    Q = S[j];
                    // 消除 Variable used in lambda expression should be final or effectively final
                    int finalJ = j;
                    if (terminatorsWithSharp.stream().anyMatch(t -> t.equals(S[finalJ - 1]))) {
                        j = j - 1;
                    } else {
                        j = j - 2;
                    }
                } while (!least(S[j], Q));
                String N = stipulationsOfAnAgreement(j + 1, k, S);
                k = j + 1;
                S[k] = N;
            }
            if (least(S[j], a) || equality(S[j], a)) {
                k = k + 1;
                S[k] = a;
            } else {
                System.out.println("错误, 该文法不是算符优先文法");
                return false;
            }
        } while (!"#".equals(a));
        System.out.println("恭喜你,该文法是算符优先文法");
        System.out.println("语法树:");
        list.forEach(pair -> System.out.println(pair.getFirst() + " -> " + pair.getSecond()));
        return true;
    }

    /**
     * 判断 a 和 b 是否是 a > b 的关系
     * @param a 列
     * @param b 行
     * */
    private boolean greatest(String a, String b) {
        return operatePrecedenceRelationList(a, b, (x, y) -> ">".equals(precedenceRelationList[x][y]));
    }

    /**
     * 判断 a 和 b 是否是 a < b 的关系
     * @param a 列
     * @param b 行
     * */
    private boolean least(String a, String b) {
        return operatePrecedenceRelationList(a, b, (x, y) -> "<".equals(precedenceRelationList[x][y]));
    }

    /**
     * 判断 a 和 b 是否是 a = b 的关系
     * @param a 列
     * @param b 行
     * */
    private boolean equality(String a, String b) {
        return operatePrecedenceRelationList(a, b, (x, y) -> "=".equals(precedenceRelationList[x][y]));
    }

    /**
     * 规约
     * @param start 规约开始下标
     * @param end 规约结束下标
     * @param stack 栈
     * @return 返回规约后的结果
     * */
    private String stipulationsOfAnAgreement (int start, int end, String[] stack) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = start; i<= end; i++) {
            stringBuilder.append(stack[i]);
        }
        // 归于到某个非终结符, 默认取第一个
        System.out.println("规约串为: " + stringBuilder + "\n归约到: " + nonTerminators.get(0));
        list.add(new Pair<>(stringBuilder.toString(), nonTerminators.get(0)));
        return nonTerminators.get(0);
    }
    List<Pair<String, String>> list = new ArrayList<>();

    /**
     * 判断两个产生式的类型是非终结符
     * */
    private boolean areNonTerminator(String a, String b) {
        return isNonTerminator(a) && isNonTerminator(b);
    }

    /**
     * 计算产生式的值
     * */
    public int eval (String generateExpression) {
        Map<String, Pair<String, String>> result = new TreeMap<>(Comparator.comparingInt(Integer::parseInt));
        WordAnalysis.analyseToAllByString(generateExpression, result);
        WordAnalysis.printAll();
        if (analyze(replaceNumberWithTerminator(generateExpression))) {
            String postfix = infixToPostfix(generateExpression);
            System.out.println("表达式的值为: " + calculatePostfix(postfix));
            System.out.println("\n\n下面是构造形象语法树:");
            constructSyntaxTree(replaceNumberWithTerminator(generateExpression));
            return calculatePostfix(postfix);
        } else {
            throw new RuntimeException("该产生式不是算符优先文法");
        }
    }

    private boolean adjustInTwo = false;

    /**
     * <p>构造语法树</p>
     * <p>自底向上构建</p>
     * @param inputGenerateExpression 产生式, 对于该产生式构建一棵语法树
     */
    public void constructSyntaxTree(String inputGenerateExpression) {
        adjustInTwo = false;
        Map<Integer, List<Node>> levelMap = new HashMap<>(8);
        // 记录次数
        int count = 1;
        // 将数字替换为终结符
        inputGenerateExpression = replaceNumberWithTerminator(inputGenerateExpression);
        // 输入的产生式长度
        int inputStringLength = inputGenerateExpression.length();
        List<Node> nodeList = new ArrayList<>();
        String generateExpression;
        boolean isFinished = true;
        while (isFinished) {
            // 第一次进入循环
            if (nodeList.size() == 0) {
                generateExpression = inputGenerateExpression;
            } else {
                List<Node> lastLevelNodeList = levelMap.get(count - 1);
                if (nodeListIsTheSame(lastLevelNodeList, nodeList)) {
                    Scanner scanner = new Scanner(System.in);
                    System.out.print("是否进行手动构建 > ");
                    String input = scanner.next();
                    if (input.contains("y") || "S".equals(input) || "s".equals(input)|| "Y".equals(input)) {
                        count = manualConstruct(levelMap, nodeList, count);
                    } else {
                        System.out.println("您选择自动构建, 接下来为您自动构建--------------- ");
                        count = adjustNodeList(levelMap, nodeList, count);
                    }

                }
                levelMap.put(count++, nodeList);
                generateExpression = nodeValueToString(nodeList);
                nodeList = new ArrayList<>();
            }
            int length = generateExpression.length();
            int maxLength = 0;
            // 从产生式开始逐一遍历
            for (int index = 0; index < length;) {
                int lastIndex = index + 1;
                String part = generateExpression.substring(index, lastIndex);
                // 找出该产生式的推导式
                List<String> partStartExpressions = findStartExpressions(part);
                String value = null;
                boolean matching = false;
                int currentIndex = index;
                for (var partStartExpression : partStartExpressions) {
                    // 获取产生式
                    var pGenerateExpressions = grammar.get(partStartExpression);
                    for (var pGenerateExpression : pGenerateExpressions) {
                        for (int i = lastIndex; i <= length; i++) {
                            String s = generateExpression.substring(currentIndex, i);
                            if (s.length() > pGenerateExpression.length()) {
                                break;
                            }
                            if (matchingFirst(pGenerateExpression, s)) {
                                matching = true;
                                // 长度判断
                                if (pGenerateExpression.length() > maxLength) {
                                    maxLength = pGenerateExpression.length();
                                    value = partStartExpression;
                                    part = pGenerateExpression;
                                    index += pGenerateExpression.length();
                                }
                            }
                        }
                    }
                }
                if (matching) {
                    nodeList.add(new Node(List.of(new Node(null, part)), value));
                } else {
                    nodeList.add(new Node(null, part));
                    index++;
                }
                maxLength = 0;
            }
            // 判断终止,如果不能构建语法树,则会进入死循环,用count来判断是否进入死循环
            if (count > Math.pow(4, inputStringLength + 1)) {
                System.out.println("无法构建该产生式的语法树");
                System.out.println("请在运行一次, 使用手动构建语法树");
            }
            // 判断nodeList是否以开始符号开头
            boolean isStartSymbol = nodeList.get(0).getValue().equals(startTerminator);
            // 判断nodeList的长度为1
            boolean isOne = nodeList.size() == 1;
            // 两者满足,结束循环
            isFinished = !(isOne && isStartSymbol);
        }
        // 将最后一次产生的NodeList进行分解,每一个值对应一个节点
        List<Node> newNodeList = new ArrayList<>();
        Node lastNode = nodeList.get(0).getChild().get(0);
        String v = lastNode.getValue();
        int length = v.length();
        for (int i = 0; i < length; i++) {
            String value = v.substring(i, i + 1);
            newNodeList.add(new Node(List.of(new Node(null, value)), startTerminator));
        }
        // 将最后一次产生的NodeList分解后合成的newNodeList加入到层级Map中
        levelMap.put(count, newNodeList);

//        showLevelMap(levelMap);

        root = mapToTree(levelMap);
        this.showSyntaxTree(inputGenerateExpression);
    }

    /**
     * 手动构建语法树
     * */
    private int manualConstruct(Map<Integer, List<Node>> levelMap, List<Node> nodeList, int count) {
        int topLevel = levelMap.size();
        var current = levelMap.get(topLevel);
        var previousCurrent = levelMap.get(topLevel - 1);
        var previousPreviousCurrent = levelMap.get(topLevel - 2);
        var previousPreviousPreviousCurrent = levelMap.get(topLevel - 3);
        String nodeListString = nodeValueToString(nodeList);
        String currentString = nodeValueToString(current);
        String previousCurrentString = nodeValueToString(previousCurrent);
        String previousPreviousCurrentString = nodeValueToString(previousPreviousCurrent);
        String previousPreviousPreviousCurrentString = nodeValueToString(previousPreviousPreviousCurrent);
        System.out.println("3 > " + previousPreviousPreviousCurrentString + "   孩子节点 : " + nodeChildValueToString(previousPreviousPreviousCurrent));
        System.out.println("2 > " + previousPreviousCurrentString + "   孩子节点 : " + nodeChildValueToString(previousPreviousCurrent));
        System.out.println("1 > " + previousCurrentString + "   孩子节点 : " + nodeChildValueToString(previousCurrent));
        System.out.println("--> " + currentString);
        System.out.print("是否对[" + nodeListString + "]进行修改 > ");
        Scanner scanner = new Scanner(System.in);
        String input = scanner.next();
        if (input.contains("y") || "是".equals(input) || "s".equals(input)) {
            System.out.print("请输入修改后的内容 > ");
            String modify = scanner.next();
            System.out.println("已将[" + nodeListString + "]替换为" + modify);
            System.out.println("已删除  ->  1 > " + previousCurrentString + "   孩子节点 : " + nodeChildValueToString(previousCurrent));
            // 默认情况将 previousPreviousCurrentString 的内容接在 nodeList的后面
            // TODO 修改
            nodeList.clear();
            for (int i = 0; i < modify.length(); i++) {
                String value = modify.substring(i, i + 1);
                String child = previousPreviousCurrentString.substring(i, i + 1);
                nodeList.add(new Node(List.of(new Node(null, child)), value));
            }
            levelMap.remove(--count);
            adjustNodeList(previousPreviousPreviousCurrent, previousPreviousCurrent, nodeList);

            return count;
        } else {
            System.out.println("您放弃修改...");
            count = adjustNodeList(levelMap, nodeList, count);
            try {
                Thread.currentThread().wait(1200);
            } catch (Exception ignore) {
                return count;
            }
        }
        return count;
    }

    private String nodeChildValueToString(List<Node> nodeList) {
        if (nodeList == null) {
            return null;
        }
        StringBuilder stringBuilder = new StringBuilder();
        for (var node : nodeList) {
            if (node.getChild() != null) {
                for (var child : node.getChild()) {
                    if (child == null) {
                        break;
                    } else {
                        stringBuilder.append(child.getValue());
                    }
                }
            }
        }
        return stringBuilder.toString();
    }

    private String replaceNumberWithTerminator(String inputGenerateExpression) {
        for (int i = 0; i < inputGenerateExpression.length(); i++) {
            if (inputGenerateExpression.substring(i, i + 1).matches("\\d")) {
                String s = inputGenerateExpression.substring(i, i + 1);
                String terminator = null;
                for (var t : terminators) {
                    if (t.matches("\\w")) {
                        terminator = t;
                        break;
                    }
                }
                if (terminator != null) {
                    inputGenerateExpression = inputGenerateExpression.replace(s, terminator);
                }
            }
        }
        return inputGenerateExpression;
    }

    /**
     * 打印层级Map
     * @param levelMap 层级Map
     * */
    private void showLevelMap (Map<Integer, List<Node>> levelMap) {
        System.out.println("+++++++++++++++++++++++++++++");
        for (var s : levelMap.entrySet()) {
            System.out.print(s.getKey() + " : ");
            for (var k : s.getValue()) {
                System.out.print(k.getValue() + " ");
            }
            System.out.println();
        }
        System.out.println("+++++++++++++++++++++++++++++");
    }

    /**
     * 调整nodeList
     * <pre>
     *                      i  +  i
     *                      P  +  P
     *                      F  +  F (previousPreviousLastLevelNodeList)
     *     T  +  T   <---   T  +  T (previousLastLevelNodeList)
     *     ↓  ↓  ↓          E  +  E
     *     E  +  T   <---   E  +  E (nodeList)
     *
     * </pre>
     *
     * */
    private void adjustNodeList(List<Node> previousPreviousLastLevelNodeList, List<Node> previousLastLevelNodeList, List<Node> nodeList) {
        int length = nodeList.size();
        String newValue = previousLastLevelNodeList.get(length - 1).getValue();
        int l;
        boolean flag = true;
        for (l = 2; l < length - 1; l++) {
            flag = false;
            newValue = previousLastLevelNodeList.get(length - l).getValue();
            if (isNonTerminator(newValue)) {
                break;
            }
        }
        if (flag) {
            l = 1;
        }
        nodeList.get(length - l).setValue(newValue);
        for (int i = 0 ; i < length; i++) {
            nodeList.get(i).setChild(
                    List.of(new Node(null, previousLastLevelNodeList.get(i).getValue()))
            );
        }
        newValue = previousPreviousLastLevelNodeList.get(length - l).getValue();
        previousLastLevelNodeList.get(length - l).setValue(newValue);
    }

    /**
     * 调整nodeList
     * <pre>
     *                      i  +  i
     *                      P  +  P
     *                      F  +  F (thirdLevel)
     *     T  +  T   <---   T  +  T (secondLevel)
     *     ↓  ↓  ↓          E  +  E (topLevel)
     *     E  +  T   <---   E  +  E (nodeList)
     *
     * </pre>
     *
     * */
    private int adjustNodeList(Map<Integer, List<Node>> levelMap, List<Node> nodeList, int  count) {
        List<String> possibleGenerateExpression = findDirectPossible(nodeList);
        if (!possibleGenerateExpression.isEmpty()) {
            adjustInTwo = true;
            return adjust(possibleGenerateExpression, levelMap, nodeList, count);
        } else {
            List<Node> previousLastLevelNodeList = levelMap.get(count - 2);
            List<Node> previousPreviousLastLevelNodeList = levelMap.get(count - 3);
            if (previousPreviousLastLevelNodeList == null) {
                return count;
            }
            adjustNodeList(previousPreviousLastLevelNodeList, previousLastLevelNodeList, nodeList);
        }
        return --count;
    }


    private int adjust (List<String> possibleGenerateExpression, Map<Integer, List<Node>> levelMap, List<Node> nodeList, int  count) {
        // count 是 levelMap.size() + 1
        for (int i = 0; i < possibleGenerateExpression.size(); i++) {
            String value = possibleGenerateExpression.get(0).substring(i, i + 1);
            // 不是终结符
            if (!isTerminator(value)) {
                // 返回寻找到相匹配的
                for (var currentLevel : levelMap.entrySet()) {
                    Node node = currentLevel.getValue().get(i);
                    if (node.getValue().equals(value)) {
                        int key = currentLevel.getKey();
                        for (int j = key + 1; j <= levelMap.size(); j++) {
                            var list = levelMap.get(j);
                            list.get(i).setValue(value);
                        }
                    }
                }
            }
        }

        for (int i = 0; i < nodeList.size(); i++) {
            String value = possibleGenerateExpression.get(0).substring(i, i + 1);
            nodeList.get(i).setChild(List.of(new Node(null, nodeList.get(i).getValue())));
            nodeList.get(i).setValue(value);
        }
        for (int i = 0; i < nodeList.size(); i++) {
            List<Node> nodes = levelMap.get(levelMap.size() - 1);
            nodeList.get(i).setChild(List.of(new Node(null, nodes.get(i).getValue())));
        }
        levelMap.remove(levelMap.size());
        count--;
        return count;
    }

    /**
     * 寻找可能的推导式
     * @param nodeList 产生式
     * @return 可能的开始式
     * */
    private List<String> findDirectPossible(List<Node> nodeList) {
        StringBuilder stringBuilder = new StringBuilder();
        for (var node : nodeList) {
            stringBuilder.append(node.getValue());
        }
        // 拿到nodeList的产生式
        String generateExpression = stringBuilder.toString();
        // 匹配到的个数
        int matchingCount = 0;
        // 最高匹配个数的产生式 possibleGenerateExpressions
        List<String> possibleGenerateExpressions = new ArrayList<>();
        // 遍历全部产生式, 看看哪个相似度最高
        for (var generateExpressions : grammar.entrySet()) {
            for (var normalizedGenerateExpression : generateExpressions.getValue()) {
                // 长度一样, 匹配字符
                if (normalizedGenerateExpression.length() == generateExpression.length()) {
                    int particularCount = 0;
                    for (int i = 0; i < normalizedGenerateExpression.length(); i++) {
                        String nChar = normalizedGenerateExpression.substring(i, i + 1);
                        String gChar = generateExpression.substring(i, i + 1);
                        // 终结符一样
                        if (isTerminator(nChar) && isTerminator(gChar)) {
                            if (nChar.equals(gChar)) {
                                possibleGenerateExpressions.add(normalizedGenerateExpression);
                            } else {
                                particularCount = 0;
                                break;
                            }
                        } else
                        if (nChar.equals(gChar)) {
                            particularCount++;
                        }
                    }
                    // 相似匹配完成
                    // 相等也加入进来
                    if (particularCount >= matchingCount && particularCount != 0) {
                        matchingCount = particularCount;
                        possibleGenerateExpressions.add(normalizedGenerateExpression);
                    }
                }
            }
        }
        return possibleGenerateExpressions;
    }

    /**
     * 检查两个NodeList是否一样
     * @param nodeList 待检查的nodeList
     * @param lastLevelNodeList 待检查的nodeList
     * @return 检查结果
     * */
    private boolean nodeListIsTheSame(List<Node> lastLevelNodeList, List<Node> nodeList) {
        if (lastLevelNodeList == null) {
            return false;
        }
        if (lastLevelNodeList.size() == nodeList.size()) {
            for (int i = 0; i < lastLevelNodeList.size(); i++) {
                Node n1 = lastLevelNodeList.get(i);
                Node n2 = nodeList.get(i);
                if (!n1.getValue().equals(n2.getValue())) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    /**
     * 将层级Map变为语法树
     * @param levelMap 层级Map
     * @return 语法树根节点
     * */
    private Node mapToTree(Map<Integer, List<Node>> levelMap) {
        Node root = new Node(startTerminator);
        // 得到节点的所有孩子节点值
        List<String> childString = new ArrayList<>();
        // 上一层的孩子值
        List<Node> lastNodeList = null;
        for (int i = levelMap.size(); i > 0; i--) {
            var nodeList = levelMap.get(i);
            if (i == levelMap.size()) {
                List<Node> childList = new ArrayList<>();
                for (var v : nodeList) {
                    childList.add(v.getChild().get(0));
                }
                root.setChild(childList);
                lastNodeList = childList;
            } else {
                for (var s : childString) {
                    for (var node : nodeList) {
                        if (s.equals(node.getValue())) {
                            for (var lastNode : lastNodeList) {
                                if (lastNode.getValue().equals(s)) {
                                    if (node.getChild() == null) {
                                        lastNode.setChild(List.of(new Node(List.of(new Node(null, s)), s)));
                                    } else {
                                        var list = node.getChild();
                                        List<Node> newNodeList = new ArrayList<>();
                                        String v = list.get(0).getValue();
                                        int length = v.length();
                                        for (int j = 0; j < length; j++) {
                                            String value = v.substring(j, j + 1);
                                            newNodeList.add(new Node(null, value));
                                        };
                                        if (newNodeList.isEmpty()) {
                                            lastNode.setChild(list);
                                        } else {
                                            String string = nodeValueToString(lastNode.getChild());
                                            if (string != null) {
                                                if (!string.equals(nodeValueToString(newNodeList))) {
                                                    Scanner scanner = new Scanner(System.in);
                                                    System.out.println("lastNode: " + lastNode.getValue());
                                                    System.out.print("是否将[" + string + "]替换为[" + nodeValueToString(newNodeList) +  "] > ");
                                                    String input = scanner.next();
                                                    if ("y".equals(input) || "s".equals(input) || "S".equals(input) || "Y".equals(input)) {
                                                        lastNode.setChild(newNodeList);
                                                    }
                                                }
                                            } else {
                                                lastNode.setChild(newNodeList);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                getLastNodeList(root);
                lastNodeList = new ArrayList<>(totalLastNodeList);
                totalLastNodeList.clear();
            }
            childString.clear();
            for (var node : nodeList) {
                if (node.getChild() != null) {
                    for (var v : node.getChild()) {
                        int l = v.getValue().length();
                        if (l != 1) {
                            for (int s = 0; s < l; s++) {
                                childString.add(v.getValue().substring(s, s + 1));
                            }
                        } else {
                            childString.add(v.getValue());
                        }
                    }
                } else {
                    childString.add(node.getValue());
                }
            }
        }
        root = root.distinct();
        return root;
    }

    List<Node> totalLastNodeList = new ArrayList<>();
    /**
     * 返回最新的叶子结点
     * */
    private void getLastNodeList(Node root) {
        if (root.getChild() == null) {
            totalLastNodeList.add(root);
        } else {
            for (var node : root.getChild()) {
                getLastNodeList(node);
            }
        }
    }

    /**
     * 将节点链表中的当前节点值归一为字符串
     * @param nodeList 节点链表
     * @return 归一后的字符串
     * */
    private String nodeValueToString(List<Node> nodeList) {
        if (nodeList == null) {
            return null;
        }
        StringBuilder stringBuilder = new StringBuilder();
        for (var n : nodeList) {
            stringBuilder.append(n.getValue());
        }
        return stringBuilder.toString();
    }

    private List<String> findStartExpressions(String part) {
        List<String> partStartExpressions = new ArrayList<>();
        for (var generateExpressions : grammar.entrySet()) {
            for (var item : generateExpressions.getValue()) {
                // 记录是否part中的字符都在item中
                boolean allMatching = true;
                // 循环逐一匹配part的字符是否与item字符匹配
                for (int i = 0; i < part.length(); i++) {
                    String pChar = part.substring(i, i + 1);
                    String iChar = item.substring(i, i + 1);
                    if (!pChar.equals(iChar)) {
                        allMatching = false;
                        break;
                    }
                }
                // 匹配
                if (allMatching) {
                    // 把推导式放入数组
                    partStartExpressions.add(generateExpressions.getKey());
                }
            }
        }
        return partStartExpressions;
    }

    private boolean matchingFirst (String partStartExpression, String part) {
        // 长度不一样, 直接不匹配
        if (partStartExpression.length() != part.length()) {
            return false;
        }
        // 循环逐一匹配part的字符是否与item字符匹配
        for (int i = 0; i < part.length(); i++) {
            String pChar = part.substring(i, i + 1);
            String seChar = partStartExpression.substring(i, i + 1);
            if (!pChar.equals(seChar)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 输出语法树
     * */
    public void showSyntaxTree(String inputGenerateExpression) {
        System.out.println(inputGenerateExpression + " 的语法树:");
        var list = root.show();
        list.forEach(System.out::println);
    }

    /**
     * 计算后缀表达式的值
     * @param exp 后缀表达式
     * @return 计算出来的值
     */
    private int calculatePostfix(String exp){
        Stack<Integer> stack = new Stack<>();
        int length = exp.length();
        int index = 0;
        while(index < length){
            switch (exp.charAt(index)) {
                case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' -> stack.push((int) exp.charAt(index) - 48);
                case '+' -> {
                    int a = stack.pop();
                    int b = stack.pop();
                    stack.push(a + b);
                }
                case '-' -> {
                    int c = stack.pop();
                    int d = stack.pop();
                    stack.push(d - c);
                }
                case '*' -> {
                    int e = stack.pop();
                    int f = stack.pop();
                    stack.push(e * f);
                }
                case '/' -> {
                    int g = stack.pop();
                    int h = stack.pop();
                    stack.push(h / g);
                }
            }
            index++;
        }
        return stack.pop();
    }

    /**
     * 中缀转后缀
     * @param exp 中缀表达式
     * @return 后缀表达式
     */
    private String infixToPostfix (String exp) {
        Stack<Character> stack = new Stack<>();
        StringBuilder suffix = new StringBuilder();
        int index = 0;
        int length = exp.length();
        while(index < length){
            switch (exp.charAt(index)) {
                case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' -> suffix.append(exp.charAt(index));
                case '*', '/', '(' -> stack.push(exp.charAt(index));
                // 碰到'+''-',将栈中所有运算符弹出,送到输出队列中
                case '+', '-' -> {
                    while (stack.size() != 0) {
                        char temp = stack.pop();
                        if (temp == '(') {
                            stack.push('(');
                            break;
                        }
                        suffix.append(temp);
                    }
                    stack.push(exp.charAt(index));
                }
                case ')' -> {
                    while (!stack.isEmpty() && stack.peek() != '(') {
                        suffix.append(stack.pop());
                    }
                    stack.pop();
                }
            }
            index++;
        }
        while(!stack.isEmpty()){
            suffix.append(stack.pop());
        }
        return suffix.toString();
    }

}


测试用例

package main.experiment2;

import java.util.List;

/**
 * @author Administrator
 */
public class Test {
    public static void main(String[] args) {
        Grammar grammar = new Grammar(
                List.of("E", "T", "F", "P"),
                List.of(
                        List.of("E+T", "T"),
                        List.of("T*F", "F"),
                        List.of("P↑F", "P"),
                        List.of("(E)", "i")
                )
        );
        grammar.showGrammar();
        grammar.showNonTerminator();
        grammar.showTerminator();
        grammar.showFirstTerminators();
        grammar.showLastTerminators();
        grammar.showPrecedenceRelationList();
        System.out.println("结果为" + grammar.eval("6*(5+4)"));
    }

    private static void test1 () {
        Grammar grammar = new Grammar(
                List.of("E", "T", "F", "P"),
                List.of(
                        List.of("E+T", "T"),
                        List.of("T*F", "F"),
                        List.of("P↑F", "P"),
                        List.of("(E)", "i")
                )
        );
        grammar.showGrammar();
        grammar.showNonTerminator();
        grammar.showTerminator();
        grammar.showFirstTerminators();
        grammar.showLastTerminators();
        grammar.showPrecedenceRelationList();
        System.out.println("结果为" + grammar.eval("6*3"));
//        grammar.constructSyntaxTree("2*3");
//        grammar.constructSyntaxTree("i+i");
//        grammar.constructSyntaxTree("F+F");
//        grammar.constructSyntaxTree("T+T*F+i");
//        grammar.constructSyntaxTree("i+(i*i)");
//        grammar.constructSyntaxTree("i*(i+i)");
    }

    private static void test2 () {
        Grammar grammar = new Grammar(
                List.of("S", "A"),
                List.of(
                        List.of("*A"),
                        List.of("0A1", "*")
                )
        );
        grammar.showGrammar();
        grammar.showNonTerminator();
        grammar.showTerminator();
        grammar.showFirstTerminators();
        grammar.showLastTerminators();
        grammar.showPrecedenceRelationList();
    }

    private static void test3 () {
        Grammar grammar = new Grammar(
                List.of("Z", "A", "B"),
                List.of(
                        List.of("A()"),
                        List.of("(", "Ai", "B)"),
                        List.of("i")
                )
        );
        grammar.showGrammar();
        grammar.showNonTerminator();
        grammar.showTerminator();
        grammar.showFirstTerminators();
        grammar.showLastTerminators();
        grammar.showPrecedenceRelationList();
    }

    private static void test4 () {
        Grammar grammar = new Grammar(
                List.of("S", "T"),
                List.of(
                        List.of("a", "b", "(T)"),
                        List.of("TdS", "S")
                )
        );
        grammar.showGrammar();
        grammar.showNonTerminator();
        grammar.showTerminator();
        grammar.showFirstTerminators();
        grammar.showLastTerminators();
        grammar.showPrecedenceRelationList();
        grammar.constructSyntaxTree("(Sd(T)db)");
    }
}

Node类

package main.experiment2;

import lombok.*;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Diminish
 * @date 2022/4/17 8:23
 */
@Getter
@Setter
@With
@AllArgsConstructor
@Builder
@NoArgsConstructor
public class Node {

    private List<Node> child = new ArrayList<>();

    private String value;

    public Node distinct() {
        _distinct(this);
        _distinct(this);
        _distinct(this);
        return this;
    }

    private void _distinct (Node node) {
        if (!(node.getChild() == null)) {
            try {
                if (!node.value.matches("[A-Z]")) {
                    node.child = null;
                } else {
                    // 只有一个孩子
                    boolean isOneChild = node.getChild().size() == 1;
                    //  孩子节点的值和本节点的值一样
                    boolean theSameValue = node.getChild().get(0).getValue().equals(node.value);
                    if (isOneChild && theSameValue) {
                        node.setChild(node.getChild().get(0).getChild());
                    }
                    for (var n : node.getChild()) {
                        _distinct(n);
                    }
                }
            } catch (Exception ignored) {
            }
        }
    }

    public Node(String value) {
        this.value = value;
    }

    public boolean isSame (Node node) {
        return this.value.equals(node.value);
    }

    /**
     * 遍历语法树
     * */
    public List<List<String>> show() {
        Node root = this;
        List<List<String>> res = new ArrayList<>();
        helper(root, 0, res);
        return res;
    }

    private void helper(Node root, int depth, List<List<String>> res) {
        if (root == null) {
            return;
        }
        //判断是否是新的一层
        if (depth + 1 > res.size()) {
            res.add(new ArrayList<>());
        }
        res.get(depth).add(root.value);

        //处理子节点
        if (root.child != null) {
            for (Node node : root.child) {
                if (node != null) {
                    helper(node, depth + 1, res);
                }
            }
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/122794.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!