将方程从一种语言转换为另一种语言

时间:2014-05-12 04:20:36

标签: python regex parsing

我有一项任务,我需要使用Python将一种语言(MATLAB)的方程转换为另一种语言(C ++)。除了动力操作外,一切都很简单。方程式由Python字符串表示。

例如,我想转换

Eq = ((a+b)^2 + (c+d)^(1/2)) * e

要,

Eq = (pow((a+b),2) + pow(c+d, 1/2)) * e

我尝试了正则表达式,但由于嵌套括号,它似乎不起作用。有没有好办法呢?

3 个答案:

答案 0 :(得分:2)

解决此问题的最佳方法是使用Python的抽象语法树。我们可以使用ast模块来实现。

import ast, _ast

ops = {_ast.Mult: "*", _ast.Add: "+", _ast.BitXor: "pow", _ast.Div: "/"}

def rec(n):
    if isinstance(n, _ast.Expr):
        return rec(n.value)
    elif isinstance(n, _ast.BinOp):
        if isinstance(n.op, _ast.BitXor):
            return "{}({}, {})".format(ops[type(n.op)], rec(n.left),rec(n.right))
        else:
            return "({} {} {})".format(rec(n.left), ops[type(n.op)],rec(n.right))
    elif isinstance(n, _ast.Name):
        return n.id
    elif isinstance(n, _ast.Num):
        return n.n

print rec(ast.parse("(((a+b)^2) + ((c+d)^(1/2))) * e").body[0])
# ((pow((a + b), 2) + pow((c + d), (1 / 2))) * e)

注意:由于^表示Python中的二进制异或操作,因此需要用一个额外的括号括起该表达式,就像我在示例中所示。

首先,我们检查它是否是表达式,然后我们处理它的值。如果它是二进制操作,我们检查它是否为Bitwise XOR,在这种情况下我们以不同的格式返回结果,否则我们返回像left op right这样的结果。如果当前项看起来像名称,那么我们会返回其id,如果是数字,我们会返回属性n

答案 1 :(得分:1)

您可以按照以下方式执行此操作。注意:这仍然是一种非常原始的方法,我要小心依赖它100%:

import re

s = "Eq = ((a+b)^2 + (c+d)^(1/2)) * e"

>>> print re.sub(r'\(([^()\s]*)\)\^\(?([^()\s]*)\)?', 'pow(\\1,\\2)', s)
Eq = (pow(a+b,2) + pow(c+d,1/2)) * e

答案 2 :(得分:0)

我认为我使用简单的tokeniser和解析器而不是正则表达式来做到这一点。它不是that hard编写的,并且比基于正则表达式的解析器更强大和可读。