编译原理实验二-逆波兰式生成程序

一、实验目的和要求:

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

运行结果:

 

 

 

四、心得体会

实现逆波兰式的算法,难度并不大,之所以要将看似简单的中缀表达式转换为复杂的逆波兰式,原因就在于这个简单是相对人类的思维结构来说的,对计算机而言中序表达式是非常复杂的结构。相对的,逆波兰式在计算机看来却是比较简单易懂的结构。因为计算机普遍采用的内存结构是栈式结构,它执行先进后出的顺序。

 
 
posted @ 2022-03-15 09:25  临易  阅读(601)  评论(0编辑  收藏  举报