/**
   * resolves n to node of type R, via declaration if n is an identifier, via simple cast otherwise
   * returns null if n's declaration or n can't be cast to R or S
   */
  public Pair<R, S> resolve(BaseNode n, BaseNode parent) {
    if (n instanceof IdentNode) {
      Pair<R, S> pair = resolve((IdentNode) n);
      if (pair != null) {
        assert pair.fst == null || pair.snd == null;
        parent.becomeParent(pair.fst);
        parent.becomeParent(pair.snd);
      }
      return pair;
    }

    Pair<R, S> pair = new Pair<R, S>();
    if (clsR.isInstance(n)) {
      pair.fst = clsR.cast(n);
    }
    if (clsS.isInstance(n)) {
      pair.snd = clsS.cast(n);
    }
    if (pair.fst != null || pair.snd != null) {
      assert pair.fst == null || pair.snd == null;
      return pair;
    }

    n.reportError(
        "\""
            + n
            + "\" is a "
            + n.getUseString()
            + " but a "
            + Util.getStrListWithOr(classes, BaseNode.class, "getUseStr")
            + " is expected");
    return null;
  }