如何将混合了中缀和前缀子表达式的字符串转换为所有前缀子表达式?

How to convert a string mixed with infix and prefix sub-expressions to all prefix sub-expressions?

提问人:Han 提问时间:9/10/2023 最后编辑:Han 更新时间:9/13/2023 访问量:64

问:

考虑我有一个以这种格式编写的字符串公式:“func(a+b,c)”,其中func是一个自定义函数,这个字符串包含infix(即+)和prefix(即func)表示,我想将其转换为具有所有前缀表示的字符串,“func(+(a,b),c)”,我该怎么做?

另一个例子是 “func1(a*(b+c),d)-func2(e,f)” 到 “-(func1(*(a, +(b,c)), d), func2(e,f))”

更多背景: 我想构建一个解析器,用户将如上所述以字符串格式输入表达式,通常自定义函数会写为前缀表达式,即“func(a,b)”,但由于通用约定,人们仍然会在中缀表达式中写入 +-*/,即“a+b”。

如果表达式以所有中缀格式给出,我可以轻松地将其转换为我预定义的树对象,但是如果表达式混合了前缀和中缀格式,我不知道如何将其转换为树对象,因此询问如何将字符串转换为所有中缀格式。

我没有使用解析器的经验,感谢任何初步指导。

Python 正则表达式 字符串 解析堆栈

评论

0赞 Chris 9/10/2023
是时候对编写解析器进行一些研究了。
0赞 Community 9/10/2023
请澄清您的具体问题或提供其他详细信息以准确说明您的需求。正如目前所写的那样,很难确切地说出你在问什么。
0赞 Han 9/11/2023
谢谢,我已经用更多的背景编辑了我的问题

答:

1赞 ffff 9/13/2023 #1

如果您要解析的语言与 Python 相似,则可以使用内置 ast 模块提供的 Python 解析器,并在您感兴趣的节点上实现访问者,以构建前缀表达式。例如,您可以尝试以下操作:

import ast

def printc(*args): print(*args, end='')

class PrefixPrinter(ast.NodeVisitor):
    def visit_BinOp(self, node):
        if type(node.op) == ast.Add:
            printc("+")
        if type(node.op) == ast.Sub:
            printc("-")
        if type(node.op) == ast.Mult:
            printc("*")
        if type(node.op) == ast.Div:
            printc("/")
        printc("(")
        self.visit(node.left)
        printc(",")
        self.visit(node.right)
        printc(")")

    def visit_Call(self, node):
        self.visit(node.func)
        printc("(")
        for index, arg in enumerate(node.args):
            self.visit(arg)
            if index < len(node.args) - 1:
                printc(", ")
        printc(")")

    def visit_Name(self, node):
        printc(node.id)

first_example = "func(a+b,c)"
second_example = "func1(a*(b+c),d)-func2(e,f)"
printc(f"{first_example=} converts to ")
PrefixPrinter().visit(ast.parse(first_example))
print()
printc(f"{second_example=} converts to ")
PrefixPrinter().visit(ast.parse(second_example))
print()

执行:

$ python3 to_prefix.py 
first_example='func(a+b,c)' converts to func(+(a,b), c)
second_example='func1(a*(b+c),d)-func2(e,f)' converts to -(func1(*(a,+(b,c)), d),func2(e, f))