1

我想做一些类似于使用 Python 进行常量折叠的事情。

Python 有一个方便的内置函数 eval(),因此可以通过应用 eval() 轻松折叠只有常量的方程。

例子:

s = '4 + (5) * 2'
reduced_s = str(eval(s))  # '14'

但是,我想实现的常量折叠应该处理非常量标签。

例子:

s = '_tbl + (2) + (2) * 4' 
should be folded to '_tbl + 10'.

如果常量部分由标签分隔,例如 (s = '2 + _tbl + 4'),它仍应生成 '_tbl + 6' (或 '6 + _tbl)。

几年前,我使用“C”编写了一个常量折叠例程。这不是一个小例程,因为我需要构建一棵树并评估运算符的优先级。

由于 Python 语言比“C”强大得多,所以在使用 Python 做同样的事情之前,我想寻求其他人的智慧。

非常感谢您对这一挑战的见解。

4

2 回答 2

0

正如评论中指出的那样,使用ast模块听起来是个好主意。下面我给出一个示例来分离非常量标签并评估表达式的其余部分。希望,这会给一些积极的方向。

import ast

label = None

class MyTransformer(ast.NodeTransformer):

    def visit_Name(self, node):
        global label

        if(node.id != "evaluated"):
            label = node.id
            return ast.Num(0)
        return node


expression = '_tbl + (2) + (2) * 4' 

node = ast.parse("evaluated=" + expression)
node=MyTransformer().visit(node)
node = ast.fix_missing_locations(node)
eval(compile(node, '<string>', 'exec'))

print(label, str(evaluated))
于 2015-02-02T07:19:48.327 回答
0

如果eval表达式中包含“+”,那么需要解析表达式会比较困难,但是如果“+”操作在字符串表达式之外,那么可以重载操作符“ add ”来模拟评估。

class MyString(str):
    def __init__(self):
        self.mIntList = []
        self.mStringList = []

    def __add__(self, other):
        result = 0
        try:
            result = eval(other)
        except:
            self.mStringList.append(other)
        else:
            self.mIntList.append(result)
        finally:
            return self

    def __str__(self):
        return str(sum(self.mIntList)) + " ".join(self.mStringList)

if __name__ == '__main__':
    s1 = MyString()
    s1 = s1 + "_table" + "(2) + (2) * 4"
    print s1
    s2 = MyString()
    s2 = s2 + "2" + "table" + "2*4"
    print s2

输出是

10_table
10table
于 2015-02-02T05:01:21.107 回答