code: public Selector resolve(Selector tree, Resolver resolver, PositionAssigner positionAssigner) {
      if (tree instanceof Identifier) {
        Identifier id = (Identifier) tree;
        // The subtree to resolve is an Identifier.  Resolve the Identifier.
        return resolver.resolve(id, positionAssigner);
      }
      else if (tree.getNumIds() > 0) {
        Operator oper = (Operator) tree;
        // The subtree to resolve is an Operator, under which there are some Identifiers.
        for (int i = 0; i < oper.getOperands().length; i++)
          oper.setOperand(i,resolve(oper.getOperands()[i], resolver, positionAssigner));
        oper.assignType();
      } // else tree is a literal and not modified
      return tree;
    }
docs: Walks a Selector tree and resolves all the Identifiers
  
  @param tree the Selector tree to walk.  The tree may be modified in place by this
  method.  Strictly speaking, only Identifier nodes can ever be replaced, but, since
  the tree can consist of only an Identifier, this may result in the tree being
  replaced rather than modified.
  
  @param resolver an implementation of the Resolver interface which will be called with
  every identifier encountered and also to push and pop Identifier resolution contexts.
  
  @return a replacement Selector tree.  This will be the old tree modified in place
  except for the special case where the top level node was an Identifier and it was
  replaced by the resolver.