Java 實現《編譯原理》中間代碼生成 -逆波蘭式生成與計算 - 程序解析


Java 實現《編譯原理》中間代碼生成 -逆波蘭式生成與計算 - 程序解析

編譯原理學習筆記

(一)逆波蘭式是什么?

逆波蘭式(Reverse Polish notation,RPN,或逆波蘭記法),也叫 后綴表達式(將運算符寫在操作數之后)

一般的表達式又稱 中綴表達式,這種表達式的二元運算符放在兩個運算量 之間。而逆波蘭表達式又稱 后綴表達式,這種表達式把運算符放在運算量 后面

比如如 a+b 的逆波蘭式表示為 ab+

注意:逆波蘭式是一個無括號表達式;逆波蘭式的運算符出現的順序就是原表達式的運算順序。

(二)逆波蘭式編譯原理有什么關系?

逆波蘭式,三元式,四元式等是編譯原理 - 中間代碼生成階段的常見的中間代碼形式。

(三)本篇任務

通過設計,使用 Java 語言編寫一個逆波蘭式生成程序,測試效果:

(四)Java 源代碼

package com.java997.analyzer.rpn;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Stack;

/**
 * <p>
 * 逆波蘭式
 *
 * @author XiaoPengwei
 * @since 2019-06-19
 */
public class RpnMain {

    /**
     * 檢查算術表達術括號是否匹配, 語法是否正確
     *
     * @param s 算術表達術
     * @return boolean
     */
    public boolean isMatch(String s) {

        //括號符號棧
        Stack<Character> charStack = new Stack<>();

        //將表達式的字符串轉換成數組
        char[] charArray = s.toCharArray();

        //遍歷數組
        for (char aChar : charArray) {
            if (aChar == '(') {
                charStack.push(aChar);
            } else if (aChar == ')') {
                //如果是 ) , 且棧為空則返回 false
                if (charStack.isEmpty()) {
                    return false;
                } else {
                    //如果是 ) , 且棧不為空則返回 false
                    //peek() 是返回棧頂的值, 不做其他操作
                    if (charStack.peek() == '(') {
                        //把棧頂的值刪除
                        charStack.pop();
                    }
                }
            }
        }
        //走到這里, 棧為空則表達式正確
        return charStack.empty();
    }

    /**
     * 判斷是否為操作符 + - * /
     *
     * @param charAt
     * @return boolean
     */
    public boolean isOperator(char charAt) {
        return charAt == '+' || charAt == '-' || charAt == '*' || charAt == '/';
    }

    /**
     * 根據正確的表達式, 獲取逆波蘭式
     *
     * @param input
     * @return java.lang.String
     */
    public StringBuilder getRpn(String input) {
        //結果
        StringBuilder sb = new StringBuilder();
        sb.append("The RPN is: ");
        //運算符棧
        Stack<Character> opStack = new Stack();

        //運算符優先級
        Map<Character, Integer> opMap = new HashMap(5);
        opMap.put('(', 0);
        opMap.put('+', 1);
        opMap.put('-', 1);
        opMap.put('*', 2);
        opMap.put('/', 2);

        //處理字符串
        for (int i = 0; i < input.length(); i++) {
            //如果是'('直接壓棧
            if (input.charAt(i) == '(') {
                opStack.push('(');
            } else if (new RpnMain().isOperator(input.charAt(i))) {
                //如果是運算符
                char curOp = input.charAt(i);
                //如果運算符棧是空,就直接壓棧
                if (opStack.isEmpty()) {
                    opStack.push(curOp);
                } else if (opMap.get(curOp) > opMap.get(opStack.peek())) {
                    //運算符棧不為空,且當當前運算符的優先級比站內第一個運算符的優先級高的時候,壓棧
                    opStack.push(curOp);
                } else {
                    //棧不為空,且運算符的優先級小於等於棧頂元素
                    for (int j = 0; j <= opStack.size(); j++) {
                        //彈出棧內第一個元素
                        char ch = opStack.pop();
                        sb.append(ch);
                        if (opStack.isEmpty()) {
                            opStack.push(curOp);
                            break;
                        } else if (opMap.get(curOp) > opMap.get(opStack.peek())) {
                            opStack.push(curOp);
                            break;
                        }
                    }
                }
            } else if (input.charAt(i) == ')') {
                //如果是')'就把站內'('上的元素都彈出棧
                for (int j = 0; j < opStack.size(); j++) {
                    char c = opStack.pop();
                    if (c == '(') {
                        break;
                    } else {
                        sb.append(c);
                    }
                }
            } else if ('A'<=input.charAt(i)&&input.charAt(i)<='Z'){
                //如果是字母就直接添加
                sb.append(input.charAt(i));
            }else if ('a'<=input.charAt(i)&&input.charAt(i)<='z'){
                //如果是字母就直接添加
                sb.append(input.charAt(i));
            }else if (Character.isDigit(input.charAt(i))){
                //如果是數字
                sb.append(input.charAt(i));
            }else {
                return new StringBuilder("But the expression contains unrecognizable characters");
            }
        }

        //把棧內剩余的運算符都彈出站
        for (int i = 0; i <= opStack.size(); i++) {
            sb.append(opStack.pop());
        }

        return sb;
    }

    public static void main(String[] args) {
        RpnMain rpnMain = new RpnMain();
        Scanner sc = new Scanner(System.in);

        while (true) {
            System.out.println("==========================\nPlease input an expression:");
            String input = sc.nextLine();

            if ("q".equals(input)) {
                sc.close();
                return;
            } else {
                if (rpnMain.isMatch(input)) {
                    System.out.println("The expression's brackets are matched");
                    // 獲取逆波蘭式
                    System.out.println(rpnMain.getRpn(input));
                } else {
                    System.out.println("Error: The expression's brackets are not matched! Enter 'q' to exit");
                }
            }
        }
    }
}

測試:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM