All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.lambda.Debugger.Completion Maven / Gradle / Ivy

The newest version!
/*                        Completion.java

  Copyright 2003, Bil Lewis

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.
  
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   
*/

package com.lambda.Debugger;

//              Completion.java

/*
 */


import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;

public class Completion {

  static private HashMap		objectTable, methodTable;



    public static void printTable() {
    Set set =  methodTable.keySet();
    Iterator e = set.iterator();

    while (e.hasNext()) {
      Object key = e.next();
      Object o = methodTable.get(key);
      System.out.println(""+key +"\t\t\t"+o);
    }
  }

  public static String completeObject(String s) {
    Object result = complete(s, objectTable);
    if (result instanceof String) return((String) result);
    if (result == null) return "";
    if (result instanceof ObjectCompletionPair) return( ((ObjectCompletionPair)result).mutual );
    throw new NullPointerException("completeObject IMPOSSIBLE "+result);
  }

  public static Object completedObject(String s) throws CompletionException {
    Object result = complete(s, objectTable);
    if ( (result instanceof String) || (result == null) ) throw new CompletionException(""+result);
    if (result instanceof ObjectCompletionPair) return( ((ObjectCompletionPair)result).obj );
    throw new CompletionException("completedObject IMPOSSIBLE "+result);
  }


  public static Object complete(String s, HashMap table) {		// => "int[2]_", , (OCP)<"Demo", Demo>
    if (s.length() == 0) return "";
    char ch = s.charAt(0);

    if (Character.isDigit(ch)) {
      try {
	Integer i = new Integer(Integer.parseInt(s));
	return(new ObjectCompletionPair(s, i));
      }				// Just verify it's an int
      catch (NumberFormatException e) {return(s);}
    }

    if (ch == '"') {
      if (s.charAt(s.length()-1) == '"')
	return(new ObjectCompletionPair(s, s.substring(1, s.length()-1)));
      else
	return(s);
    }

    Object o = table.get(s);

    if (o != null) return o;

    int len = s.length();					// If they type an error, return longest possible substring
    for (int i = len; i >= 0; i--) {
      String sub = s.substring(0, i);
      o = table.get(sub);
      if (o != null) return o;
    }
    return null;    
  }


  public static void createCompletionTable() {
      HashMapEq hm = Shadow.getTable();
      if ((objectTable != null) && (objectTable.size() == hm.size())) return;
    objectTable = new HashMap(hm.size()*3);			// Correct length?
    
	Iterator iter =  hm.values().iterator();

    while (iter.hasNext()) {
	Shadow sh = (Shadow) iter.next();	
	Object key = sh.obj;
	if (key instanceof String) continue;
	String name = sh.printString(); //printString();
	if (name == null) {continue;}			// If they can't see it, they can't type it
	mapCharsObject(name, key, objectTable);
    }

  }


  public static void mapCharsMethod(String name, Method method, HashMap table) {
    int len = name.length();

    for (int i = 1; i <= len; i++) {
      String sub = name.substring(0, i);
      MethodCompletionPair mcp = (MethodCompletionPair) table.get(sub);

      if (mcp == null) {
	table.put(sub, new MethodCompletionPair(name, method));
	continue;
      }

      String mutual = longest(name, mcp.mutual);
      if (mcp.mutual.equals(mutual)) continue;
      mcp.mutual = mutual;
      mcp.methods.clear();
    }
    
    MethodCompletionPair mcp  = (MethodCompletionPair) table.get(name);
    mcp.methods.add(method);
  }


  public static void mapCharsObject(String name, Object obj, HashMap table) {
    int len = name.length();

    for (int i = 1; i <= len; i++) {
      String sub = name.substring(0, i);
      ObjectCompletionPair ocp = (ObjectCompletionPair) table.get(sub);

      if (ocp == null) {
	table.put(sub, new ObjectCompletionPair(name, obj));
	continue;
      }

      String mutual = longest(name, ocp.mutual);
      if (ocp.mutual == mutual) continue;
      ocp.mutual = mutual;
      ocp.obj = null;
    }
    
    ObjectCompletionPair ocp  = (ObjectCompletionPair) table.get(name);
    ocp.obj = obj;
  }


  public static String longest(String s1, String s2) {
    int len = Math.min(s1.length(), s2.length());

    for (int i = 0; i < len; i++) {
      if (s1.charAt(i) == s2.charAt(i)) continue;
      return s1.substring(0, i);
    }

    if (s1.length() < s2.length())
      return s1;
    else
      return s2;
  }
    


  public static String completeCall(String s) {				// Do completion of a whole line: .quick(1, 2)
    int len = s.length();
    int dotIndex = s.indexOf('.');
    int objIndex = dotIndex-1;
    String objString, sub, methodString;
    int closeIndex = s.indexOf(')');

    if (objIndex < 0)
      sub = s;
    else
      sub = s.substring(0, objIndex+1);

    Object obj = complete(sub, objectTable);
    if (obj instanceof String) {
      if (dotIndex > 0) return(s+" NO SUCH OBJECT: " + obj);					//
      return (String)obj;
    }
    else if (obj instanceof ObjectCompletionPair) {
      objString = ((ObjectCompletionPair)obj).mutual;
      obj = ((ObjectCompletionPair)obj).obj;
    }
    else {
      throw new NullPointerException("completeCall IMPOSSIBLE1 "+s+" -> "+obj);      
    }

    if (dotIndex < 0) return objString;
    if (len == dotIndex) return objString+".";

    if (obj instanceof Class)
      createMethodTable((Class)obj);
    else
      createMethodTable(obj.getClass());

    int openIndex = s.indexOf('(');
    if (openIndex == -1)
      sub = s.substring(dotIndex+1);
    else
      sub = s.substring(dotIndex+1, openIndex);
    
    Object methodObj = complete(sub, methodTable);
    if (methodObj == null) return(objString + ".");					// No possible completionom
    
    if (methodObj instanceof String) return(objString + "." + methodObj);
    if (methodObj instanceof MethodCompletionPair) {
      methodString = ((MethodCompletionPair)methodObj).mutual;
      if (openIndex < 0) return(objString + "." + methodString);
      if (openIndex+1 == len) return(objString + "." + methodString + "(");
    }
    else {
      throw new NullPointerException("completeCall IMPOSSIBLE2 "+s);   
    }



    // NO ARGS

    if (closeIndex == openIndex+1) return s;



    // FIRST ARG    
    int arg1Index;
    int comma1Index= s.indexOf(',');

    if (comma1Index < 0) {
      if (closeIndex > 0)
	arg1Index = closeIndex-1;
      else
	arg1Index = len-1;
    }
    else
      arg1Index = comma1Index-1;

    sub = s.substring(openIndex+1, arg1Index+1);
    String arg1String = sub;

    if (sub.length() == 0) return(objString + "." + methodString + "(");
    char ch = sub.charAt(0);
    if (Character.isDigit(ch)) {
      try {Integer.parseInt(sub);}				// Just verify it's an int
      catch (NumberFormatException e) {return(objString + "." + methodString + "("+ch);}
    }

    else if (ch == '"') {
      if (sub.charAt(sub.length()-1) != '"') {return(objString + "." + methodString + "("+sub);}		// If incomplete quote
    }

    // Must be  or MyObj, or MyObj[23]_1
    else if (! (Character.isLetter(ch) || ch == '<') )
      return(objString + "." + methodString + "(");
    else {
      Object arg1 = complete(sub, objectTable);

      if (arg1 instanceof String) {
	arg1String = (String) arg1;
	if (arg1Index+1 == len) return(objString + "." + methodString + "(" + arg1String);
	if ((comma1Index+1 == len) || (comma1Index+2 == len)) return(objString + "." + methodString + "(" + arg1String + ", "); // ", " required
	if (closeIndex == arg1Index+1) return(objString + "." + methodString + "(" + arg1String + ")"); // ", " required
      }
      else {
	if (arg1 instanceof ObjectCompletionPair) {
	  arg1String = ((ObjectCompletionPair) arg1).mutual;
	}
	else {
	  Shadow ss = (Shadow) Shadow.getAlternate(arg1);
	  if (ss == null) return(objString + "." + methodString + "(");
	  arg1String = ss.tostring;
	}
	if ((comma1Index<0) && (closeIndex<0)) return(objString + "." + methodString + "(" + arg1String);
	if ((comma1Index+1 == len) || (comma1Index+2 == len)) return(objString + "." + methodString + "(" + arg1String + ", "); // ", " required
	if (closeIndex == arg1Index+1) return(objString + "." + methodString + "(" + arg1String + ")"); // ", " required
      }

    }

    if (closeIndex == arg1Index+1) return(objString + "." + methodString + "(" + arg1String + ")"); // ", " required
    if (comma1Index<0) return(objString + "." + methodString + "(" + arg1String);
    if ((comma1Index+1 == len) || (comma1Index+2 == len)) return(objString + "." + methodString + "(" + arg1String + ", "); // ", " required
    if (s.charAt(comma1Index+1) != ' ') return(objString + "." + methodString + "(" + arg1String + ", "); // ", " required




    // SECOND ARG    
    int arg2Index;
    int comma2Index= s.indexOf(',', comma1Index+1);


    if (comma2Index < 0) {
      if (closeIndex > 0)
	arg2Index = closeIndex-1;
      else
	arg2Index = len-1;
    }
    else
      arg2Index = comma2Index-1;

    sub = s.substring(comma1Index+2, arg2Index+1);
    String arg2String = sub;					// if number, boolean, or string: don't complete

    if (sub.length() == 0) return(objString + "." + methodString + "("+ arg1String + ", ");
    ch = sub.charAt(0);
    if (Character.isDigit(ch)) {
      try {Integer.parseInt(sub);}				// Just verify it's an int
      catch (NumberFormatException e) {return(objString + "." + methodString + "("+ arg1String + ", "+ch);}
    }

    else if (ch == '"') {
      if (sub.charAt(sub.length()-1) != '"') {return(objString + "." + methodString + "("+ arg1String + ", "+sub);}		// If incomplete quote
    }

    // Must be  or MyObj, or MyObj[23]_1
    else if (! (Character.isLetter(ch) || ch == '<') )
      return(objString + "." + methodString + "("+ arg1String + ", "+ arg2String + ", ");
    else {
      Object arg2 = complete(sub, objectTable);

      if (arg2 instanceof String) {
	arg2String = (String) arg2;
	if (arg2Index+1 == len) return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String);
	if ((comma2Index+1 == len) || (comma2Index+2 == len))
	  return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", "); // ", " required
	if (closeIndex == arg2Index+1)
	  return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ")"); // ", " required
      }
      else {
	if (arg2 instanceof ObjectCompletionPair) {
	  arg2String = ((ObjectCompletionPair) arg2).mutual;
	}
	else {
	  Shadow ss = (Shadow) Shadow.getAlternate(arg2);
	  if (ss == null) return(objString + "." + methodString + "("+ arg1String + ", ");
	  arg2String = ss.tostring;
	}
	if ((comma2Index<0) && (closeIndex<0))
	  return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String);
	if ((comma2Index+1 == len) || (comma2Index+2 == len))
	  return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", "); // ", " required
	if (closeIndex == arg2Index+1)
	  return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ")"); // ", " required
      }

    }

    if (closeIndex == arg2Index+1)
      return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ")"); // ", " required
    if (comma2Index<0) return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String);
    if ((comma2Index+1 == len) || (comma2Index+2 == len))
      return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", "); // ", " required
    if (s.charAt(comma2Index+1) != ' ') return(objString + "." + methodString + "(" + arg1String + ", "); // ", " required







    // THIRD ARG
    
    int arg3Index;
    int comma3Index= s.indexOf(',', comma2Index+1);


    if (comma3Index < 0) {
      if (closeIndex > 0)
	arg3Index = closeIndex-1;
      else
	arg3Index = len-1;
    }
    else
      arg3Index = comma3Index-1;

    sub = s.substring(comma2Index+2, arg3Index+1);
    String arg3String = sub;					// if number, boolean, or string: don't complete

    if (sub.length() == 0) return(objString + "." + methodString + "("+ arg1String + ", "+ arg2String + ", ");
    ch = sub.charAt(0);
    if (Character.isDigit(ch)) {
      try {Integer.parseInt(sub);}				// Just verify it's an int
      catch (NumberFormatException e) {return(objString + "." + methodString + "("+ arg1String + ", "+ arg2String + ", "+ch);}
    }

    else if (ch == '"') {
      if (sub.charAt(sub.length()-1) != '"') {return(objString + "." + methodString + "("+ arg1String + ", "+ arg2String + ", "+sub);}
    }

    // Must be  or MyObj, or MyObj[33]_1
    else if (! (Character.isLetter(ch) || ch == '<') )
      return(objString + "." + methodString + "("+ arg1String + ", "+ arg2String + ", "+ arg3String + ", ");
    else {
      Object arg3 = complete(sub, objectTable);

      if (arg3 instanceof String) {
	arg3String = (String) arg3;
	if (arg3Index+1 == len) return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", "+ arg3String);
	if ((comma3Index+1 == len) || (comma3Index+2 == len))
	  return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", "+ arg3String + ", "); // ", " required
	if (closeIndex == arg3Index+1)
	  return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", "+ arg3String + ")"); // ", " required
      }
      else {
	if (arg3 instanceof ObjectCompletionPair) {
	  arg3String = ((ObjectCompletionPair) arg3).mutual;
	}
	else {
	  Shadow ss = (Shadow) Shadow.getAlternate(arg3);
	  if (ss == null) return(objString + "." + methodString + "("+ arg1String + ", "+ arg2String + ", ");
	  arg3String = ss.tostring;
	}
	if ((comma3Index<0) && (closeIndex<0))
	  return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", "+ arg3String);
	if ((comma3Index+1 == len) || (comma3Index+2 == len))
	  return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", "+ arg3String + ", "); // ", " required
	if (closeIndex == arg3Index+1)
	  return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", "+ arg3String + ")"); // ", " required
      }

    }

    if (closeIndex == arg3Index+1)
      return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", "+ arg3String + ")"); // ", " required
    if (comma3Index<0) return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", "+ arg3String);
    if ((comma3Index+1 == len) || (comma3Index+2 == len))
      return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", "+ arg3String + ", "); // ", " required
    if (s.charAt(comma3Index+1) != ' ') return(objString + "." + methodString + "(" + arg1String + ", "); // ", " required



    // FOURTH ARG
    
    int arg4Index;
    int comma4Index= s.indexOf(',', comma3Index+1);


    if (comma4Index < 0) {
      if (closeIndex > 0)
	arg4Index = closeIndex-1;
      else
	arg4Index = len-1;
    }
    else
      arg4Index = comma4Index-1;

    sub = s.substring(comma3Index+2, arg4Index+1);
    String arg4String = sub;					// if number, boolean, or string: don't complete

    if (sub.length() == 0) return(objString + "." + methodString + "("+ arg1String + ", "+ arg2String + ", " + arg3String + ", ");
    ch = sub.charAt(0);
    if (Character.isDigit(ch)) {
      try {Integer.parseInt(sub);}				// Just verify it's an int
      catch (NumberFormatException e) {return(objString + "." + methodString + "("+ arg1String + ", "+ arg2String + ", " + arg3String + ", "+ch);}
    }

    else if (ch == '"') {
      if (sub.charAt(sub.length()-1) != '"') {return(objString + "." + methodString + "("+ arg1String + ", "+ arg2String + ", " + arg3String + ", "+sub);}
    }

    // Must be  or MyObj, or MyObj[44]_1
    else if (! (Character.isLetter(ch) || ch == '<') )
      return(objString + "." + methodString + "("+ arg1String + ", "+ arg2String + ", " + arg3String + ", "+ arg4String + ", ");
    else {
      Object arg4 = complete(sub, objectTable);

      if (arg4 instanceof String) {
	arg4String = (String) arg4;
	if (arg4Index+1 == len) return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", " + arg3String + ", "+ arg4String);
	if ((comma4Index+1 == len) || (comma4Index+2 == len))
	  return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", " + arg3String + ", "+ arg4String + ", "); // ", " required
	if (closeIndex == arg4Index+1)
	  return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", " + arg3String + ", "+ arg4String + ")"); // ", " required
      }
      else {
	if (arg4 instanceof ObjectCompletionPair) {
	  arg4String = ((ObjectCompletionPair) arg4).mutual;
	}
	else {
	  Shadow ss = (Shadow) Shadow.getAlternate(arg4);
	  if (ss == null) return(objString + "." + methodString + "("+ arg1String + ", "+ arg2String + ", " + arg3String + ", ");
	  arg4String = ss.tostring;
	}
	if ((comma4Index<0) && (closeIndex<0))
	  return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", " + arg3String + ", "+ arg4String);
	if ((comma4Index+1 == len) || (comma4Index+2 == len))
	  return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", " + arg3String + ", "+ arg4String + ", "); // ", " required
	if (closeIndex == arg4Index+1)
	  return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", " + arg3String + ", "+ arg4String + ")"); // ", " required
      }

    }

    if (closeIndex == arg4Index+1)
      return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", " + arg3String + ", "+ arg4String + ")"); // ", " required
    if (comma4Index<0) return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", " + arg3String + ", "+ arg4String);
    if ((comma4Index+1 == len) || (comma4Index+2 == len))
      return(objString + "." + methodString + "(" + arg1String + ", "+ arg2String + ", " + arg3String + ", "+ arg4String + ", "); // ", " required


    // REST IGNORED
    String rest = s.substring(arg1Index+2);
    return("MAX FOUR ARGS ACCEPTED: " + objString + "." + methodString + "(" + arg1String + ", " + rest); // ", " required

  }




  public static ParsePair parse(String s) throws CompletionException {
    ParsePair pp;
    Class objClass;

    pp = parse1(s);

    MethodCompletionPair cp = pp.cPair;

    Object obj = pp.obj;
    if (obj instanceof Class)
      objClass = (Class) obj;
    else
      objClass = obj.getClass();
    
    String methodName = cp.mutual;

    int n = pp.objects.length;
    Class[] classes = new Class[n];
    for (int i = 0; i < n; i++) {
      Object o = pp.objects[i];
      if (o == null) o = ShadowNull.NULL;
      Class c = o.getClass();
      if (c == Integer.class) c = int.class;
      if (c == Boolean.class) c = boolean.class;
      if (c == ShadowNull.class) c = null;			// WILL THIS WORK?
      classes[i] = c;
    }

    Method method;


    //    try {method = objClass.getDeclaredMethod(methodName, classes);}
    try {method = Subtype.getDeclaredMethod(objClass, methodName, classes);}
    catch (NoSuchMethodException e) {
      //System.out.println("No such method: " + methodName);
      throw new CompletionException("No such method: " + methodName);
    }

    pp.method = method;			// pp may chose arbitrary methods here.

    verifyCreation(pp);
    return pp;
  }

  public static void verifyCreation(ParsePair pp) throws CompletionException {
    int len = pp.objects.length;

    Object obj = pp.obj;
    if (obj instanceof ObjectCompletionPair) obj = ((ObjectCompletionPair)obj).obj;
    verifyCreation(Shadow.get(obj));

    for (int i = 0; i < len; i++) {
      Object o = pp.objects[i];
      if (o instanceof ObjectCompletionPair) o = ((ObjectCompletionPair)o).obj;
      verifyCreation(Shadow.get(o));
    }
  }


  public static void verifyCreation(Shadow s) throws CompletionException {
    if (s.size() == 0) return;
    TimeStamp ts = s.getShadowVar(0).getTS(0);
    if (ts.laterThan(TimeStamp.currentTime())) throw new CompletionException(s, ts);
    return;
  }


  public static ParsePair parse1(String s)  throws CompletionException {
    String objString="", sub, methodString;
    MethodCompletionPair cp;
    int len = s.length();
    int dotIndex = s.indexOf('.');
    int objIndex = dotIndex-1;
    int openIndex = s.indexOf('(');
    int closeIndex = s.indexOf(')');

    if (openIndex < 0) throw new CompletionException("Parse failure: No '(' " + s);
    if (closeIndex != len-1) throw new CompletionException("Parse failure: ')' not final character " + s);
    if (objIndex < 0) throw new CompletionException("Parse failure: No '(' " + s);

    sub = s.substring(0, objIndex+1);
    Object obj = complete(sub, objectTable);

    if (obj instanceof String) throw new CompletionException("Parse failure: Incomplete Expression " + s);
    if (len == objIndex+1) throw new CompletionException("Parse failure: Incomplete Expression " + s);
    objString = sub;

    if (obj instanceof ObjectCompletionPair) obj = ((ObjectCompletionPair)obj).obj;
    Class c = obj.getClass();
    if (obj instanceof Class) c = (Class)obj;
    createMethodTable(c);
    Method m;

    sub = s.substring(objIndex+2, openIndex);
    Object methodObj = complete(sub, methodTable);
    if (methodObj == null) throw new CompletionException("Parse failure: Incomplete Expression " + s);
    if (methodObj instanceof String) throw new CompletionException("Parse failure: Incomplete Expression " + s);
    
    if (methodObj instanceof MethodCompletionPair) {
      cp = (MethodCompletionPair)methodObj;
      methodString = cp.mutual;
    }
    else if (methodObj instanceof Method) {
      m = (Method) methodObj;
      methodString = m.getName();
      cp = new MethodCompletionPair(methodString, m);
    }
    else
      throw new CompletionException("IMPOSSIBLE Parse failure: " + s);


    // NO ARGS

    if (closeIndex == openIndex+1) return new ParsePair(s, obj, cp);


    // FIRST ARG    

    char ch;
    Object arg1;
    String arg1String = sub;
    int arg1Index;
    int comma1Index= s.indexOf(',');

    if (comma1Index < 0) {
      arg1Index = closeIndex-1;
    }
    else
      arg1Index = comma1Index-1;

    sub = s.substring(openIndex+1, arg1Index+1);

    arg1String = sub;					// if number, boolean, or string: don't verify
    if (sub.length() < 1) throw new CompletionException("IMPOSSIBLE Parse failure: " + s);
    ch = sub.charAt(0);


    if ( Character.isDigit(ch) || (ch == '"') ) {
      arg1 = parsePrimitive(sub);
    }
    else if ( (Character.isLetter(ch) || ch == '<') ) {		    // Must be  or MyObj, or MyObj[23]_1
      arg1 = complete(sub, objectTable);
      if (arg1 instanceof String) throw new CompletionException("Parse failure: incomplete arg #1 '" + sub + "' in " + s);
      if (arg1 instanceof ObjectCompletionPair) 
	arg1 = ((ObjectCompletionPair)arg1).obj;
      else
	 throw new CompletionException("IMPOSSIBLE Parse failure: incomplete arg #1 '" + sub + "' in " + s);
      Shadow ss = (Shadow) Shadow.getAlternate(arg1);
      if (ss == null) throw new CompletionException("IMPOSSIBLE Parse failure: incomplete arg #1 '" + sub + "' in " + s);
      arg1String = ss.tostring;
    }
    else 
      throw new CompletionException("Parse failure: incorrect arg #1 '" + sub + "' in " + s);

    if (closeIndex == arg1Index+1) return new ParsePair(s, obj, cp, arg1);
    if (comma1Index<0) throw new CompletionException("Parse failure: missing ','"+s);


    // SECOND ARG    

    Object arg2;
    String arg2String = sub;
    int arg2Index;
    int comma2Index= s.indexOf(',', comma1Index+1);

    if (comma2Index < 0) {
      arg2Index = closeIndex-1;
    }
    else
      arg2Index = comma2Index-1;

    if (comma1Index+2 >= arg2Index+1) throw new CompletionException("IMPOSSIBLE Parse failure: " + s);
    sub = s.substring(comma1Index+2, arg2Index+1);

    arg2String = sub;					// if number, boolean, or string: don't verify
    if (sub.length() < 1) throw new CompletionException("IMPOSSIBLE Parse failure: " + s);
    ch = sub.charAt(0);


    if ( Character.isDigit(ch) || (ch == '"') ) {
      arg2 = parsePrimitive(sub);
    }
    else if ( (Character.isLetter(ch) || ch == '<') ) {		    // Must be  or MyObj, or MyObj[23]_1
      arg2 = complete(sub, objectTable);
      if (arg2 instanceof String) throw new CompletionException("Parse failure: incomplete arg #2 '" + sub + "' in " + s);
      if (arg2 instanceof ObjectCompletionPair) 
	arg2 = ((ObjectCompletionPair)arg2).obj;
      else
	 throw new CompletionException("IMPOSSIBLE Parse failure: incomplete arg #2 '" + sub + "' in " + s);
      Shadow ss = (Shadow) Shadow.getAlternate(arg2);
      if (ss == null) throw new CompletionException("IMPOSSIBLE Parse failure: incomplete arg #2 '" + sub + "' in " + s);
      arg2String = ss.tostring;
    }
    else 
      throw new CompletionException("Parse failure: incorrect arg #2 '" + sub + "' in " + s);

    if (closeIndex == arg2Index+1) return new ParsePair(s, obj, cp, arg1, arg2);
    if (comma2Index<0) throw new CompletionException("Parse failure: missing ','"+s);

    // THIRD ARG    

    Object arg3;
    String arg3String = sub;
    int arg3Index;
    int comma3Index= s.indexOf(',', comma2Index+1);

    if (comma3Index < 0) {
      arg3Index = closeIndex-1;
    }
    else
      arg3Index = comma3Index-1;

    if (comma2Index+2 >= arg3Index+1) throw new CompletionException("IMPOSSIBLE Parse failure: " + s);
    sub = s.substring(comma2Index+2, arg3Index+1);

    arg3String = sub;					// if number, boolean, or string: don't verify
    if (sub.length() < 1) throw new CompletionException("IMPOSSIBLE Parse failure: " + s);
    ch = sub.charAt(0);


    if ( Character.isDigit(ch) || (ch == '"') ) {
      arg3 = parsePrimitive(sub);
    }
    else if ( (Character.isLetter(ch) || ch == '<') ) {		    // Must be  or MyObj, or MyObj[33]_1
      arg3 = complete(sub, objectTable);
      if (arg3 instanceof String) throw new CompletionException("Parse failure: incomplete arg #3 '" + sub + "' in " + s);
      if (arg3 instanceof ObjectCompletionPair) 
	arg3 = ((ObjectCompletionPair)arg3).obj;
      else
	 throw new CompletionException("IMPOSSIBLE Parse failure: incomplete arg #3 '" + sub + "' in " + s);
      Shadow ss = (Shadow) Shadow.getAlternate(arg3);
      if (ss == null) throw new CompletionException("IMPOSSIBLE Parse failure: incomplete arg #3 '" + sub + "' in " + s);
      arg3String = ss.tostring;
    }
    else 
      throw new CompletionException("Parse failure: incorrect arg #3 '" + sub + "' in " + s);

    if (closeIndex == arg3Index+1) return new ParsePair(s, obj, cp, arg1, arg2, arg3);
    if (comma3Index<0) throw new CompletionException("Parse failure: missing ','"+s);


    // FOURTH ARG     

    Object arg4;
    String arg4String = sub;
    int arg4Index;
    int comma4Index= s.indexOf(',', comma3Index+1);

    if (comma4Index < 0) {
      arg4Index = closeIndex-1;
    }
    else
      arg4Index = comma4Index-1;
    if (comma3Index+2 >= arg4Index+1) throw new CompletionException("IMPOSSIBLE Parse failure: " + s);
    sub = s.substring(comma3Index+2, arg4Index+1);

    arg4String = sub;					// if number, boolean, or string: don't verify
    if (sub.length() < 1) throw new CompletionException("IMPOSSIBLE Parse failure: " + s);
    ch = sub.charAt(0);


    if ( Character.isDigit(ch) || (ch == '"') ) {
      arg4 = parsePrimitive(sub);
    }
    else if ( (Character.isLetter(ch) || ch == '<') ) {		    // Must be  or MyObj, or MyObj[44]_1
      arg4 = complete(sub, objectTable);
      if (arg4 instanceof String) throw new CompletionException("Parse failure: incomplete arg #4 '" + sub + "' in " + s);
      if (arg4 instanceof ObjectCompletionPair) 
	arg4 = ((ObjectCompletionPair)arg4).obj;
      else
	 throw new CompletionException("IMPOSSIBLE Parse failure: incomplete arg #4 '" + sub + "' in " + s);
      Shadow ss = (Shadow) Shadow.getAlternate(arg4);
      if (ss == null) throw new CompletionException("IMPOSSIBLE Parse failure: incomplete arg #4 '" + sub + "' in " + s);
      arg4String = ss.tostring;
    }
    else 
      throw new CompletionException("Parse failure: incorrect arg #4 '" + sub + "' in " + s);

    if (closeIndex == arg4Index+1) return new ParsePair(s, obj, cp, arg1, arg2, arg3, arg4);
    if (comma4Index<0) throw new CompletionException("Parse failure: missing ','"+s);
  
    throw new CompletionException("Parse failure: Too many arguments " + s);
  }




  public static Object parsePrimitive(String s) throws CompletionException {
    if (s.length() == 0) throw new CompletionException("Parse failure: not a primitive or String " + s);
    char ch = s.charAt(0);

    if (Character.isDigit(ch)) {
      try {
	Integer i = new Integer(Integer.parseInt(s));
	return(i);
      }				// Just verify it's an int
      catch (NumberFormatException e) {throw new CompletionException("Parse failure: bad int " + s);}
    }

    if (ch == '"') {
      if (s.charAt(s.length()-1) == '"')
	return(s.substring(1, s.length()-1));
      else
	throw new CompletionException("Parse failure: bad String " + s);
    }
    throw new CompletionException("IMPOSSIBLE Parse failure " + s);
  }



  public static void createMethodTable(Class c) {
    Method[] methods = c.getMethods();
    methodTable = new HashMap();
    int len = methods.length;

    for (int i = 0; i < len; i++) {			//System.out.println(methods[i]);
      String name = methods[i].getName();
      mapCharsMethod(name, methods[i], methodTable);
    }
  }

    


  public static void main(String[] args) {
    /*
      Shadow.put(new Thing(), new Shadow("Thing"));		// 0
      Shadow.put(new Thing(), new Shadow("Thing"));		// 1
      Shadow.put(new Thing(), new Shadow("Thing"));		// 2
      Shadow.put(new Thing(), new Shadow("Thing"));		// 3
      Shadow.put(new SubThing(), new Shadow("SubThing"));	// 4
      Shadow.put(new SubThing(), new Shadow("SubThing"));	// 5
      Shadow.put(new MyThing(), new Shadow("MyThing"));		// 6
      Shadow.put(new MyThing(), new Shadow("MyThing"));		// 7
      Shadow.put(new MyThing(), new Shadow("MyThing"));		// 8

      Shadow.put(new Boolean(false), new Shadow("false"));
      Shadow.put(new Boolean(true), new Shadow("true"));
      */
    //System.out.println(Shadow.table);

    //createCompletionTable(Shadow.table);
    
    //System.out.println(objectTable);


    System.out.println("Completing " + "<" + " -> " + complete("<", objectTable));
    System.out.println("Completing " + " " + complete(" " + complete(" " + complete(" " + complete(" " + complete(" " + complete(" " + complete(" " + complete(" " + complete("t", objectTable));
    System.out.println("Completing " + "tr" + " -> " + complete("tr", objectTable));
    System.out.println("Completing " + "falx" + " -> " + complete("falx", objectTable));

    System.out.println("----------------------------------------------------------------");

    System.out.println("Completing " + " " + completeCall("." + " -> " + completeCall("."));
    System.out.println("Completing " + ".to" + " -> " + completeCall(".to"));
    System.out.println("Completing " + ".doo" + " -> " + completeCall(".doo"));
    System.out.println("Completing " + ".doo(" + " -> " + completeCall(".doo("));
    System.out.println("Completing " + ".doo()" + " -> " + completeCall(".doo()"));
    System.out.println("Completing " + ".doo(\"Test\")" + " -> " + completeCall(".doo(\"Test\")"));
    System.out.println("Completing " + ".d" + " -> " + completeCall(".d"));
    System.out.println("Completing " + ".di" + " -> " + completeCall(".di"));
    System.out.println("Completing " + ".doon" + " -> " + completeCall(".doon"));


    System.out.println("Completing " + ".doo( " + completeCall(".doo(.did(12," + " -> " + completeCall(".did(12,"));
    System.out.println("Completing " + ".did(12" + " -> " + completeCall(".did(12"));
    System.out.println("Completing " + ".did(12)" + " -> " + completeCall(".did(12)"));
    System.out.println("Completing " + ".doo(, 12" + " -> " + completeCall(".doo(, 12"));
    System.out.println("Completing " + ".doo(, 12)" + " -> " + completeCall(".doo(, 12)"));
    System.out.println("Completing " + ".doo(,  " + completeCall(".doo(, .doo(,  " + completeCall(".doo(, .doo(, )" + " -> " + completeCall(".doo(, )"));


    System.out.println("Completing " + ".doo()" + " -> " + completeCall(".doo()"));

    try {

      System.out.println("Parsing " + ".doo()" + " -> " + parse(".doo()"));

      System.out.println("Parsing " + ".doo()" + " -> " + parse(".doo()"));
      System.out.println("Parsing " + ".doo(12)" + " -> " + parse(".doo(12)"));
      System.out.println("Parsing " + ".doo(, 12)" + " -> " + parse(".doo(, 12)"));
      System.out.println("Parsing " + ".doo()" + " -> " + parse(".doo()"));
      System.out.println("Parsing " + ".doo(12, )" + " -> " + parse(".doo(12, )"));
      System.out.println("Parsing " + ".doo(, )" + " -> " + parse(".doo(, )"));

      //    System.out.println(methodTable);
    }
    catch (CompletionException ce) {System.out.println(ce);}
    

  }
}


class Thing {
  public static Object doo() {return "WORKED";}
  public static Object doo(Thing t) {return "WORKED";}
  public static Object doo(Thing t, int i) {return "WORKED";}
  public static Object doo(Thing t, MyThing mt) {return "WORKED";}
  public static Object doo(int i) {return "WORKED";}
  public static Object doo(Thing t, int i, boolean b) {return "WORKED";}
  public static Object doo(Thing t, int i, boolean b, int j) {return "WORKED";}
  public  Object did() {return "WORKED";}
  public  Object doone() {return "WORKED";}
}

class SubThing extends Thing {}

class MyThing {
}


class MethodCompletionPair {
  public String mutual;
  public Vector methods = new MyVector();

  public MethodCompletionPair(String s, Method m) {
    mutual=s;
    methods.add(m);
  }

  public Method firstMethod() {
    if (methods.size() == 0) return null;		// Trouble!
    return (Method)methods.elementAt(0);
  }

  public void addMethod(Method m) {
    methods.add(m);
  }
}



class ObjectCompletionPair {
  public String mutual;
  public Object obj;

  public ObjectCompletionPair(String s, Object o) {
    mutual=s;
    obj = o;
  }

}






© 2015 - 2025 Weber Informatics LLC | Privacy Policy