提问人:aiao 提问时间:6/9/2023 最后编辑:aiao 更新时间:6/9/2023 访问量:38
Python 定义简单表达式语言(类似 bash)
Python define simple expression language (bash like)
问:
我想定义我自己的简单语言来评估文字。
要求:
- 基于 python 允许轻松使用/添加 Python 函数(示例中未显示)
- 如果前面没有 Token,则应将其迭代为 Literal。
$
$
在 token 之前表示它是一个变量(类似于 bash)
TL;博士:
我想回来dollar_solution(**VAR_DICT)
"Minimum Working Example"
尽职调查(如果没有帮助,请忽略):
- 到目前为止,我已经能够做到这一点,但特殊字符是一元减法 ( [])。
USub
-
- 失败的 () 部分在 期间。查看
ast.parse
的代码,它只是调用 .这是否意味着我需要使用自己的 .asdl 调用自己的编译?dollar_solution
ast.parse
builtins:compile
- 基于我的研究的半生不熟的想法(按清洁度顺序):
- 定义一元运算符(在 .asdl 中)并在 中处理它。
$
MyTransormer::visit_UnaryOp
- 定义我自己的,以允许美元作为名称中的有效字符,并在 MyTransformer 中处理它
.asdl
- 定义一元运算符(在 .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()
答: 暂无答案
下一个:使用一元加运算符安全吗?
评论
ast
$
$