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;

/**

*

* 逆波兰式

*

* @author XiaoPengwei

* @since 2019-06-19

*/

public class RpnMain {

/**

* 检查算术表达术括号是否匹配, 语法是否正确

*

* @param s 算术表达术

* @return boolean

*/

public boolean isMatch(String s) {

//括号符号栈

Stack 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 opStack = new Stack();

//运算符优先级

Map 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");

}

}

}

}

}

测试:

原文出处:https://www.cnblogs.com/xpwi/p/11050692.html

逆波兰式 java_Java 实现《编译原理》中间代码生成 -逆波兰式生成与计算 - 程序解析...相关推荐

  1. 编译原理—中间代码生成、布尔表达式翻译、短路计算、控制流语句翻译、条件语句、循环语句

    编译原理-中间代码生成.布尔表达式翻译.短路计算.控制流语句翻译.条件语句循环语句 1.布尔表达式的翻译 1.1 数值表示法 1.2举例 1.3短路计算 1.4回填技术 1.5短路计算及回填的翻译方案 ...

  2. 编译原理逆波兰式实验java_逆波兰式算法的编译原理实验过程.doc

    逆波兰式算法的编译原理实验过程 实验目的 深入理解算符优先分析法 掌握FirstVt和LastVt集合的求法有算符优先关系表的求法 掌握利用算符优先分析法完成中缀表达式到逆波兰式的转化 实验内容及要求 ...

  3. (编译原理)正规文法转正规式(原代码)

    (编译原理)正规文法转正规式 一.实验要求 输入:正规文法 输出:正规式 例: 输入:S->aB B->b 输出:ab 输入:S->aS S->b 输出:a*b 输入:S-&g ...

  4. 编译原理:代码生成(pcode),C语言实现

    编译原理:代码生成(pcode),C语言实现 部分参考代码及函数: #include #include <stdio.h> #include <string.h> #inclu ...

  5. 编译原理 | 实验四 | 逆波兰式

    目录 一.问题分析 二.算法思想 1.关于分词器 2.关于逆波兰式分析器: 三.实现代码 1.头文件  &  类视图 2.预处理部分 3.逆波兰分析过程 4.计算,输出部分 四.总结 一.问题 ...

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

    一.实验目的和要求: 1. 掌握语法分析的基本思想,并用高级语言编写逆波兰式生成程序 2. 要求利用逆波兰式生成算法编写程序,将从键盘上输入的算术表达式 (中缀表达式)转化成逆波兰式 二.实验平台: ...

  7. 编译原理中间代码生成--java实现

    本人博客内编译原理文章的配套资源jar包,包括词法分析,语法分析,中间代码生成,静态语义检查,代码解释执行以及抽象语法树的手动生成:https://download.csdn.net/download ...

  8. 【编译原理】词法分析(正规式与自动机)

    文章目录 一·单词的形式化描述工具 二·有穷自动机(有限自动机) 三· 正规式和有穷自动机的等价性 四· 正规文法和有穷自动机的等价性 一·单词的形式化描述工具 ▶ 正规文法 即3型文法,是一个四元式 ...

  9. 编译原理_正规集和正规式_有限自动机

    ** 正规集和正规式 ** 也就是说程序设计语言的合法单词是 正规集,而正规式可以用来表示正规集 正规集是集合 正规式的等价可以转换为集合的等价来证明 将每一类的单词符号写成一个正规式,通过或运算将这 ...

最新文章

  1. 胡玮炜卸任摩拜CEO,或将成为美团大裁员的开端
  2. gridView 多余字符显示省略号...
  3. 2020 最新 JVM 生态报告
  4. linux启动脚本 范本,Linux—微服务启停shell脚本编写模板
  5. 利用OpenCV的级联分类器类CascadeClassifier和Haar特征实现人脸区域的检测
  6. 【语法解释】init
  7. 2019牛客暑期多校训练营(第七场)A String(暴力)
  8. Ansible的Inventory管理
  9. 磁力mysql搜索_多功能搜索 搜索系统安装 小说 电影 磁力
  10. BDD怎样帮助你解决沟通问题并增进协作
  11. Flask消息闪现及日志记录
  12. swift网络数据请求方法
  13. 辣条社区:问题解答、面试系列、求职助力、学习资源,你需要的都在这里
  14. python发邮件图片太长显示不出来_Python电子邮件图像太长,无法显示,为什么Python在发送多图表电子邮件时只显示第一个图像?,python,发邮件,图片,不,出来,第一张...
  15. 【PAT乙】1005 继续(3n+1)猜想 (25分)
  16. Cairo-Dock 系统关机无效
  17. 数据分析案例-航空公司客户价值分析(聚类)
  18. android系统版本命名,安卓历代系统版本命名回顾 你吃过哪些甜点?
  19. Win11 全新壁纸下载
  20. 台式计算机配置什么音响好,用什么办法才能让台式的电脑不用音响就有声音

热门文章

  1. TIOBE 2015年6月编程语言排行榜
  2. 敏捷开发Scrum学习
  3. if (Build.VERSION.SDK_INT = Build.VERSION_CODES.KITKAT)设置后的效果
  4. Opencv4Android的OpenCL的测试,使用Opencv的ocl封装库
  5. mc服务器对虚拟存储,Duang~~~ 虚拟存储的十个建议
  6. 大数据在生活中有哪些应用举例?大数据好找工作吗?
  7. 138 - 打球过程
  8. 智源社区周刊:LeCun等撰文回应Marcus;朱松纯团队价值对齐工作登Science官网头条;马毅沈向洋等公开AI智能综述论文...
  9. Signatures and Zero-Knowledge Proofs
  10. 计算机解题的过程实际上是实施某种算法,计算机等级考试二级C考点.doc