The position in the tree can be specified using a list of child numbers. Your evaluates would look something like this (quickly written; not compiled/tested):
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
}
The above should track the context as a list of numbers that tell which child you're currently processing.
Rather than implement that in each node type, I'd recommend writing a decorator (or a superclass using a template method) to do it for you, such as:
// 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);
}
If you use the decorator, make sure you decorate every node...
That gives you access to the context list.
You can then add a "stop context" parameter that you can compare (so you'd have two contexts passed in and you could compare them to see if they match.
Hope this helps! -- Scott
Scott Stanchfield
2009-11-17 21:36:16