Python 定义简单表达式语言(类似 bash)

Python define simple expression language (bash like)

提问人:aiao 提问时间:6/9/2023 最后编辑:aiao 更新时间:6/9/2023 访问量:38

问:

我想定义我自己的简单语言来评估文字。

要求:

  • 基于 python 允许轻松使用/添加 Python 函数(示例中未显示)
  • 如果前面没有 Token,则应将其迭代为 Literal$
  • $在 token 之前表示它是一个变量(类似于 bash)

TL;博士

我想回来dollar_solution(**VAR_DICT)"Minimum Working Example"


尽职调查(如果没有帮助,请忽略):

  • 到目前为止,我已经能够做到这一点,但特殊字符是一元减法 ( [])。USub-
  • 失败的 () 部分在 期间。查看 ast.parse 的代码,它只是调用 .这是否意味着我需要使用自己的 .asdl 调用自己的编译?dollar_solutionast.parsebuiltins:compile
  • 基于我的研究的半生不熟的想法(按清洁度顺序):
    • 定义一元运算符(在 .asdl 中)并在 中处理它。$MyTransormer::visit_UnaryOp
    • 定义我自己的,以允许美元作为名称中的有效字符,并在 MyTransformer 中处理它.asdl
  • 这听起来像是我可能需要定义自己的语言。我从哪里开始使用 Python 中的解析器?
  • 有没有一些库已经这样做了?
import ast
from _ast import Name, Constant, BinOp, Add, UnaryOp, USub
from typing import Any

EXPECTED_RESULT = "Minimum Working Example"

VAR_DICT = {"mini": "Minimum", "ex": "Example"}

MINUS_EXPRESSION = "-mini + ' ' + Working + ' ' + -ex"
DOLLAR_EXPRESSION = "$mini + ' ' + Working + ' ' + $ex"


def minus_solution(**kwargs):
    tree = ast.parse(MINUS_EXPRESSION, mode="eval")
    safe_tree = MyTransformer(var_dict=kwargs).visit(tree)
    return ast.literal_eval(safe_tree)


def dollar_solution(**kwargs):
    tree = ast.parse(DOLLAR_EXPRESSION, mode="eval")
    safe_tree = MyTransformer(var_dict=kwargs).visit(tree)
    return ast.literal_eval(safe_tree)


def main():
    try:
        assert dollar_solution(**VAR_DICT) == EXPECTED_RESULT
    except:
        print("Dollar Solution Failed!!!")
    else:
        print("Dollar Solution Success!!!")

    try:
        assert minus_solution(**VAR_DICT) == EXPECTED_RESULT
    except:
        print("Minus Solution Failed!!!")
    else:
        print("Minus Solution Success!!!")


class MyTransformer(ast.NodeTransformer):
    def __init__(self, var_dict):
        self._var_dict = var_dict

    def visit_Name(self, node: Name) -> Any:
        return Constant(
            value=node.id,
            col_offset=node.col_offset,
            lineno=node.lineno,
        )

    def visit_BinOp(self, node: BinOp) -> Any:
        super().generic_visit(node)
        assert (
            isinstance(node.op, Add)
            and isinstance(node.left, Constant)
            and isinstance(node.right, Constant)
        ), f"Bad operand or operator"

        return Constant(
            value=str(node.left.value) + str(node.right.value),
            col_offset=node.col_offset,
            lineno=node.lineno,
        )

    def visit_UnaryOp(self, node: UnaryOp) -> Any:
        assert isinstance(node.operand, Name) and isinstance(
            node.op, USub
        ), "Not Name in expression"
        return Constant(
            value=self._var_dict[node.operand.id],
            col_offset=node.col_offset,
            lineno=node.lineno,
        )


if __name__ == "__main__":
    main()

python-3.x 语法 abstract-syntax-tree 一元运算符

评论

0赞 chepner 6/9/2023
是的,专门是一个 Python 解析器,在 Python 的语法中不是有效的标记。您需要一个识别 的分词器,然后定义一个可以使用 DOLLAR 标记的语法(可以基于 Python 的语法)。ast$$

答: 暂无答案