亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么使用Python實現一個簡單的四則運算解釋器

發布時間:2023-04-21 16:57:11 來源:億速云 閱讀:92 作者:iii 欄目:編程語言

本文小編為大家詳細介紹“怎么使用Python實現一個簡單的四則運算解釋器”,內容詳細,步驟清晰,細節處理妥當,希望這篇“怎么使用Python實現一個簡單的四則運算解釋器”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

計算功能演示

這里先展示了程序的幫助信息,然后是幾個簡單的四則運算測試,看起來是沒問題了(我可不敢保證,程序沒有bug!)。

怎么使用Python實現一個簡單的四則運算解釋器

輸出 tokens

怎么使用Python實現一個簡單的四則運算解釋器

輸出 AST

這個格式化的 JSON 信息太長了,不利于直接看到。我們將它渲染出來看最后生成的樹形圖。保存下面這個 JSON 在一個文件中,這里我叫做 demo.json,然后執行如下命令:pytm-cli -d LR -i demo.json -o demo.html,然后再瀏覽器打開生成的 html 文件。

怎么使用Python實現一個簡單的四則運算解釋器

代碼

所有的代碼都在這里了,只需要一個文件 my_eval.py,想要運行的話,復制、粘貼,然后按照演示的步驟執行即可。

Node、BinOp、Constan 是用來表示節點的類.
Calculator 中 lexizer 方法是進行分詞的,本來我是打算使用正則的,如果你看過我前面的博客的話,可以發現我是用的正則來分詞的(因為 Python 的官方文檔正則表達式中有一個簡易的分詞程序)。不過我看其他人都是手寫的分詞,所以我也這樣做了,不過感覺并不是很好,很繁瑣,而且容易出錯。
parse 方法是進行解析的,主要是解析表達式的結構,判斷是否符合四則運算的文法,最終生成表達式樹(它的 AST)。

"""
Grammar

G -> E
E -> T E'
E' -> '+' T E' | '-' T E' | ?
T -> F T'
T' -> '*' F T' | '/' F T' | ?
F -> '(' E ')' | num | name

"""

import json
import argparse


class 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())

讀到這里,這篇“怎么使用Python實現一個簡單的四則運算解釋器”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

成武县| 蒲城县| 甘德县| 阿城市| 霸州市| 合作市| 东明县| 融水| 武穴市| 望奎县| 秦皇岛市| 宁远县| 宁城县| 周宁县| 周至县| 太保市| 宿松县| 铜陵市| 临邑县| 高青县| 都匀市| 德格县| 邛崃市| 嘉黎县| 资源县| 临澧县| 奉贤区| 澳门| 双流县| 夹江县| 铁岭县| 吉林省| 巧家县| 长乐市| 沈阳市| 扶绥县| 昌图县| 资源县| 马公市| 体育| 建阳市|