逆波兰式 java_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;
/**
*
* 逆波兰式
*
* @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.2举例 1.3短路计算 1.4回填技术 1.5短路计算及回填的翻译方案 ...
- 编译原理逆波兰式实验java_逆波兰式算法的编译原理实验过程.doc
逆波兰式算法的编译原理实验过程 实验目的 深入理解算符优先分析法 掌握FirstVt和LastVt集合的求法有算符优先关系表的求法 掌握利用算符优先分析法完成中缀表达式到逆波兰式的转化 实验内容及要求 ...
- (编译原理)正规文法转正规式(原代码)
(编译原理)正规文法转正规式 一.实验要求 输入:正规文法 输出:正规式 例: 输入:S->aB B->b 输出:ab 输入:S->aS S->b 输出:a*b 输入:S-&g ...
- 编译原理:代码生成(pcode),C语言实现
编译原理:代码生成(pcode),C语言实现 部分参考代码及函数: #include #include <stdio.h> #include <string.h> #inclu ...
- 编译原理 | 实验四 | 逆波兰式
目录 一.问题分析 二.算法思想 1.关于分词器 2.关于逆波兰式分析器: 三.实现代码 1.头文件 & 类视图 2.预处理部分 3.逆波兰分析过程 4.计算,输出部分 四.总结 一.问题 ...
- 编译原理实验二-逆波兰式生成程序
一.实验目的和要求: 1. 掌握语法分析的基本思想,并用高级语言编写逆波兰式生成程序 2. 要求利用逆波兰式生成算法编写程序,将从键盘上输入的算术表达式 (中缀表达式)转化成逆波兰式 二.实验平台: ...
- 编译原理中间代码生成--java实现
本人博客内编译原理文章的配套资源jar包,包括词法分析,语法分析,中间代码生成,静态语义检查,代码解释执行以及抽象语法树的手动生成:https://download.csdn.net/download ...
- 【编译原理】词法分析(正规式与自动机)
文章目录 一·单词的形式化描述工具 二·有穷自动机(有限自动机) 三· 正规式和有穷自动机的等价性 四· 正规文法和有穷自动机的等价性 一·单词的形式化描述工具 ▶ 正规文法 即3型文法,是一个四元式 ...
- 编译原理_正规集和正规式_有限自动机
** 正规集和正规式 ** 也就是说程序设计语言的合法单词是 正规集,而正规式可以用来表示正规集 正规集是集合 正规式的等价可以转换为集合的等价来证明 将每一类的单词符号写成一个正规式,通过或运算将这 ...
最新文章
- 胡玮炜卸任摩拜CEO,或将成为美团大裁员的开端
- gridView 多余字符显示省略号...
- 2020 最新 JVM 生态报告
- linux启动脚本 范本,Linux—微服务启停shell脚本编写模板
- 利用OpenCV的级联分类器类CascadeClassifier和Haar特征实现人脸区域的检测
- 【语法解释】init
- 2019牛客暑期多校训练营(第七场)A String(暴力)
- Ansible的Inventory管理
- 磁力mysql搜索_多功能搜索 搜索系统安装 小说 电影 磁力
- BDD怎样帮助你解决沟通问题并增进协作
- Flask消息闪现及日志记录
- swift网络数据请求方法
- 辣条社区:问题解答、面试系列、求职助力、学习资源,你需要的都在这里
- python发邮件图片太长显示不出来_Python电子邮件图像太长,无法显示,为什么Python在发送多图表电子邮件时只显示第一个图像?,python,发邮件,图片,不,出来,第一张...
- 【PAT乙】1005 继续(3n+1)猜想 (25分)
- Cairo-Dock 系统关机无效
- 数据分析案例-航空公司客户价值分析(聚类)
- android系统版本命名,安卓历代系统版本命名回顾 你吃过哪些甜点?
- Win11 全新壁纸下载
- 台式计算机配置什么音响好,用什么办法才能让台式的电脑不用音响就有声音
热门文章
- TIOBE 2015年6月编程语言排行榜
- 敏捷开发Scrum学习
- if (Build.VERSION.SDK_INT = Build.VERSION_CODES.KITKAT)设置后的效果
- Opencv4Android的OpenCL的测试,使用Opencv的ocl封装库
- mc服务器对虚拟存储,Duang~~~ 虚拟存储的十个建议
- 大数据在生活中有哪些应用举例?大数据好找工作吗?
- 138 - 打球过程
- 智源社区周刊:LeCun等撰文回应Marcus;朱松纯团队价值对齐工作登Science官网头条;马毅沈向洋等公开AI智能综述论文...
- Signatures and Zero-Knowledge Proofs
- 计算机解题的过程实际上是实施某种算法,计算机等级考试二级C考点.doc