Package org.rascalmpl.values.uptr

Source Code of org.rascalmpl.values.uptr.SymbolAdapter

/*******************************************************************************
* Copyright (c) 2009-2013 CWI
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:

*   * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
*   * Tijs van der Storm - Tijs.van.der.Storm@cwi.nl
*   * Paul Klint - Paul.Klint@cwi.nl - CWI
*   * Mark Hills - Mark.Hills@cwi.nl (CWI)
*   * Arnold Lankamp - Arnold.Lankamp@cwi.nl
*******************************************************************************/
package org.rascalmpl.values.uptr;

import org.eclipse.imp.pdb.facts.IConstructor;
import org.eclipse.imp.pdb.facts.IInteger;
import org.eclipse.imp.pdb.facts.IList;
import org.eclipse.imp.pdb.facts.ISet;
import org.eclipse.imp.pdb.facts.IString;
import org.eclipse.imp.pdb.facts.IValue;
import org.eclipse.imp.pdb.facts.IValueFactory;
import org.rascalmpl.interpreter.asserts.ImplementationError;
import org.rascalmpl.values.ValueFactoryFactory;

public class SymbolAdapter {
  private static final IValueFactory VF = ValueFactoryFactory.getValueFactory();
 
  private SymbolAdapter() {
    super();
  }
 
  public static IConstructor delabel(IConstructor sym) {
    if (isLabel(sym)) {
      return (IConstructor) sym.get("symbol"); // do not use getSymbol() here!
    }
    return sym;
  }

  public static boolean isLabel(IConstructor sym) {
    return sym.getConstructorType() == Factory.Symbol_Label;
  }

  public static boolean isSort(IConstructor tree) {
    tree = delabel(tree);
    return tree.getConstructorType() == Factory.Symbol_Sort;
  }

  public static boolean isMeta(IConstructor tree) {
    tree = delabel(tree);
    return tree.getConstructorType() == Factory.Symbol_Meta;
  }
 
  public static boolean isStartSort(IConstructor tree) {
    tree = delabel(tree);
    return tree.getConstructorType() == Factory.Symbol_Start_Sort;
 
 
  public static boolean isStart(IConstructor tree) {
    tree = delabel(tree);
    return tree.getConstructorType() == Factory.Symbol_START;
  }
   
  public static IConstructor getStart(IConstructor tree) {
    if (isStartSort(tree)) {
      tree = delabel(tree);
      return (IConstructor) tree.get("start");
    }
    throw new ImplementationError("Symbol does not have a child named start: " + tree);
  }

 
  public static IConstructor getLabeledSymbol(IConstructor tree) {
    return ((IConstructor) tree.get("symbol"));
  }
   
  public static IConstructor getSymbol(IConstructor tree) {
    tree = delabel(tree);
    if (isOpt(tree) || isIterPlus(tree) || isIterStar(tree|| isIterPlusSeps(tree) || isIterStarSeps(tree) || isMeta(tree) || isConditional(tree)) {
      return ((IConstructor) tree.get("symbol"));
    }
   
    throw new ImplementationError("Symbol does not have a child named symbol: " + tree);
  }
 
  public static boolean isConditional(IConstructor tree) {
    return tree.getConstructorType() == Factory.Symbol_Conditional;
  }

  public static String getLabelName(IConstructor tree) {
    return ((IString) tree.get("name")).getValue();
  }
 
  /**
   * Use this to get a name of a sort or parameterized sort, not to get the name of a label.
   * @param tree sort or parameterized sort
   * @return the name of the sort
   */
  public static String getName(IConstructor tree) {
    tree = delabel(tree);
   
    return ((IString) tree.get("name")).getValue();
  }
 
  public static String getLabel(IConstructor tree) {
    if (isLabel(tree)) {
      return ((IString) tree.get("name")).getValue();
    }
   
    throw new ImplementationError("Symbol does not have a child named \"label\" : " + tree);
  }

  public static boolean isParameterizedSort(IConstructor tree) {
    return tree.getConstructorType() == Factory.Symbol_ParameterizedSort;
  }
 
  public static boolean isParameterizedLex(IConstructor tree) {
    return tree.getConstructorType() == Factory.Symbol_ParameterizedLex;
  }
 
  public static boolean isLiteral(IConstructor tree) {
    return tree.getConstructorType() == Factory.Symbol_Lit;
  }

  public static boolean isCILiteral(IConstructor tree) {
    return tree.getConstructorType() == Factory.Symbol_CiLit;
  }

  public static boolean isIterStar(IConstructor tree) {
    return tree.getConstructorType() == Factory.Symbol_IterStar;
  }
 
  public static boolean isIterPlus(IConstructor tree) {
    return tree.getConstructorType() == Factory.Symbol_IterPlus;
  }
 
  public static boolean isLayouts(IConstructor tree) {
    return tree.getConstructorType() == Factory.Symbol_LayoutX;
  }
 
  public static boolean isStarList(IConstructor tree) {
    tree = delabel(tree);
    return isIterStar(tree) || isIterStarSeps(tree) ;
  }
 
  public static boolean isPlusList(IConstructor tree) {
    tree = delabel(tree);
    return isIterPlus(tree) || isIterPlusSeps(tree);
  }
 
  public static boolean isSepList(IConstructor tree){
    tree = delabel(tree);
    return isIterPlusSeps(tree) || isIterStarSeps(tree);
  }
 
  public static boolean isAnyList(IConstructor tree) {
    tree = delabel(tree);
    return isStarList(tree) || isPlusList(tree);
  }
 
  public static boolean isOpt(IConstructor tree) {
    return delabel(tree).getConstructorType() == Factory.Symbol_Opt;
  }
 
  public static boolean isSequence(IConstructor tree){
    return delabel(tree).getConstructorType() == Factory.Symbol_Seq;
  }
 
  public static boolean isAlternative(IConstructor tree){
    return delabel(tree).getConstructorType() == Factory.Symbol_Alt;
  }

  public static String toString(IConstructor symbol, boolean withLayout) {
    // TODO: this code clones the symbol formatter impemented in Rascal.
    // When we have a faster Rascal (compiler?) we should remove this clone.
   
    if (isLabel(symbol)) {
      return toString((IConstructor) symbol.get("symbol"), withLayout) + " " + ((IString) symbol.get("name")).getValue();
    }
    if (isSort(symbol) || isLex(symbol) || isKeyword(symbol)) {
      return getName(symbol);
    }
    if (isCharClass(symbol)) {
      IList ranges = getRanges(symbol);
      StringBuilder b = new StringBuilder();
      b.append("[");
      for (IValue range : ranges) {
        IInteger from = getRangeBegin(range);
        IInteger to = getRangeEnd(range);
        if  (from.equals(to)) {
          b.append(escapeChar(from.intValue()));
        }
        else {
          b.append(escapeChar(from.intValue()));
          b.append("-");
          b.append(escapeChar(to.intValue()));
        }
      }
      b.append("]");
      return b.toString();
    }
   
   
    if (isIterPlusSeps(symbol)) {
      IList seps = getSeparators(symbol);
      StringBuilder b = new StringBuilder();
     
      if (!withLayout && seps.length() == 1 && isLayouts((IConstructor) seps.get(0))) {
        b.append(toString(getSymbol(symbol), withLayout));
        b.append('+');
      }
      else {
        b.append('{');
        b.append(toString(getSymbol(symbol), withLayout));
        for (IValue sep : seps) {
          b.append(" ");
          b.append(toString((IConstructor) sep, withLayout));
        }
        b.append('}');
        b.append('+');
      }
     
      return b.toString();
     
    }
   
    if (isIterStarSeps(symbol)) {
      StringBuilder b = new StringBuilder();
       IList seps = getSeparators(symbol);
      
      if (!withLayout && seps.length() == 1 && isLayouts((IConstructor) seps.get(0))) {
        b.append(toString(getSymbol(symbol), withLayout));
        b.append('*');
      }
      else {
        b.append('{');
        b.append(toString(getSymbol(symbol), withLayout));
        for (IValue sep : seps) {
          if (!isLayouts((IConstructor) sep)) {
            b.append(" ");
            b.append(toString((IConstructor) sep, withLayout));
          }
        }
        b.append('}');
        b.append('*');
      }
      return b.toString();
    }
    if (isIterPlus(symbol)) {
      return toString(getSymbol(symbol), withLayout) + '+';
    }
    if (isIterStar(symbol)) {
      return toString(getSymbol(symbol), withLayout) + '*';
    }
    if (isOpt(symbol)) {
      return toString(getSymbol(symbol), withLayout) + '?';
    }
    if (isSeq(symbol)) {
      return "(" + toString(getSymbols(symbol), ' ', withLayout) + ")";
    }
    if (isAlt(symbol)) {
      ISet alts = getAlternatives(symbol);
      StringBuilder b = new StringBuilder();
      b.append("(");
      boolean first = true;
      for (IValue elem : alts) {
        if (!first) {
          first = false;
          b.append(" | ");
        }
        b.append(toString((IConstructor) elem, withLayout));
      }
      b.append(")");
      return b.toString();
    }
    if (isLayouts(symbol)) {
      return withLayout ? "layout[" + symbol.get("name") + "]" : "";
    }
    if (isLiteral(symbol)) {
      return '"' + ((IString) symbol.get("string")).getValue() + '"';
    }
    if (isCILiteral(symbol)) {
      return '\'' + ((IString) symbol.get("string")).getValue() + '\'';
    }
    if (isParameterizedSort(symbol) || isParameterizedLex(symbol)) {
      StringBuilder b = new StringBuilder();
      b.append(getName(symbol));
      IList params = (IList) symbol.get("parameters");
      b.append('[');
      b.append(toString(params, ',', withLayout));
      b.append(']');
      return b.toString();
    }
    if (isStartSort(symbol)) {
      return "start[" + toString(getStart(symbol), withLayout) + "]";
    }
    if (isParameter(symbol)) {
      return "&" + getName(symbol);
    }
   
    if (isInt(symbol) || isStr(symbol) || isReal(symbol) || isBool(symbol) || isRat(symbol)
        || isNode(symbol) || isValue(symbol) || isVoid(symbol) || isNum(symbol) || isDatetime(symbol) || isLoc(symbol)) {
      return symbol.getName();
    }
   
    if (isSet(symbol) || isList(symbol) || isBag(symbol) || isReifiedType(symbol)) {
      return symbol.getName() + "[" + toString((IConstructor) symbol.get("symbol"), withLayout) + "]";
    }
   
    if (isRel(symbol) || isListRel(symbol) || isTuple(symbol)) {
      StringBuilder b = new StringBuilder();
      b.append(symbol.getName());
      IList symbols = (IList) symbol.get("symbols");
      b.append('[');
      b.append(toString(symbols, ',', withLayout));
      b.append(']');
      return b.toString();
    }
   
    if (isMap(symbol)) {
      return symbol.getName() + "[" + toString((IConstructor) symbol.get("from"), withLayout) + "," + toString((IConstructor) symbol.get("to"), withLayout) + "]";
    }
   
    if (isConditional(symbol)) {
      ISet conditions = getConditions(symbol);
      StringBuilder b = new StringBuilder();
      // first prefix conditions
      for (IValue elem : conditions) {
        IConstructor cond = (IConstructor) elem;
        switch (cond.getConstructorType().getName()) {
        case "precede":
          b.append(toString((IConstructor) cond.get("symbol"), withLayout));
          b.append(" << ");
          break;
        case "not-precede":
          b.append(toString((IConstructor) cond.get("symbol"), withLayout));
          b.append(" !<< ");
          break;
        case "begin-of-line":
          b.append("^ ");
          break;
        }
      }
      // then the symbol
      b.append(toString(getSymbol(symbol), withLayout));
     
      // then the postfix conditions
      for (IValue elem : conditions) {
        IConstructor cond = (IConstructor) elem;
        switch (cond.getConstructorType().getName()) {
        case "follow":
          b.append(" >> ");
          b.append(toString((IConstructor) cond.get("symbol"), withLayout));
          break;
        case "not-follow":
          b.append(" !>> ");
          b.append(toString((IConstructor) cond.get("symbol"), withLayout));
          break;
        case "delete":
          b.append(" \\ ");
          b.append(toString((IConstructor) cond.get("symbol"), withLayout));
          break;
        case "except":
          b.append("!");
          b.append(((IString) cond.get("label")).getValue());
        case "end-of-line":
          b.append(" $");
          break;
        }
      }
       
      return b.toString();
    }
   
    if (isADT(symbol) || isAlias(symbol)) {
      StringBuilder b = new StringBuilder();
      b.append(getName(symbol));
      IList params = (IList) symbol.get("parameters");
     
      if (!params.isEmpty()) {
        b.append('[');
        b.append(toString(params, ',', withLayout));
        b.append(']');
      }
      return b.toString();
    }
   
    if (isFunc(symbol)) {
      StringBuilder b = new StringBuilder();
      b.append(toString((IConstructor) symbol.get("ret"), withLayout));
      b.append("(");
      b.append(toString((IList) symbol.get("parameters"), ',', withLayout));
      b.append(")");
      return b.toString();
    }
   
    if (isCons(symbol)) {
      StringBuilder b = new StringBuilder();
      b.append(toString((IConstructor) symbol.get("adt"), withLayout));
      b.append(" ");
      b.append(((IString) symbol.get("name")).getValue());
      b.append("(");
      b.append(toString((IList) symbol.get("parameters"), ',', withLayout));
      b.append(")");
    }
   
    // TODO: add more to cover all different symbol constructors
    return symbol.toString();
  }

  private static ISet getConditions(IConstructor symbol) {
    return (ISet) symbol.get("conditions");
  }

  /**
   * char-classes have almost the same escape convention as char classes except for spaces
   * @param from
   * @return
   */
  private static String escapeChar(int from) {
    if (from == ' ') {
      return "\\ ";
    }
   
    String strRep = VF.string(from).toString();
    return strRep.substring(1, strRep.length() - 1);
  }

  private static IInteger getRangeEnd(IValue range) {
    return (IInteger) ((IConstructor) range).get("end");
  }

  private static IInteger getRangeBegin(IValue range) {
    return (IInteger) ((IConstructor) range).get("begin");
  }

  public static IList getRanges(IConstructor symbol) {
    return (IList) symbol.get("ranges");
  }

  public static IList getSymbols(IConstructor symbol) {
    return (IList) symbol.get("symbols");
  }

  private static String toString(IList symbols, char sep, boolean withLayout) {
    StringBuilder b = new StringBuilder();
   
    if (symbols.length() > 0) {
      b.append(toString((IConstructor) symbols.get(0), false));
      for (int i = 1; i < symbols.length(); i++) {
        IConstructor sym = (IConstructor) symbols.get(i);
        if (!withLayout && isLayouts(sym)) {
          continue;
        }
        b.append(sep);
        b.append(toString(sym, withLayout));
      }
    }
   
    return b.toString();
  }
 
  public static boolean isCons(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Cons;
  }
 
  public static boolean isFunc(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Func;
  }

  public static boolean isAlias(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Alias;
  }

  public static boolean isADT(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Adt;
  }

  public static boolean isReifiedType(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_ReifiedType;
  }

  public static boolean isBag(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Bag;
  }

  public static boolean isList(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_List;
  }

  public static boolean isSet(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Set;
  }

  public static boolean isTuple(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Tuple;
  }

  public static boolean isRel(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Rel;
  }
 
  public static boolean isListRel(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_ListRel;
  }

  public static boolean isMap(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Map;
  }

  public static boolean isDatetime(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Datetime;
  }
 
  public static boolean isLoc(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Loc;
  }

  public static boolean isNum(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Num;
  }

  public static boolean isVoid(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Void;
  }

  public static boolean isValue(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Value;
  }

  public static boolean isNode(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Node;
  }

  public static boolean isRat(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Rat;
  }

  public static boolean isBool(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Bool;
  }

  public static boolean isReal(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Real;
  }

  public static boolean isStr(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Str;
  }

  public static boolean isInt(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Int;
  }

  public static boolean isParameter(IConstructor symbol) {
    return symbol.getConstructorType() == Factory.Symbol_Parameter;
  }

  public static IConstructor getRhs(IConstructor symbol) {
    symbol = delabel(symbol);
    return (IConstructor) symbol.get("rhs");
  }
 
  public static boolean isIterStarSeps(IConstructor rhs) {
    rhs = delabel(rhs);
    return rhs.getConstructorType() == Factory.Symbol_IterStarSepX;
  }
 
  public static boolean isIterPlusSeps(IConstructor rhs) {
    rhs = delabel(rhs);
    return rhs.getConstructorType() == Factory.Symbol_IterSepX;
  }

  public static IList getSeparators(IConstructor rhs) {
    rhs = delabel(rhs);
    return (IList) rhs.get("separators");
  }

  public static boolean isLex(IConstructor rhs) {
    return rhs.getConstructorType() == Factory.Symbol_Lex;
  }
 
  public static boolean isKeyword(IConstructor rhs) {
    return rhs.getConstructorType() == Factory.Symbol_Keyword;
  }

  public static boolean isEmpty(IConstructor rhs) {
    return rhs.getConstructorType() == Factory.Symbol_Empty;
  }
 
  /**
   * Computes symbol equality modulo lex/sort/layout/keyword distinction and modulo labels and conditions
   */
  public static boolean isEqual(IConstructor l, IConstructor r) {
    while (isLabel(l)) {
      l = getLabeledSymbol(l);
    }
   
    while (isLabel(r)) {
      r = getLabeledSymbol(r);
    }
   
    while (isConditional(l)) {
      l = getSymbol(l);
    }
   
    while (isConditional(r)) {
      r = getSymbol(r);
    }
   
    if (isLayouts(l) && isLayouts(r)) {
      return true;
    }
   
    if (isSort(l) || isLex(l) || isKeyword(l) || isLayouts(l)) {
      if (isLex(r) || isSort(r) || isKeyword(r) || isLayouts(r)) {
        return getName(l).equals(getName(r));
      }
    }
   
    if (isParameterizedSort(l) && isParameterizedSort(r)) {
      return getName(l).equals(getName(r)) && isEqual(getParameters(l), getParameters(r));
    }
   
    if (isParameterizedLex(l) && isParameterizedLex(r)) {
      return getName(l).equals(getName(r)) && isEqual(getParameters(l), getParameters(r));
    }
   
    if (isParameter(l) && isParameter(r)) {
      return getName(l).equals(getName(r));
    }
   
    if ((isIterPlusSeps(l) && isIterPlusSeps(r)) || (isIterStarSeps(l) && isIterStarSeps(r))) {
      return isEqual(getSymbol(l), getSymbol(r)) && isEqual(getSeparators(l), getSeparators(r));
    }
   
    if ((isIterPlus(l) && isIterPlus(r)) || (isIterStar(l) && isIterStar(r)) || (isOpt(l) && isOpt(r))) {
      return isEqual(getSymbol(l), getSymbol(r));
    }
   
    if (isEmpty(l) && isEmpty(r)) {
      return true;
    }
   
    if (isAlt(l) && isAlt(r)) {
      return isEqual(getAlternatives(l), getAlternatives(r));
    }
   
    if (isSeq(l) && isSeq(r)) {
      return isEqual(getSequence(l), getSequence(r));
    }
   
    if ((isLiteral(l) && isLiteral(r)) || (isCILiteral(l) && isCILiteral(r)) || (isCharClass(l) && isCharClass(r))) {
      return l.isEqual(r);
    }
   
    return false;
  }

  private static IList getParameters(IConstructor l) {
    return (IList) l.get("parameters");
  }

  public static boolean isCharClass(IConstructor r) {
    return r.getConstructorType() == Factory.Symbol_CharClass;
  }

  private static IList getSequence(IConstructor r) {
    return (IList) r.get("sequence");
  }

  public static boolean isEqual(ISet l, ISet r) {
    if (l.size() != r.size()) {
      return false;
    }
   
    OUTER:for (IValue le : l) {
      for (IValue re : r) {
        if (isEqual((IConstructor) le, (IConstructor) re)) {
          continue OUTER; // found a match
        }

        return false; // no partner found
      }
    }

    return true;
  }

  private static ISet getAlternatives(IConstructor r) {
    return (ISet) r.get("alternatives");
  }

  public static boolean isAlt(IConstructor l) {
    return l.getConstructorType() == Factory.Symbol_Alt;
  }

  public static boolean isSeq(IConstructor l) {
    return l.getConstructorType() == Factory.Symbol_Seq;
  }
 
  public static boolean isEqual(IList l, IList r) {
    if (l.length() != r.length()) {
      return false;
    }
     
    for (int i = 0; i < l.length(); i++) {
      if (!isEqual((IConstructor) l.get(i), (IConstructor) r.get(i))) {
        return false;
      }
    }
   
    return true;
  }
}
TOP

Related Classes of org.rascalmpl.values.uptr.SymbolAdapter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.