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

一、实验目的

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

二、实验内容

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

三、实验要求

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

四、输出

P -> (E) | i
T -> T*F | F
E -> E+T | T
F -> P↑F | 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) {// 长度为2if (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) > bvar 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 等价与 bequal(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 等价与 bequal(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集合, 求出后对应的元素置为trueMap<String, Boolean> flags = new HashMap<>(8);// 初始化集合, 表示开始时所有的非终结符的firstVt集合没有求出, 所有默认是falsefor (var i : firstTerminators.entrySet()) {flags.put(i.getKey(), false);}int index = 0;while (!isFinished) {// 记录一个产生式是否计算完了firstVtboolean isBreak = false;// index循环if (index > nonTerminators.size() - 1) {index = 0;}// 获取index位置上的非终结符VnString 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 != Qif (!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;}// 计算出了 firstVtflags.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集合, 求出后对应的元素置为trueMap<String, Boolean> flags = new HashMap<>(8);// 初始化集合, 表示开始时所有的非终结符的firstVt集合没有求出, 所有默认是falsefor (var i : lastTerminators.entrySet()) {flags.put(i.getKey(), false);}int index = 0;while (!isFinished) {// 记录一个产生式是否计算完了lastVtboolean isBreak = false;// index循环if (index > nonTerminators.size() - 1) {index = 0;}// 获取index位置上的非终结符VnString 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 != Qif (!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;}// 计算出了 lastVtflags.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 finalint 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 finalint 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的长度为1boolean 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() + 1for (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;// 最高匹配个数的产生式 possibleGenerateExpressionsList<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;}} elseif (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);}}}}
}

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

  1. 编译原理实验二:赋值语句的语法分析程序设计

    编译原理实验二:赋值语句的语法分析程序设计 1.1实验内容 目的: 在前面实验的基础上,通过设计.编制.调试一个典型的赋值语句的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查,进一步掌握 ...

  2. 编译原理实验二:Bison

    编译原理实验二:Bison 实验要求 1.了解Bision基础知识,如何将文法产生式转换为Bison语句 2.阅读/src/common/SyntaxTree.c,对应头文件 /include/Syn ...

  3. 编译原理实验二(全部存储到数组再逐行验证语法版.....这种思路被老师否了,应该是验证一行扔掉一行才对)

    编译原理实验二(可能还有BUG,不确定继续找) 要大改一次23333,老师的意思是不能用数组存储,而是一边识别单词,然后识别完一行就判断一次语法 写实验二的时候找到的实验一的一个逻辑错误 改动了实验一 ...

  4. 编译原理实验二 macos系统 itoa方法报错解决方法

    编译原理实验二 生成符号表的前期准备中使用itoa函数报错问题 执行 gcc -o parser lex.yy.c parser.tab.c ast.c 显示: itoa 函数是一个广泛应用的,从非标 ...

  5. 编译原理实验二:标识符的识别

    实验要求 [任务介绍]根据给定源语言的构词规则,从任意字符串中识别出所有的合法标识符. [输入]字符串. [输出]单词符号流,一行一个单词. [题目]设计一个程序,从任意字符串中识别出所有可视为C语言 ...

  6. 编译原理-实验二-LL(1)语法分析程序的设计

    一.实验目的 了解LL(1)分析器的基本构成及用自顶向下的LL(1)方法对表达式进行语法分析的方法,掌握LL(1)语法分析程序的构造方法. 二.实验内容 根据LL(1)语法分析算法的基本思想,设计一个 ...

  7. 编译原理—实验二LL(1)语法分析(一)

    一.实验目的 1.熟悉LL(1)语法分析的基本原理,语法分析的过程,以及语法分析中要注意的一些问题. 2. 复习高级语言及线性表.栈.图等典型数据结构,进一步加强用高级语言来解决实际问题的能力. 二. ...

  8. 编译原理实验五:用Yacc设计语法分析器1

    所有实验的源代码:点此下载 实验目的: 学习如何使用Yacc设计一个语法分析器,并与用lex写的词法分析器链接起来. 实验内容: 使用yacc为实验2所给的语言写一个语法分析器(你可以重新设计该语言的 ...

  9. 编译原理实验二 自上而下语法分析

    自上而下 语法分析实验 一.实验目的 (1)给出 PL/0 文法规范,要求编写 PL/0语言的语法分析程序. (2)通过设计.编制.调试一个典型的自上而下语法分析程序,实现对词法分析程序所提供的单词序 ...

最新文章

  1. Dynamics CRM 导入用户数据错误 could not retrieve salesperson role
  2. axure 下拉多选 元件_Axure教程:下拉多选列表集合(多选下拉列表+单选下拉列表+分级下拉列表)...
  3. Android配置----Android开发环境搭建
  4. 一些长时间GC停顿问题的排查及解决办法
  5. 伪指令 .align 的含义
  6. redis序列化_SpringBoot整合redis
  7. mysql update 多个字段_MySQL数据库基础
  8. [论文阅读] Exploring Dense Context for Salient Object Detection
  9. Java的常用Swing外观类总结
  10. java4选择结构 二
  11. 比rufus/scheduler更独立简洁的定时脚本必备whenever
  12. 乐易模块V7.62更新日志
  13. 24届大三日常实习字节(抖音)后端一面 面经
  14. 虚拟网络之Kubernetes Cilium CNI 快速部署实操
  15. Regular Expression 正则表达式 语法规则及使用
  16. Mapbox简易入门教程
  17. NYOJ - 597
  18. mysql印度时区_一次 JDBC 与 MySQL 因 “CST” 时区协商误解导致时间差了 14 或 13 小时的排错经历...
  19. kubernetes 之QoS服务质量管理
  20. 两个onCreate()方法

热门文章

  1. 2022-2028全球与中国360度投影系统市场现状及未来发展趋势
  2. PyTorch~Faster RCNNの小麦麦穗检测
  3. Jetson NX性能介绍
  4. python 声音合成_Python 音频生成器的实现示例
  5. 每天听一本书,日精日进
  6. Adobe Audition 2022 v22.5 WiN-MAC 专业音频编辑软件
  7. AutoHotkey模拟创建Gui工具栏
  8. 15款顶级的开源人工智能工具推荐
  9. 50行python游戏代码_使用50行Python代码从零开始实现一个AI平衡小游戏
  10. PMDG Boeing 737NGX启动程序