Package org.rascalmpl.interpreter.utils

Source Code of org.rascalmpl.interpreter.utils.Symbols

/*******************************************************************************
* 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
*   * Arnold Lankamp - Arnold.Lankamp@cwi.nl
*******************************************************************************/
package org.rascalmpl.interpreter.utils;

import java.util.List;

import org.eclipse.imp.pdb.facts.IConstructor;
import org.eclipse.imp.pdb.facts.IList;
import org.eclipse.imp.pdb.facts.IListWriter;
import org.eclipse.imp.pdb.facts.IString;
import org.eclipse.imp.pdb.facts.IValue;
import org.eclipse.imp.pdb.facts.IValueFactory;
import org.rascalmpl.ast.CaseInsensitiveStringConstant;
import org.rascalmpl.ast.Char;
import org.rascalmpl.ast.Class;
import org.rascalmpl.ast.Nonterminal;
import org.rascalmpl.ast.Range;
import org.rascalmpl.ast.StringConstant;
import org.rascalmpl.ast.Sym;
import org.rascalmpl.ast.Type;
import org.rascalmpl.interpreter.asserts.NotYetImplemented;
import org.rascalmpl.values.ValueFactoryFactory;
import org.rascalmpl.values.uptr.Factory;

public class Symbols {
  private static IValueFactory factory = ValueFactoryFactory.getValueFactory();
 
  public static IConstructor typeToSymbol(Sym type, boolean lex, String layout) {
    return (IConstructor) symbolAST2SymbolConstructor(type, lex, layout);
  }
 
  public static IConstructor typeToSymbol(Type type, boolean lex, String layout) {
    if (type.isUser()) {
      if (lex) {
        return factory.constructor(Factory.Symbol_Lex, factory.string(((org.rascalmpl.semantics.dynamic.QualifiedName.Default) type.getUser().getName()).lastName()));
      }
      else {
        return factory.constructor(Factory.Symbol_Sort, factory.string(Names.name(Names.lastName(type.getUser().getName()))));
      }
    }
   
    if (type.isSymbol()) {
      return (IConstructor) symbolAST2SymbolConstructor(type.getSymbol(), lex, layout);
    }

    throw new RuntimeException("Can't convert type to symbol: "+type);
  }
 
  // TODO: distribute this code over the dynamic.Sym classes in typeOf method
  private static IValue symbolAST2SymbolConstructor(Sym symbol, boolean lex, String layout) {
   
    if (symbol.isCaseInsensitiveLiteral()) {
      return factory.constructor(Factory.Symbol_CiLit, ciliteral2Symbol(symbol.getCistring()));
    }
    if (symbol.isCharacterClass()) {
      Class cc = symbol.getCharClass();
      return charclass2Symbol(cc);
    }
    if (symbol.isIter()) {
      if (lex) {
        return factory.constructor(Factory.Symbol_IterPlus, symbolAST2SymbolConstructor(symbol.getSymbol(), lex, layout));
      }
      else {
        IValue layoutSymbol = factory.constructor(Factory.Symbol_LayoutX, factory.string(layout));
        IValue elementSym = symbolAST2SymbolConstructor(symbol.getSymbol(), lex, layout);
        IValue seps = factory.list(layoutSymbol);
        return factory.constructor(Factory.Symbol_IterSepX, elementSym, seps);
      }
    }
    if (symbol.isIterStar()) {
      if (lex) {
        return factory.constructor(Factory.Symbol_IterStar, symbolAST2SymbolConstructor(symbol.getSymbol(), lex, layout));
      }
      else {
        IValue layoutSymbol = factory.constructor(Factory.Symbol_LayoutX, factory.string(layout));
        IValue elementSym = symbolAST2SymbolConstructor(symbol.getSymbol(), lex, layout);
        IValue seps = factory.list(layoutSymbol);
        return factory.constructor(Factory.Symbol_IterStarSepX, elementSym, seps);
      }
    }
    if (symbol.isIterSep()) {
      IValue layoutSymbol = factory.constructor(Factory.Symbol_LayoutX, factory.string(layout));
      IValue elementSym = symbolAST2SymbolConstructor(symbol.getSymbol(), lex, layout);
      IValue sepSym = symbolAST2SymbolConstructor(symbol.getSep(), lex, layout);
      IValue seps;
     
      if (lex) {
        seps = factory.list(sepSym);
      }
      else {
        seps = factory.list(layoutSymbol, sepSym, layoutSymbol);
      }
     
      return factory.constructor(Factory.Symbol_IterSepX, elementSym, seps);
    }
   
    if (symbol.isIterStarSep()) {
      IValue layoutSymbol = factory.constructor(Factory.Symbol_LayoutX, factory.string(layout));
      IValue elementSym = symbolAST2SymbolConstructor(symbol.getSymbol(), lex, layout);
      IValue sepSym = symbolAST2SymbolConstructor(symbol.getSep(), lex, layout);
      IValue seps;
      if (lex) {
        seps = factory.list(sepSym);
      }
      else {
        seps = factory.list(layoutSymbol, sepSym, layoutSymbol);
      }
      return factory.constructor(Factory.Symbol_IterStarSepX, elementSym, seps);
    }
   
    if (symbol.isLiteral()) {
      return literal2Symbol(symbol.getString());
    }
    if (symbol.isOptional()) {
      return factory.constructor(Factory.Symbol_Opt, symbolAST2SymbolConstructor(symbol.getSymbol(), lex, layout));
    }
   
    if (symbol.isStart()) {
      Nonterminal nonterminal = symbol.getNonterminal();
      return factory.constructor(Factory.Symbol_Start_Sort, factory.constructor(Factory.Symbol_Sort, factory.string(((Nonterminal.Lexical) nonterminal).getString())))
    }
    if (symbol.isNonterminal()) {
      Nonterminal nonterminal = symbol.getNonterminal();
      IString name = factory.string(((Nonterminal.Lexical) nonterminal).getString());
      if (lex) {
        return factory.constructor(Factory.Symbol_Lex, name);
      }
      else {
        return factory.constructor(Factory.Symbol_Sort, name);
      }
    }
   
    if(symbol.isSequence()){
      List<Sym> symbols = symbol.getSequence();
      IValue layoutSymbol = factory.constructor(Factory.Symbol_LayoutX, factory.string(layout));
      IValue[] symValues = new IValue[lex ? symbols.size() : symbols.size() * 2 - 1];
      for(int i = symbols.size() - 1; i >= 0; i -= lex ? 1 : 2) {
        symValues[lex ? i : i * 2] = symbolAST2SymbolConstructor(symbols.get(i), lex, layout);
        if (lex && i > 0) {
          symValues[i - 1] = layoutSymbol;
        }
      }
      IValue syms = factory.list(symValues);
      return factory.constructor(Factory.Symbol_Seq, syms);
    }
    if(symbol.isAlternative()){
      List<Sym> symbols = symbol.getSequence();
      IValue[] symValues = new IValue[symbols.size()];
      for(int i = symbols.size() - 1; i >= 0; --i){
        symValues[i] = symbolAST2SymbolConstructor(symbols.get(i), lex, layout);
      }
      IValue syms = factory.list(symValues);
      return factory.constructor(Factory.Symbol_Alt, syms);
    }
    if (symbol.isParametrized()) {
      List<Sym> symbols = symbol.getParameters();
      IValue[] symValues = new IValue[symbols.size()];
      for(int i = symbols.size() - 1; i >= 0; --i){
        symValues[i] = symbolAST2SymbolConstructor(symbols.get(i), lex, layout);
      }
      IValue syms = factory.list(symValues);
      return factory.constructor(Factory.Symbol_ParameterizedSort, factory.string(((Nonterminal.Lexical) symbol.getNonterminal()).getString()), syms);
    }
   
    if (symbol.isPrecede() || symbol.isNotPrecede() || symbol.isFollow() || symbol.isNotFollow() || symbol.isColumn() || symbol.isStartOfLine() || symbol.isEndOfLine() || symbol.isExcept()) {
      return symbolAST2SymbolConstructor(symbol.getSymbol(), lex, layout);
    }
   
    throw new RuntimeException("Symbol has unknown type: "+ symbol);
  }

  private static IValue literal2Symbol(StringConstant sep) {
    String lit = ((StringConstant.Lexical) sep).getString();
    StringBuilder builder = new StringBuilder(lit.length());
   
    // TODO: did we deal with all escapes here? probably not!
    for (int i = 1; i < lit.length() - 1; i++) {
      if (lit.charAt(i) == '\\') {
        i++;
        switch (lit.charAt(i)) {
        case 'b':
          builder.append('\b');
          break;
        case 'f':
          builder.append('\f');
          break;
        case 'n':
          builder.append('\n');
          break;
        case 't':
          builder.append('\t');
          break;
        case 'r':
          builder.append('\r');
          break;
        case '\\':
          builder.append('\\');
          break;
        case '\"':
          builder.append('\"');
          break;
        case '>':
          builder.append('>');
          break;
        case '<':
          builder.append('<');
          break;
        case '\'':
          builder.append('\'');
          break;
        case 'u':
          while (lit.charAt(i++) == 'u');
          builder.append((char) Integer.decode("0x" + lit.substring(i, i+4)).intValue());
          i+=4;
          break;
        default:
          // octal escape
          int a = lit.charAt(i++);
          int b = lit.charAt(i++);
          int c = lit.charAt(i);
          builder.append( (char) (100 * a + 10 * b + c))
        }
      }
      else {
        builder.append(lit.charAt(i));
      }
    }
   
    return factory.constructor(Factory.Symbol_Lit, factory.string(builder.toString()));
  }
 
  private static IValue ciliteral2Symbol(CaseInsensitiveStringConstant constant) {
    String lit = ((CaseInsensitiveStringConstant.Lexical) constant).getString();
    StringBuilder builder = new StringBuilder(lit.length());
   
    for (int i = 1; i < lit.length() - 1; i++) {
      if (lit.charAt(i) == '\\') {
        i++;
        switch (lit.charAt(i)) {
        case 'n':
          builder.append('\n');
          break;
        case 't':
          builder.append('\t');
          break;
        case 'r':
          builder.append('\r');
          break;
        case '\\':
          builder.append('\\');
          break;
        case '\"':
          builder.append('\'');
          break;
        default:
          int a = lit.charAt(i++);
          int b = lit.charAt(i++);
          int c = lit.charAt(i);
          builder.append( (char) (100 * a + 10 * b + c))
        }
      }
      else {
        builder.append(lit.charAt(i));
      }
    }
   
    return factory.constructor(Factory.Symbol_Lit, factory.string(builder.toString()));
  }

  private static IValue charclass2Symbol(Class cc) {
    if (cc.isSimpleCharclass()) {
      return factory.constructor(Factory.Symbol_CharClass, ranges2Ranges(cc.getRanges()));
    }
    throw new NotYetImplemented(cc);
  }
 
  private static IList ranges2Ranges(List<Range> ranges) {
    IListWriter result = factory.listWriter(Factory.CharRanges.getElementType());
   
    for (Range range : ranges) {
      if (range.isCharacter()) {
        IValue ch = char2int(range.getCharacter());
        result.append(factory.constructor(Factory.CharRange_Single, ch));
      }
      else if (range.isFromTo()) {
        IValue from = char2int(range.getStart());
        IValue to = char2int(range.getEnd());
        result.append(factory.constructor(Factory.CharRange_Range, from, to));
      }
    }
   
    return result.done();
  }

  private static IValue char2int(Char character) {
    String s = ((Char.Lexical) character).getString();
    if (s.startsWith("\\")) {
      if (s.length() > 1 && java.lang.Character.isDigit(s.charAt(1))) { // octal escape
        // TODO
        throw new NotYetImplemented("octal escape sequence in character class types");
      }
      if (s.length() > 1 && s.charAt(1) == 'u') { // octal escape
        // TODO
        throw new NotYetImplemented("unicode escape sequence in character class types");
      }
      char cha = s.charAt(1);
      switch (cha) {
      case 't': return factory.integer('\t');
      case 'n': return factory.integer('\n');
      case 'r': return factory.integer('\r');
      case '\"' : return factory.integer('\"');
      case '\'' : return factory.integer('\'');
      case '-' : return factory.integer('-');
      case '<' : return factory.integer('<');
      case '>' : return factory.integer('>');
      case '\\' : return factory.integer('\\');
      }
      s = s.substring(1);
    }
    char cha = s.charAt(0);
    return factory.integer(cha);
  }
}
TOP

Related Classes of org.rascalmpl.interpreter.utils.Symbols

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.