/* Copyright 2004-2006 David N. Welton

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

package org.hecl;

import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;

/**
 * The ListThing class implements lists, storing them internally
 * as a Vector.
 * 
 * @author David N. Welton 
 * @version 1.0
 */
public class ListThing implements RealThing {
    protected Vector val = null;

    private int depth = 0;

    /**
     * Creates a new, empty ListThing instance.
     *  
     */
    public ListThing() {
        val = new Vector();
    }

    /**
     * Creates a new ListThing instance from a vector.
     * 
     * @param v a Vector value
     */
    public ListThing(Vector v) {
        val = v;
    }

    /**
     * Attempts to create a new ListThing instance from a string.
     * May fail if the string can't be parsed into a list.
     * 
     * @param s a String value
     * @exception HeclException if an error occurs
     */
    public ListThing(String s) throws HeclException {
        ParseList parseList = new ParseList(s);
        /* FIXME - this probably doesn't handle newlines. */
        val = parseList.parse();
        if (val == null) {
            val = new Vector();
        }
    }

    /**
     * create allocates and returns a new ListThing typed Thing.
     *
     * @param v a Vector value.  Note that the Vector
     * must contain Things, rather than, say, int's or Strings or
     * something else!
     * @return a Thing value
     */
    public static Thing create(Vector v) {
        return new Thing(new ListThing(v));
    }

    @Override
    public String thingclass() {
	return "list";
    }

    /**
     * setListFromAny attempts to transform the given Thing into
     * a ListThing typed Thing.
     *
     * @param thing a Thing value
     * @exception HeclException if an error occurs
     */
    private static void setListFromAny(Thing thing) throws HeclException {
        RealThing realthing = thing.getVal();

        if (realthing instanceof ListThing) {
            /* Nothing to be done. */
            return;
        }

        RealThing newthing = null;
        Vector newval = new Vector();
	if (realthing instanceof HashThing) {
            Hashtable h = HashThing.get(thing);

            for (Enumeration e = h.keys(); e.hasMoreElements();) {
                String key = (String) e.nextElement();
                newval.addElement(new Thing(key));
                newval.addElement(h.get(key));
            }
            newthing = new ListThing(newval);
        } else {
            newthing = new ListThing(realthing.getStringRep());
        }
	thing.setVal(newthing);
    }

    /**
     * get attempts to transform the given Thing into a List, and
     * return its Vector value.
     * 
     * @param thing a Thing value
     * @return a Vector value
     * @exception HeclException if an error occurs
     */
    public static Vector get(Thing thing) throws HeclException {
        setListFromAny(thing);
        ListThing getlist = (ListThing) thing.getVal();

	/* If the thing is slated for copying, it's elements should be
	 * as well. */
 	if (thing.copy) {
	    for (Enumeration e = getlist.val.elements(); e.hasMoreElements();) {
		Thing te = (Thing) e.nextElement();
		te.copy = true;
	    }
	}

        return getlist.val;
    }

    /**
     * getArray attempts to transform the given Thing
     * into a List, and return it as an array of Things.
     *
     * @param thing a Thing value
     * @return a Thing[] value
     * @exception HeclException if an error occurs
     */
    public static Thing[] getArray(Thing thing) throws HeclException {
	Vector v = ListThing.get(thing);
	Thing[] res = new Thing[v.size()];
	int i = 0;
	for (Enumeration e = v.elements(); e.hasMoreElements();) {
	    res[i] = (Thing)e.nextElement();
	    i ++;
	}
	return res;
    }

    /**
     * deepcopy copies a list and all of its elements.
     * 
     * @return a RealThing value
     * @throws HeclException
     */
    @Override
    public RealThing deepcopy() throws HeclException {
        Vector newv = new Vector();
        for (Enumeration e = val.elements(); e.hasMoreElements();) {
            newv.addElement(((Thing) e.nextElement()).deepcopy());
        }

        return new ListThing(newv);
    }

    /**
     * toListString transforms list elements into the
     * string form {foo bar} if the element contains a space.
     *
     * @param thing a Thing value
     * @return a String value
     */
    public static String toListString(Thing thing) {
        String elementstring = thing.toString();

        if (elementstring.indexOf(' ') >= 0
	    || elementstring.indexOf('\t') >= 0) {
	    StringBuffer resbuf = new StringBuffer();
            resbuf.append('{').append(elementstring).append('}');

	    // System.err.println("toListString: >"+elementstring+"< --> " + resbuf.toString());
	    return resbuf.toString();
        }
	return elementstring;
    }

    public static StringBuffer appendListItem(StringBuffer buf,Thing thing) {
        String elementstring = thing.toString();

        if (elementstring.indexOf(' ') >= 0
	    || elementstring.indexOf('\t') >= 0) {
	    buf.append('{').append(elementstring).append('}');
	} else {
	    buf.append(elementstring);
	}
	return buf;
    }
    
//#ifdef notdef
    static final int USE_BRACES = 1;
    static final int DONT_USE_BRACES = 2;
    static final int BRACES_UNMATCHED = 4;
    
    static int scanElement(Thing t) {
	String s = t.toString();
	int flags = 0;
	int n = s.length();
	char ch;
	
	if(n == 0 || (((ch = s.charAt(0)) == '{') || ch == '}'))
	    flags |= USE_BRACES;

	int nestinglevel = 0;
	for(int i=0; igetStringRep returns a string representation of a
     * ListThing.
     * 
     * @return a String value
     */
    @Override
    public String getStringRep() {
        int sz = val.size();
	if(sz == 0) {
	    return "";
	    //return "{}";
	}

/* 	if(depth > 1) {
	    //throw new HeclException("Can't print circular references");
	    return "CIRCULAR REF! BANG!";
	} else {
	    depth ++;
	}  */


	int i = 0;
//#ifdef notdef
	int[] flags = new int[sz];
	for(i=0; i 0)
		resbuf.append(' ');
	    //resbuf.append(toListString((Thing)val.elementAt(i)));
	    appendListItem(resbuf,(Thing)val.elementAt(i));
	}
        return resbuf.toString();
    }

    /**
     * The stringSplit method takes a string and splits
     * it according to another string,
     *
     * @param str a String value
     * @param splitstr a String value
     * @return a Thing value
     */
    public static Thing stringSplit(String str, String splitstr) {
	int idx = 0;
	int last = 0;
	Vector result = new Vector();
	if (splitstr == null) {
	    /* By default, we split on spaces. */
	    splitstr = " ";
	}

	int splitstringlen = splitstr.length();

	if (splitstringlen > 0) {
	    idx = str.indexOf(splitstr);
	    while (idx >= 0) {
		result.addElement(new Thing(str.substring(last, idx)));
		last = idx + splitstringlen;
		idx = str.indexOf(splitstr, last);
	    }
	    result.addElement(new Thing(str.substring(last, str.length())));
	} else {
	    /* This is a special case: when the splitstring is an
	     * empty string "". */
	    for(int i = 0; i < str.length(); i++) {
		char[] c = new char[1];
		c[0] = str.charAt(i);
		result.addElement(new Thing(new String(c)));
	    }
	}
	return ListThing.create(result);
    }


    /**
     * The buildCmdList method takes a Thing, treats it as a
     * list, and adds arguments to it from the args array.  The whole
     * thing is returned and is ready to be executed by interp.eval().
     * This is a convenience function utilized in various callbacks
     * throughout the code.
     *
     * @param cmd a Thing value
     * @param args an array of Thing values
     * @return a Thing value
     * @exception HeclException if an error occurs
     */
    public static Thing buildCmdList(Thing cmd, Thing[] args) throws HeclException {
	Vector v = ListThing.get(cmd.deepcopy());
	for(int i = 0; i < args.length; i++) {
	    v.addElement(args[i]);
	}
	return ListThing.create(v);
    }
}

 

Ads help maintain this website.