Package wyil.util.type

Source Code of wyil.util.type.TypeParser

// Copyright (c) 2011, David J. Pearce (djp@ecs.vuw.ac.nz)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//    * Redistributions of source code must retain the above copyright
//      notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//    * Neither the name of the <organization> nor the
//      names of its contributors may be used to endorse or promote products
//      derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL DAVID J. PEARCE BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package wyil.util.type;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

import wycc.lang.NameID;
import wyfs.lang.Path;
import wyfs.util.Trie;
import wyil.lang.Type;
import static wyil.lang.Type.*;

/**
* The Type Parser is used to convert a given string into a type (or a syntax
* error). This is generally useful for debugging purposes, but it does have
* other usees as well.
*
* @author David J. Pearce
*
*/
public class TypeParser {
  private int index;
  private String str;

  public TypeParser(String str) {
    this.str = str;
  }

  public Type parse() {
    return parse(new HashSet<String>());
  }

  public Type parse(HashSet<String> typeVariables) {
    Type term = parseFunctionTerm(typeVariables);
    skipWhiteSpace();
    while (index < str.length()
        && (str.charAt(index) == '|')) {
      // union type
      match("|");
      term = Union(term,parse(typeVariables));
      skipWhiteSpace();
    }
    return term;
  }

  public Type parseFunctionTerm(HashSet<String> typeVariables) {
    Type t = parseNotTerm(typeVariables);
    if(index >= str.length()) { return t; }
    char lookahead = str.charAt(index);
    if(lookahead == '(') {
      // this is a tuple, not a bracketed type.
      match("(");
      ArrayList<Type> elems = new ArrayList();
      elems.add(parse(typeVariables));
      lookahead = str.charAt(index);
      while(lookahead == ',') {
        match(",");
        elems.add(parse(typeVariables));
        skipWhiteSpace();
        lookahead = str.charAt(index);
      }
      match(")");
      skipWhiteSpace();
      return Function(t,Type.T_VOID,elems);
    }
    return t;
  }

  public Type parseNotTerm(HashSet<String> typeVariables) {
    skipWhiteSpace();
    char lookahead = str.charAt(index);
    if(lookahead == '!') {
      match("!");
      return Negation(parseNotTerm(typeVariables));
    } else {
      return parseBraceTerm(typeVariables);
    }
  }
  public Type parseBraceTerm(HashSet<String> typeVariables) {
    skipWhiteSpace();
    char lookahead = str.charAt(index);
    if(lookahead == '(') {
      match("(");
      Type t = parse(typeVariables);
      skipWhiteSpace();
      lookahead = str.charAt(index);
      if(lookahead == ',') {
        // this is a tuple, not a bracketed type.
        ArrayList<Type> elems = new ArrayList();
        elems.add(t);
        while(lookahead == ',') {
          match(",");
          elems.add(parse(typeVariables));
          skipWhiteSpace();
          lookahead = str.charAt(index);
        }
        match(")");
        skipWhiteSpace();
        return Tuple(elems);
      } else {
        match(")");
        skipWhiteSpace();
        return t;
      }
    } else {
      return parseTerm(typeVariables);
    }
  }
  public Type parseTerm(HashSet<String> typeVariables) {
    skipWhiteSpace();
    char lookahead = str.charAt(index);

    switch (lookahead) {
    case 'a':
      match("any");
      return T_ANY;
    case 'v':
      match("void");
      return T_VOID;
    case 'n':
      match("null");
      return T_NULL;
    case 'b':
      if ((index + 1 < str.length()) && str.charAt(index + 1) == 'o') {
        match("bool");
        return T_BOOL;
      } else {
        match("byte");
        return T_BYTE;
      }
    case 'c':
      match("char");
      return T_CHAR;
    case 'i':
      match("int");
      return T_INT;
    case 'r':
      match("real");
      return T_REAL;
    case 's':
      match("string");
      return T_STRING;
    case '[':
    {
      match("[");
      Type elem = parse(typeVariables);
      match("]");
      return List(elem, false);
    }
    case '{':
    {
      match("{");
      Type elem = parse(typeVariables);
      skipWhiteSpace();
      if(index < str.length() && str.charAt(index) == '-') {
        // dictionary
        match("->");
        Type value = parse(typeVariables);
        match("}");
        return Map(elem,value);

      } else if(index < str.length() && str.charAt(index) != '}') {
        // record
        HashMap<String,Type> fields = new HashMap<String,Type>();
        String id = parseIdentifier();
        fields.put(id, elem);
        skipWhiteSpace();
        boolean isOpen = false;
        while(index < str.length() && str.charAt(index) == ',') {
          match(",");
          if(str.charAt(index) == '.') {
            match("...");
            isOpen=true;
            break;
          }
          elem = parse(typeVariables);
          id = parseIdentifier();
          fields.put(id, elem);
          skipWhiteSpace();
        }
        match("}");
        return Record(isOpen,fields);
      }
      match("}");
      return Set(elem,false);
    }
    default:
    {
      String typeVariable = parseIdentifier();
      if(typeVariables.contains(typeVariable)) {
        return Nominal(new NameID(Trie.fromString("$"),
            typeVariable));
      } else {
        typeVariables = new HashSet<String>(typeVariables);
        typeVariables.add(typeVariable);
        match("<");
        Type t = parse(typeVariables);
        match(">");
        NameID label = new NameID(Trie.fromString("$"),
            typeVariable);
        return Recursive(label, t);
      }
    }

    }
  }
  private String parseIdentifier() {
    skipWhiteSpace();
    int start = index;
    while (index < str.length()
        && Character.isJavaIdentifierPart(str.charAt(index))) {
      index++;
    }
    return str.substring(start,index);
  }
  private void skipWhiteSpace() {
    while (index < str.length()
        && Character.isWhitespace(str.charAt(index))) {
      index++;
    }
  }
  private void match(String match) {
    skipWhiteSpace();
    if ((str.length() - index) < match.length()
        || !str.startsWith(match, index)) {
      throw new IllegalArgumentException("invalid type string: "
          + str);
    }
    index += match.length();
  }
}
TOP

Related Classes of wyil.util.type.TypeParser

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.