从抽象语法树生成前缀表达式

3

我正在使用一个Java库,它可以根据中缀表达式(1 + 3) + 4构建如下的AST:

                              BinaryIntegerExpression  
                              /          |            \
              IntegerExpression          op         IntegerExpression
                      |                  |                  |
           BinaryIntegerExpression       +           IntegerConstant
           /          |            \                        |
   IntegerExpression  op      IntegerExpression             4
          |           |             |
    IntegerConstant   +       IntegerConstant
          |                         |
          1                         3

基本上,BinaryIntegerExpression和IntegerConstant是IntegerExpression的子类。 该库有一个抽象类Visitor,它允许您重写preVisit和postVisit来遍历树。我除此之外不能碰任何东西。
这是我的尝试。我尝试使用简单的递归生成前缀表达式。对于小例子它能够正常工作。
public void preVisit(BinaryIntegerExpression expr) {

        if(stop == true)
            return;

        PrefixVisitor left = new PrefixVisitor();
        left.preVisit(expr.getLeft());

        PrefixVisitor right = new PrefixVisitor();
        right.preVisit(expr.getRight());

        str = "( " + expr.getOp().toString() + " " + left.getExpression() + " " + right.getExpression() + " )";
        stop = true;
    }

public void preVisit(IntegerConstant expr) {

        if(stop == true)
            return;

        str = " " + expr.toString() + " ";
    }

然而,我需要处理大小超过100MB的表达式,因此我在内存和性能方面遇到了问题。因此,我想使用堆栈来优化这个过程。有人可以给我一些提示吗?谢谢。

========================
编辑:该表达式是复杂分析的结果,我只是获取结果进行处理,不能从头开始构建结果。


1
MB代表兆字节,Mb代表兆比特。 - Peter Lawrey
1个回答

4

不清楚您试图做什么,但我会从一开始就将表达式构建为单个StringBuilder。这样会更快,但内存使用量并不少。100 MB的文本文件使用200 MB进行加载,再用200 MB作为String进行操作,加上您的表达式,似乎需要几GB的内存。

如果仍然使用过多内存,建议将表达式流式传输到文件中。处理这种情况的通用方法是使用一个"Appender",它是StringBuilder和PrintWriter的接口。

提示:考虑如何在不创建任何对象(至少不是直接创建)的情况下构建文本表达式。如果这样做,速度将更快。

最简单的解决方案是确保有足够的堆,并使用CPU和内存分析工具来提高其效率。


1
我想提出一个建议,即将PrefixVisitor类设置为无状态,并将StringBuilder用作previsit方法的返回类型,然后在每个步骤中不要实例化新的PrefixVisitors。 - Teudimundo
我会将StringBuilder作为参数,这样你只需要创建一个。 - Peter Lawrey
表达式是复杂分析的结果,我只是得到结果来处理它,无法从头开始构建结果。在这种情况下有没有避免递归的方法?我尝试增加堆大小:-Xmx4096m,但仍然存在内存问题。 - sean
1
如果递归是问题的话,你会遇到堆栈溢出的错误。问题在于你的数据结构消耗了多少内存并生成了多少文本。 - Peter Lawrey
谢谢。你能给我一个链接,让我了解一下你提到的“使用CPU和内存分析器来提高效率”吗?我想多了解一些相关信息。 - sean
1
@qsp Java内置了一个免费的分析器 https://visualvm.java.net/profiler.html,但是我使用商业版的 http://www.yourkit.com/features/index.jsp - Peter Lawrey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接