Ejemplo n.º 1
0
  /*package*/ public NonTerminalType(IConstructor cons) {
    // TODO refactor this into different factory methods in RascalTypeFactory

    if (cons.getConstructorType() == RascalValueFactory.Tree_Appl) {
      // Note that here we go from * to + lists if the list is not empty
      this.symbol = TreeAdapter.getType((ITree) cons);
    } else if (cons.getConstructorType() == RascalValueFactory.Tree_Amb) {
      ISet alts = TreeAdapter.getAlternatives((ITree) cons);

      if (!alts.isEmpty()) {
        ITree first = (ITree) alts.iterator().next();
        this.symbol = TreeAdapter.getType(first);
      } else {
        this.symbol =
            IRascalValueFactory.getInstance().constructor(RascalValueFactory.Symbol_Empty);
      }
    } else if (cons.getConstructorType() == RascalValueFactory.Tree_Cycle) {
      this.symbol = TreeAdapter.getType((ITree) cons);
    } else if (cons.getType() == RascalValueFactory.Symbol) {
      this.symbol = cons;
    } else if (cons.getType() == RascalValueFactory.Production) {
      this.symbol = ProductionAdapter.getType(cons);
    } else {
      throw new ImplementationError("Invalid concrete syntax type constructor:" + cons);
    }
  }
  public ITree filterAmbiguity(ITree ambCluster, Object environment) {
    ISet alts = (ISet) ambCluster.get("alternatives");

    if (alts.size() == 0) {
      return null;
    }

    Environment env = (Environment) environment;

    Result<IValue> var = env.getFrameVariable("amb");

    if (var != null && var instanceof ICallableValue) {
      Type type = RascalTypeFactory.getInstance().nonTerminalType(ambCluster);
      ICallableValue func = (ICallableValue) var;
      try {
        Result<IValue> result = func.call(new Type[] {TF.setType(type)}, new IValue[] {alts}, null);

        if (result.getType().isBottom()) {
          return ambCluster;
        }
        ITree r = (ITree) result.getValue();
        if (TreeAdapter.isAmb(r)) {
          ISet returnedAlts = TreeAdapter.getAlternatives(r);
          if (returnedAlts.size() == 1) {
            return (ITree) returnedAlts.iterator().next();
          } else if (returnedAlts.size() == 0) {
            return null;
          } else {
            return r;
          }
        }

        return (ITree) result.getValue();
      } catch (ArgumentMismatch e) {
        return ambCluster;
      }
    }

    return ambCluster;
  }
  @Override
  protected Result<IBool> equalToConcreteSyntax(ConcreteSyntaxResult that) {
    IConstructor left = this.getValue();
    IConstructor right = that.getValue();

    if (TreeAdapter.isLayout(left) && TreeAdapter.isLayout(right)) {
      return bool(true, ctx);
    }

    if (TreeAdapter.isAppl(left) && TreeAdapter.isAppl(right)) {
      IConstructor p1 = TreeAdapter.getProduction(left);
      IConstructor p2 = TreeAdapter.getProduction(right);

      if (!p1.isEqual(p2)) {
        return bool(false, ctx);
      }

      IList l1 = TreeAdapter.getArgs(left);
      IList l2 = TreeAdapter.getArgs(right);

      if (l1.length() != l2.length()) {
        return bool(false, ctx);
      }
      for (int i = 0; i < l1.length(); i++) {
        IValue kid1 = l1.get(i);
        IValue kid2 = l2.get(i);
        // Recurse here on kids to reuse layout handling etc.
        Result<IBool> result =
            makeResult(kid1.getType(), kid1, ctx).equals(makeResult(kid2.getType(), kid2, ctx));
        if (!result.getValue().getValue()) {
          return bool(false, ctx);
        }
        if (TreeAdapter.isContextFree(left)) {
          i++; // skip layout
        }
      }
      return bool(true, ctx);
    }

    if (TreeAdapter.isChar(left) && TreeAdapter.isChar(right)) {
      return bool((TreeAdapter.getCharacter(left) == TreeAdapter.getCharacter(right)), ctx);
    }

    if (TreeAdapter.isAmb(left) && TreeAdapter.isAmb(right)) {
      ISet alts1 = TreeAdapter.getAlternatives(left);
      ISet alts2 = TreeAdapter.getAlternatives(right);

      if (alts1.size() != alts2.size()) {
        return bool(false, ctx);
      }

      // TODO: this is very inefficient
      again:
      for (IValue alt1 : alts1) {
        for (IValue alt2 : alts2) {
          Result<IBool> result =
              makeResult(alt1.getType(), alt1, ctx).equals(makeResult(alt2.getType(), alt2, ctx));
          if (result.getValue().getValue()) {
            // As soon an alt1 is equal to an alt2
            // continue the outer loop.
            continue again;
          }
        }
        // If an alt1 is not equal to any of the the alt2's return false;
        return bool(false, ctx);
      }
      return bool(true, ctx);
    }

    return bool(false, ctx);
  }