实现加减乘除任意组合的语法解析
给定一个字符串如:2/(3+4))*(3-1)+6-8 ,用程序解析出来,输出最终的值。这是个AST 语法解析问题,最直观的是建立一颗语法树,然后遍历语法树来获得最终的效果。如下图,建立这么一个语法树,然后广度优先搜索,进行操作就能得到最终的结果。
但是,其实我们有更方便的方法去做,不用建立语法树,而是利用栈,给每个操作符号定义优先级,就可以实现这个功能。一共的操作符号有:
( ) + - * /
只有这四种,定义其优先等级分别为:
( : -1
) : 0
+ : 1
- : 1
* : 2
/ : 2
解析表达式字符串,从左到右把它的字符加入到栈,如果遇到第二个操作符开始,其优先级小于前面的操作符的优先级,则先合并前面的操作符号的操作项,不断得重复此过程直到栈中只有一个符号。
我的程序定义了两个栈,一个栈是存操作符的,一个栈是存数值的。挺多处理的细节不文字表示了,看下面的代码(python实现)
class NodeOpt:"""操作符节点"""def __init__(self, ch, precedence):self.ch = chself.precedence = precedenceclass AST:"""加减乘除任意组合的语法解析器"""# 操作符栈_operatorStack = []# 值栈_exprStack = []# 具体操作符节点left_range = NodeOpt(ch='(', precedence=-1)right_range = NodeOpt(ch=')', precedence=0)add = NodeOpt(ch='+', precedence=1)sub = NodeOpt(ch='-', precedence=1)mul = NodeOpt(ch='*', precedence=2)div = NodeOpt(ch='/', precedence=2)__opts = [add, sub, mul, div, left_range, right_range]def getOptNode(self, ch):"""根据符号获取节点"""for ops in self.__opts:if ops.ch == ch:return opsdef isValue(self, ch):"""判断是否为数值"""if self.isOperator(ch):return Falsereturn Truedef isOperator(self, ch):"""判断是否为操作符"""for ops in self.__opts:if ops.ch == ch:return Truereturn Falsedef operator(self, e1, e2, operator):"""执行操作"""opt = operator.che1 = float(e1)e2 = float(e2)if opt is '+':return e1 + e2elif opt is '-':return e1 - e2elif opt is '*':return e1 * e2elif opt is '/':return e1 / e2else:return Nonedef ifGo(self):if len(self._exprStack) >= 2 and len(self._operatorStack) >= 1:return Trueelse:return Falsedef parse(self, input):""":param input: 字符数组"""for ch in input:if ch is '(':ch = self.getOptNode(ch)self._operatorStack.append(ch)elif self.isValue(ch):self._exprStack.append(ch)elif self.isOperator(ch):ch = self.getOptNode(ch)while self.ifGo() and ch.precedence <= self._operatorStack[-1].precedence:e2 = self._exprStack.pop()e1 = self._exprStack.pop()operator = self._operatorStack.pop()self._exprStack.append(self.operator(e1, e2, operator))self._operatorStack.append(ch)if ch.ch is ')':while self._operatorStack[-1].ch != '(':self._operatorStack.pop()self._operatorStack.pop()else:return Exceptionwhile self.ifGo():e2 = self._exprStack.pop()e1 = self._exprStack.pop()operator = self._operatorStack.pop()self._exprStack.append(self.operator(e1, e2, operator))return self._exprStack.pop()if __name__ == '__main__':ast = AST()myopt = "2/(3+((2-5)+1))*(3-1)+6-8"optlist = []i = 0while i < len(myopt):optlist.append(myopt[i])i += 1result = ast.parse(optlist)print(result)
转载于:https://www.cnblogs.com/aijianiula/p/9961331.html
实现加减乘除任意组合的语法解析相关推荐
- 用 C 语言开发一门编程语言 — 语法解析器
目录 文章目录 目录 前文列表 编程语言的本质 词法分析 语法分析 使用 MPC 解析器组合库 安装 快速入门 实现波兰表达式的语法解析 波兰表达式 正则表达式 代码实现 前文列表 <用 C 语 ...
- Hive之 Hql语法解析
Hive 是基于Hadoop 构建的一套数据仓库分析系统,它提供了丰富的SQL查询方式来分析存储在Hadoop 分布式文件系统中的数据,可以将结构 化的数据文件映射为一张数据库表,并提供完整的SQL查 ...
- 多层科目任意组合汇总报表的性能优化 (上)
一 问题背景 我们先来看一张资产负债表: 这是一个典型的中国式复杂报表格式,其复杂并不在于布局,而在于其中"期末余额"的每个单元格都是一个需要独立计算的指标,互相之间几乎没有关系, ...
- c语言结构体语法分析,C语言结构体struct的语法解析
本节内容需要结合视频讲解才能更容易理解,视频播放地址如下: 用java开发编译器 本节,我们着重研究结构体定义,也就是struct 这种变量定义,C语言编译器是如何解析的,本节我们要解析的结构体定义如 ...
- C语言结构体struct的语法解析
本节内容需要结合视频讲解才能更容易理解,视频播放地址如下: 用java开发编译器 本节,我们着重研究结构体定义,也就是struct 这种变量定义,C语言编译器是如何解析的,本节我们要解析的结构体定义如 ...
- 正则表达式常用语法解析
正则表达式常用语法解析 什么是正则表达式 正则表达式之元字符 匹配位置的元字符 ^.$./b 匹配字符的元字符 ..\w.\W.\s.\S.\d.\D 正则表达式之文字匹配 字符类 字符转义 反义 正 ...
- Boost学习之语法解析器--Spirit
Boost.Spirit能使我们轻松地编写出一个简单脚本的语法解析器,它巧妙利用了元编程并重载了大量的C++操作符使得我们能够在C++里直接使用类似EBNF的语法构造出一个完整的语法解析器(同时也把C ...
- pg/og内核原理-词法语法解析(更新中)
目录 概念与含义 流程概览 词法语法代码 parsenode.h kwlist.h scan.l gram.y bison的使用 查看状态机 解决规约冲突 plpgsql的词法与语法 概念与含义 一条 ...
- 内核级python:编译器的词法和语法解析基本原理
python在收到代码内容后,首先要启动两个流程,分别为词法解析和语法解析.看过我编译原理课程的同学对这两个流程应该不陌生.词法解析其实就是把代码里面不同的元素分别归类,例如234,1.35,1e3等 ...
最新文章
- 【TCP/IP详解 卷一:协议】第十二章 广播和多播
- gis属性表怎么导成excel_第022篇:ArcGIS中将属性表直接导出为Excel的方法
- 虚拟机删除后服务器内存,卸载虚拟机后仍占内存
- JavaScript 中 JSON.parse()和JSON.stringify()
- java map转string_【库学科技】32道常见的Java基础面试题
- ffmpeg 丢帧 灰屏_音视频常见问题分析和解决:HLS切片丢帧引起的视频卡顿问题排查...
- 逻辑回归(LR) 算法模型简介
- c#rs232与三菱通讯_三菱各系统的RS232通讯接口汇总
- linux centos 权限审核 polkitd进程 简介
- 清北学堂noip2018集训D4
- a4纸在html的像素,打印常识:A4纸张在显示器上应该要多少像素?
- CSP 201609-3 炉石传说
- FairMOT训练测试自定义数据集
- 码神-day8-java
- Java常用设计模式(三)
- 再听 ,抖音视频背景制作---小龙老师
- linux命令配置网卡IP (全)
- 电子面单接口申请对接(返回电子面单模板)
- 20190917练习题总结——选择题
- 运维系统常用健康度模型浅析