代码之家  ›  专栏  ›  技术社区  ›  Paul-Jan

计算表达式树时停止并继续

  •  1
  • Paul-Jan  · 技术社区  · 16 年前

    基本上,我们将自定义脚本解析(lex/yacc)到表达式树中。表达式树中的每个节点都有一个.evaluate()方法,在程序完成之前,该方法将被递归调用。很好,很简单。这是一件好事,因为我几乎不知道解析技术、编译器构造等等(幸好我的同事知道一两件事)。

    现在是挑战 :我们目前正在进行的实施需要能够

    • 并在将来的任何给定时间恢复状态/位置。

    (在Win32/Dephi中执行此操作,但希望我们能够保持这种语言的不可知性)

    1 回复  |  直到 16 年前
        1
  •  1
  •   Scott Stanchfield    16 年前

    可以使用子编号列表指定树中的位置。您的计算结果如下(快速编写;未编译/测试):

    public class Context {
        private Context parent; // set in constructor
        private int child;  // with get/set
    }
    
    public ReturnType evaluate(Context context) 
        context.setChild(context.getChild() + 1);
        context = new Context(context); // push a new context for calls
        // do evaluation - when calling kids, pass context            
    }
    

    上面应该以数字列表的形式跟踪上下文,告诉您当前正在处理哪个孩子。

    与其在每种节点类型中都实现这一点,我建议您编写一个decorator(或使用模板方法的超类)来完成这项工作,例如:

    // decorator
    public class ContextTrackerEvaluator<T> implements Evaluator<T> {
        private Evaluator realEvaluator;
        public ContextTrackerEvaluator(Evaluator realEvaluator) {
            this.realEvaluator = realEvaluator;
        }
        public T evaluate(Context context) {
            context.setChild(context.getChild() + 1);
            context = new Context(context); // push a new context for calls
            realEvaluator.evaluate(context);
        }
    }
    
    // OR superclass w/ template method
    public class EvaluatorBase<T> {
        public final T evaluate(Context context) {
            context.setChild(context.getChild() + 1);
            context = new Context(context); // push a new context for calls
            doEvaluate(context);
        }
        // subclasses override doEvaluate to do their real work
        protected abstract T doEvaluate(Context context);
    }
    

    这样您就可以访问上下文列表。

    然后,您可以添加一个“stop context”参数进行比较(这样您就可以传入两个上下文,您可以比较它们是否匹配)。

    希望这有帮助! --斯科特

    推荐文章