編譯原理實驗二-逆波蘭式生成程式
阿新 • • 發佈:2022-03-15
一、實驗目的和要求:
1. 掌握語法分析的基本思想,並用高階語言編寫逆波蘭式生成程式
2. 要求利用逆波蘭式生成演算法編寫程式,將從鍵盤上輸入的算術表示式
(中綴表示式)轉化成逆波蘭式
二、實驗平臺:
Java語言
三、主要實驗內容及結果:
實驗內容:
逆波蘭表示式是算術表示式的字尾表示形式,逆波蘭表示式生成演算法的關 鍵在於比較當前運算子與棧頂運算子的優先關係,若當前運算子的優先順序高於 棧頂運算子,則當前運算子入棧,若當前運算子的優先順序低於棧頂運算子,則 棧頂運算子退棧。
程式程式碼:
import java.util.ArrayList;
public class InversePolish {
//存放運算子優先關係矩陣
private String[][] chars;
// 存放運算子棧(index=0表示棧底,index=size()-1表示棧頂)
private ArrayList<String> stack;
// 存放輸入串
private ArrayList<String> inStr;
// 存放輸出串
private ArrayList<String> outStr;
public static void main(String[] args) {
InversePolish inversePolish = new InversePolish();
String str = "a*(b+c)/d";
inversePolish.init(str);
inversePolish.mainFunc();
for (String currentChar : inversePolish.outStr) {
System.out.print(currentChar);
}
}
private void mainFunc() {
// 從左往右掃描中綴表示式
label1: for (String currentChar : this.inStr) {
// 輸入串為空?
if (currentChar.equals("#")) {
// 棧為空?
while (true) {
if (this.stack.get(this.stack.size() - 1).equals("#")) {
break label1;
} else {
//退棧輸出
this.outStr.add(this.stack.get(this.stack.size() - 1));
this.stack.remove(this.stack.size() - 1);
continue;
}
}
} else {
// 運算子?
if (!this.isChar(currentChar)) {
// 輸出
this.outStr.add(currentChar);
continue;
} else {
while (true) {
// 棧是否為空?
if (this.stack.get(this.stack.size() - 1).equals("#")) {
// 入棧
this.stack.add(currentChar);
continue label1;
} else {
// 比較當前運算子與棧頂運算子的優先順序
if (isFirst(currentChar)) {
// 入棧
this.stack.add(currentChar);
continue label1;
} else {
// 當前運算子是')'
if (currentChar.equals(")")) {
while (true) {
// 棧頂為'('
if (this.stack.get(this.stack.size() - 1).equals("(")) {
// 退棧
this.stack.remove(this.stack.size() - 1);
continue label1;
} else {
// 棧為空?
if (this.stack.get(this.stack.size() - 1).equals("#")) {
System.out.println("ERROR");
} else {
// 退棧輸出
this.outStr.add(this.stack.get(this.stack.size() - 1));
this.stack.remove(this.stack.size() - 1);
continue;
}
}
}
} else {
// 退棧輸出
this.outStr.add(this.stack.get(this.stack.size() - 1));
this.stack.remove(this.stack.size() - 1);
continue;
}
}
}
}
}
}
}
}
private void init(String str) {
System.out.println(str);
this.stack = new ArrayList<>();
this.inStr = new ArrayList<>();
this.outStr = new ArrayList<>();
// 輸入運算子優先關係矩陣8*7
this.chars = new String[][] { { ">", ">", "<", "<", "<", "<", ">" }, { ">", ">", "<", "<", "<", "<", ">" },
{ ">", ">", ">", ">", "<", "<", ">" }, { ">", ">", ">", ">", "<", "<", ">" },
{ ">", ">", ">", ">", ">", "<", ">" }, { "<", "<", "<", "<", "<", "<", "=" },
{ ">", ">", ">", ">", ">", "", ">" }, { "<", "<", "<", "<", "<", "<", "<" } };
// 輸入輸入串
String[] temps = str.split("");
for (String temp : temps) {
this.inStr.add(temp);
}
this.inStr.add("#");
// 輸入運算子棧
this.stack.add("#");
}
// 運算子?
private boolean isChar(String currentChar) {
return "+-*/↑()".contains(currentChar);
}
// 比較當前運算子與棧頂運算子的優先順序
private boolean isFirst(String currentChar) {
String stackChar = this.stack.get(this.stack.size() - 1);
int x = "+-*/↑()#".indexOf(stackChar);
int y = "+-*/↑()#".indexOf(currentChar);
return this.chars[x][y].equals("<");
}
}
執行結果:
四、心得體會
實現逆波蘭式的演算法,難度並不大,之所以要將看似簡單的中綴表示式轉換為複雜的逆波蘭式,原因就在於這個簡單是相對人類的思維結構來說的,對計算機而言中序表示式是非常複雜的結構。相對的,逆波蘭式在計算機看來卻是比較簡單易懂的結構。因為計算機普遍採用的記憶體結構是棧式結構,它執行先進後出的順序。