返回顶部
首页 > 资讯 > 后端开发 > Python >怎么使用Python制作一个极简四则运算解释器
  • 614
分享到

怎么使用Python制作一个极简四则运算解释器

2023-07-05 22:07:31 614人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

本篇内容主要讲解“怎么使用python制作一个极简四则运算解释器”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用Python制作一个极简四则运算解释器”吧!计算功能演示这里先展示了程序的帮

本篇内容主要讲解“怎么使用python制作一个极简四则运算解释器”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用Python制作一个极简四则运算解释器”吧!

计算功能演示

这里先展示了程序的帮助信息,然后是几个简单的四则运算测试,看起来是没问题了(我可不敢保证,程序没有bug!)。

怎么使用Python制作一个极简四则运算解释器

输出 tokens

怎么使用Python制作一个极简四则运算解释器

输出 AST

这个格式化的 JSON 信息太长了,不利于直接看到。我们将它渲染出来看最后生成的树形图(方法见前两个博客)。保存下面这个 jsON 在一个文件中,这里我叫做 demo.json,然后执行如下命令:pytm-cli -d LR -i demo.json -o demo.html,然后再浏览器打开生成的 html 文件。

怎么使用Python制作一个极简四则运算解释器

怎么使用Python制作一个极简四则运算解释器

代码

所有的代码都在这里了,只需要一个文件 my_eval.py,想要运行的话,复制、粘贴,然后按照演示的步骤执行即可。

node、BinOp、Constan 是用来表示节点的类.
Calculator 中 lexizer 方法是进行分词的,本来我是打算使用正则的,如果你看过我前面的博客的话,可以发现我是用的正则来分词的(因为 Python 的官方文档正则表达式中有一个简易的分词程序)。不过我看其他人都是手写的分词,所以我也这样做了,不过感觉并不是很好,很繁琐,而且容易出错。
parse 方法是进行解析的,主要是解析表达式的结构,判断是否符合四则运算的文法,最终生成表达式树(它的 AST)。

"""GrammarG -> EE -> T E'E' -> '+' T E' | '-' T E' | ɛT -> F T'T' -> '*' F T' | '/' F T' | ɛF -> '(' E ')' | num | name"""import jsonimport argparseclass Node:    """    简单的抽象语法树节点,定义一些需要使用到的具有层次结构的节点    """    def eval(self) -> float: ...   # 节点的计算方法    def visit(self): ...           # 节点的访问方法class BinOp(Node):    """    BinOp Node    """    def __init__(self, left, op, right) -> None:        self.left = left        self.op = op        self.right = right    def eval(self) -> float:        if self.op == "+":            return self.left.eval() + self.right.eval()        if self.op == "-":            return self.left.eval() - self.right.eval()        if self.op == "*":            return self.left.eval() * self.right.eval()        if self.op == "/":            return self.left.eval() / self.right.eval()        return 0    def visit(self):        """        遍历树的各个节点,并生成 JSON 表示        """        return {            "name": "BinOp",            "children": [                self.left.visit(),                {                    "name": "OP",                    "children": [                        {                            "name": self.op                        }                    ]                },                self.right.visit()            ]        }class Constant(Node):    """    Constant Node    """    def __init__(self, value) -> None:        self.value = value    def eval(self) -> float:        return self.value    def visit(self):        return {            "name": "NUMBER",            "children": [                {                    "name": str(self.value)  # 转成字符是因为渲染成图像时,需要该字段为 str                }            ]        }class Calculator:    """    Simple Expression Parser    """    def __init__(self, expr) -> None:        self.expr = expr           # 输入的表达式        self.parse_end = False     # 解析是否结束,默认未结束        self.toks = []             # 解析的 tokens        self.index = 0             # 解析的下标    def lexizer(self):        """        分词        """        index = 0        while index < len(self.expr):            ch = self.expr[index]            if ch in [" ", "\r", "\n"]:                index += 1                continue            if '0' <= ch <= '9':                num_str = ch                index += 1                while index < len(self.expr):                    n = self.expr[index]                    if '0' <= n <= '9':                        if ch == '0':                            raise Exception("Invalid number!")                        num_str = n                        index += 1                        continue                    break                self.toks.append({                    "kind": "INT",                    "value": int(num_str)                })            elif ch in ['+', '-', '*', '/', '(', ')']:                self.toks.append({                    "kind": ch,                    "value": ch                })                index += 1            else:                raise Exception("Unkonwn character!")    def get_token(self):        """        获取当前位置的 token        """        if 0 <= self.index < len(self.toks):            tok = self.toks[self.index]            return tok        if self.index == len(self.toks):  # token解析结束            return {                "kind": "EOF",                "value": "EOF"            }        raise Exception("Encounter Error, invalid index = ", self.index)    def move_token(self):        """        下标向后移动一位        """        self.index += 1    def parse(self) -> Node:        """        G -> E        """        # 分词        self.lexizer()        # 解析        expr_tree = self.parse_expr()        if self.parse_end:            return expr_tree        else:            raise Exception("Invalid expression!")    def parse_expr(self):        """        E -> T E'        E' -> + T E' | - T E' | ɛ        """        # E -> E E'        left = self.parse_term()        # E' -> + T E' | - T E' | ɛ        while True:            tok = self.get_token()            kind = tok["kind"]            value = tok["value"]            if tok["kind"] == "EOF":                # 解析结束的标志                self.parse_end = True                break            if kind in ["+", "-"]:                self.move_token()                left = BinOp(left, value, self.parse_term())            else:                break        return left    def parse_term(self):        """        T -> F T'        T' -> * F T' | / F T' | ɛ        """        # T -> F T'        left = self.parse_factor()        # T' -> * F T' | / F T' | ɛ        while True:            tok = self.get_token()            kind = tok["kind"]            value = tok["value"]            if kind in ["*", "/"]:                self.move_token()                right = self.parse_factor()                left = BinOp(left, value, right)            else:                break        return left    def parse_factor(self):        """        F -> '(' E ')' | num | name        """        tok = self.get_token()        kind = tok["kind"]        value = tok["value"]        if kind == '(':            self.move_token()            expr_node = self.parse_expr()            if self.get_token()["kind"] != ")":                raise Exception("Encounter Error, expected )!")            self.move_token()            return expr_node        if kind == "INT":            self.move_token()            return Constant(value=value)        raise Exception("Encounter Error, unknown factor: ", kind)if __name__ == "__main__":    # 添加命令行参数解析器    cmd_parser = argparse.ArgumentParser(        description="Simple Expression Interpreter!")    group = cmd_parser.add_mutually_exclusive_group()    group.add_argument("--tokens", help="print tokens", action="store_true")    group.add_argument("--ast", help="print ast in JSON", action="store_true")    cmd_parser.add_argument(        "expr", help="expression, contains ['+', '-', '*', '/', '(', ')', 'num']")    args = cmd_parser.parse_args()    calculator = Calculator(expr=args.expr)    tree = calculator.parse()    if args.tokens:   # 输出 tokens        for t in calculator.toks:            print(f"{t['kind']:3s} ==> {t['value']}")    elif args.ast:    # 输出 JSON 表示的 AST        print(json.dumps(tree.visit(), indent=4))    else:             # 计算结果        print(tree.eval())

总结

本来想在前面说一下为什么叫 my_eval.py,但是感觉看到后面的人不多,那就在这里说好了。如果写了一个复杂的表达式,那么怎么验证是否正确的。这里我们直接利用 Python 这个最完美的解释器就好了,哈哈。这里用 Python 的 eval 函数,你当然是不需要调用这个函数,直接复制计算的表达式即可。我用 eval 函数,只是想表达为什么我的程序会叫 my_eval 这个名字。

怎么使用Python制作一个极简四则运算解释器

这样实现下来,也算是完成了一个简单的四则运算解释器了。不过,如果你也做一遍的话,也估计会和我一样感觉到整个过程很繁琐。因为分词和语法解析都有现成的工具可以来完成,而且不容易出错,可以大大减少工作量。不过,自己来一遍也是很有必要的,在使用工具之前,至少也要了解工具的作用。

到此,相信大家对“怎么使用Python制作一个极简四则运算解释器”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: 怎么使用Python制作一个极简四则运算解释器

本文链接: https://lsjlt.com/news/355670.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 使用Python制作一个极简四则运算解释器
    前言: 这是最近完成的一个小的 demo,一个极简四则运算解释器。前面,已经基于这个想法发了两篇博客了:浅谈一下四则运算和二叉树python的简单四则运算语法树可视化然后,前两天也就...
    99+
    2023-05-14
    Python四则运算 Python运算解释器 极简四则运算
  • 怎么使用Python制作一个极简四则运算解释器
    本篇内容主要讲解“怎么使用Python制作一个极简四则运算解释器”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用Python制作一个极简四则运算解释器”吧!计算功能演示这里先展示了程序的帮...
    99+
    2023-07-05
  • 如何使用Unity制作一个简易的计算器
    这篇文章给大家分享的是有关如何使用Unity制作一个简易的计算器的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、前言Hello,又见面了,今天分享如何使用Unity制作计算器,难度中等,可以用来学习,或者当成其...
    99+
    2023-06-29
  • 怎么用python制作简单计算器功能
    今天小编给大家分享一下怎么用python制作简单计算器功能的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。效果如图:主要思路:...
    99+
    2023-06-29
  • 怎么使用Qt制作简单的计算器
    这篇文章主要讲解了“怎么使用Qt制作简单的计算器”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用Qt制作简单的计算器”吧!前言这里先跟大家说说使用到的函数:槽连接函数connect(信...
    99+
    2023-07-04
  • 怎么使用Python制作一个数据大屏
    本篇内容主要讲解“怎么使用Python制作一个数据大屏”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用Python制作一个数据大屏”吧!PywebIO介绍Python当中的PywebIO模...
    99+
    2023-07-06
  • 怎么用CSS3制作一个简单的Chrome模拟器
    这篇文章主要介绍“怎么用CSS3制作一个简单的Chrome模拟器”,在日常操作中,相信很多人在怎么用CSS3制作一个简单的Chrome模拟器问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望...
    99+
    2024-04-02
  • 怎么使用html制作一个简单的提交表单
    这篇文章主要介绍怎么使用html制作一个简单的提交表单,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!html制作一个表单的方法网页中常见的“登录”“注册”等功能通常都是使用表单实现的...
    99+
    2024-04-02
  • 使用python怎么制作一个猜数字游戏
    本篇文章给大家分享的是有关使用python怎么制作一个猜数字游戏,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。python可以做什么Python是一种编程语言,内置了许多有效的...
    99+
    2023-06-14
  • 使用python怎么制作一个云打卡系统
    这期内容当中小编将会给大家带来有关使用python怎么制作一个云打卡系统,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。python的数据类型有哪些python的数据类型:1. 数字类型,包括int(整型)...
    99+
    2023-06-14
  • 怎么使用HTML制作一个简单美观的导航栏
    小编给大家分享一下怎么使用HTML制作一个简单美观的导航栏,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!在不久前学习了基础知识(...
    99+
    2024-04-02
  • 怎么使用CSS制作一个简单美观的导航栏
    这篇文章主要讲解了“怎么使用CSS制作一个简单美观的导航栏”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用CSS制作一个简单美观的导航栏”吧! ...
    99+
    2024-04-02
  • 怎么使用Python制作一个多功能音乐播放器
    这篇文章主要介绍了怎么使用Python制作一个多功能音乐播放器的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么使用Python制作一个多功能音乐播放器文章都会有所收获,下面我们一起来看看吧。一、制作播放器的思...
    99+
    2023-07-05
  • 怎么利用Python制作一个简单的天气播报系统
    本篇内容介绍了“怎么利用Python制作一个简单的天气播报系统”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!工具python3.7pycha...
    99+
    2023-06-30
  • 怎么在python中使用tkinter制作一个2048游戏
    怎么在python中使用tkinter制作一个2048游戏?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。创建main.py代码:from tkinter i...
    99+
    2023-06-14
  • 使用Python怎么制作一个信息轰炸工具
    本篇文章给大家分享的是有关使用Python怎么制作一个信息轰炸工具,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。准备阶段我们需要安装pyautogui调用库(在命令提示符下安装...
    99+
    2023-06-15
  • 怎么使用Python和ChatGPT制作一个AI实用工具
    本篇内容介绍了“怎么使用Python和ChatGPT制作一个AI实用工具”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!注册OpenAI首先需...
    99+
    2023-07-05
  • 使用Python怎么制作一个微信防撤回脚本
    今天就跟大家聊聊有关使用Python怎么制作一个微信防撤回脚本,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一、之前解决方案大概是这样:短时间内同一位好友发送了多条消息,当他随便撤回...
    99+
    2023-06-15
  • 怎么在Python中使用Tkinter制作一个翻译软件
    本篇文章为大家展示了怎么在Python中使用Tkinter制作一个翻译软件,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。python是什么意思Python是一种跨平台的、具有解释性、编译性、互动性和...
    99+
    2023-06-06
  • 使用python怎么制作一个俄罗斯方块小游戏
    这期内容当中小编将会给大家带来有关使用python怎么制作一个俄罗斯方块小游戏,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。python可以做什么Python是一种编程语言,内置了许多有效的工具,Pyth...
    99+
    2023-06-14
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作