1. 程式人生 > 其它 >編譯原理實驗二-逆波蘭式生成程式

編譯原理實驗二-逆波蘭式生成程式

一、實驗目的和要求:

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("<");
    }
}

執行結果:

 

 

 

四、心得體會

實現逆波蘭式的演算法,難度並不大,之所以要將看似簡單的中綴表示式轉換為複雜的逆波蘭式,原因就在於這個簡單是相對人類的思維結構來說的,對計算機而言中序表示式是非常複雜的結構。相對的,逆波蘭式在計算機看來卻是比較簡單易懂的結構。因為計算機普遍採用的記憶體結構是棧式結構,它執行先進後出的順序。