package LBJ2.IR;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.ListIterator;
/**
* Currently, this is just a wrapper class for <code>LinkedList</code>. The
* code that uses it looks a little cleaner when casts are all taken care of
* automatically.
*
* @author Nick Rizzolo
**/
abstract public class List extends ASTNode
{
/** (¬ø) The list being wrapped. */
protected LinkedList list;
/**
* The characters appearing in between elements of the list in its string
* representation.
**/
protected String separator;
/**
* Full constructor.
*
* @param line The line on which the source code represented by this
* node is found.
* @param byteOffset The byte offset from the beginning of the source file
* at which the source code represented by this node is
* found.
* @param s The list's element separator.
**/
public List(int line, int byteOffset, String s) {
super(line, byteOffset);
list = new LinkedList();
separator = s;
}
/**
* Returns the size of the list.
*
* @return The number of elements currently in the list.
**/
public int size() { return list.size(); }
/**
* Returns the separating characters.
*
* @return The value of <code>separator</code>.
**/
public String getSeparator() { return separator; }
/** Sorts the list according to their natural ordering. */
public void sort() { Collections.sort(list); }
/**
* Sorts the list according to the order induced by the specified
* comparator.
*
* @param c A comparator that determines the relative ordering of two
* elements in the list.
**/
public void sort(Comparator c) { Collections.sort(list, c); }
/**
* Writes a string representation of this <code>ASTNode</code> to the
* specified buffer. The representation written is parsable by the LBJ2
* compiler, but not very readable.
*
* @param buffer The buffer to write to.
**/
protected void writeBuffer(StringBuffer buffer, String separate) {
ASTNodeIterator I = iterator();
if (!I.hasNext()) return;
I.next().write(buffer);
while (I.hasNext()) {
buffer.append(separate);
I.next().write(buffer);
}
}
/**
* Writes a string representation of this <code>ASTNode</code> to the
* specified buffer. The representation written is parsable by the LBJ2
* compiler, but not very readable.
*
* @param buffer The buffer to write to.
**/
public void write(StringBuffer buffer) { writeBuffer(buffer, separator); }
/**
* Determines whether this list is equivalent to another object.
*
* @param o The other object.
* @return <code>true</code> iff this list is equivalent to <code>o</code>.
**/
public boolean equals(Object o) {
if (o == null || !o.getClass().equals(getClass())) return false;
List list = (List) o;
if (size() != list.size()) return false;
NodeListIterator I1 = new NodeListIterator();
NodeListIterator I2 = list.new NodeListIterator();
while (I1.hasNext())
if (!I1.next().equals(I2.next())) return false;
return true;
}
/** A hash code based on the hash codes of the elements of the list. */
public int hashCode() {
int result = 53;
for (NodeListIterator I = new NodeListIterator(); I.hasNext(); ) {
Object element = I.next();
result = 31 * result + (element == null ? 7 : element.hashCode());
}
return result;
}
/**
* Used to iterate though the children of a list of AST nodes. The entire
* interface of <code>java.util.ListIterator</code> is exposed through this
* class.
*
* @author Nick Rizzolo
**/
public class NodeListIterator extends ASTNodeIterator
{
/** An iterator into <code>list</code>. */
protected ListIterator I;
/** Initializes <code>I</code>. */
public NodeListIterator() { I = list.listIterator(); }
/**
* Inserts the specified node into the list. The element is inserted
* immediately before the next element that would be returned by
* <code>next()</code>, if any, and after the next element that would be
* returned by <code>previous()</code>, if any. (If the list contains no
* elements, the new element becomes the sole element on the list.) The
* new element is inserted before the implicit cursor: a subsequent call
* to <code>next()</code> would be unaffected, and a subsequent call to
* <code>previous()</code> would return the new element. (This call
* increases by one the value that would be returned by a call to
* <code>nextIndex</code> or <code>previousIndex</code>.)
*
* @param n The node to add.
**/
public void add(ASTNode n) { I.add(n); }
/**
* Returns <code>true</code> if this list iterator has more elements when
* traversing the list in the forward direction.
*
* @return <code>true</code> if this list iterator has more elements when
* traversing the list in the forward direction.
**/
public boolean hasNext() { return I.hasNext(); }
/**
* Returns <code>true</code> if this list iterator has more elements when
* traversing the list in the reverse direction.
*
* @return <code>true</code> if this list iterator has more elements when
* traversing the list in the reverse direction.
**/
public boolean hasPrevious() { return I.hasPrevious(); }
/**
* Returns the next AST node in the list. This method may be called
* repeatedly to iterate through the list, or intermixed with calls to
* <code>previous()</code> to go back and forth. (Note that alternating
* calls to <code>next()</code> and <code>previous()</code> will return
* the same element repeatedly.)
*
* @return The next AST node in the list.
**/
public ASTNode next() { return (ASTNode) I.next(); }
/**
* Returns the index of the node that would be returned by a subsequent
* call to <code>next()</code>. (Returns list size if the list iterator
* is at the end of the list.)
*
* @return The index of the element that would be returned by a
* subsequent call to <code>next()</code>, or list size if list
* iterator is at end of list.
**/
public int nextIndex() { return I.nextIndex(); }
/**
* Returns the previous element in the list. This method may be called
* repeatedly to iterate through the list backwards, or intermixed with
* calls to next to go back and forth. (Note that alternating calls to
* next and previous will return the same element repeatedly.)
*
* @return The previous AST node in the list.
**/
public ASTNode previous() { return (ASTNode) I.previous(); }
/**
* Returns the index of the node that would be returned by a subsequent
* call to <code>previous()</code>. (Returns -1 if the list iterator is
* at the beginning of the list.)
*
* @return The index of the element that would be returned by a
* subsequent call to <code>previous()</code>, or -1 if list
* iterator is at the beginning of the list.
**/
public int previousIndex() { return I.previousIndex(); }
/**
* Removes from the list the last element that was returned by
* <code>next()</code> or <code>previous</code>. This call can only be
* made once per call to <code>next()</code> or <code>previous</code>.
* It can be made only if <code>add(ASTNode)</code> has not been called
* after the last call to <code>next()</code> or <code>previous</code>.
**/
public void remove() { I.remove(); }
/** Restarts the iterator. */
public void reset() { I = list.listIterator(); }
/**
* Replaces the last element returned by <code>next()</code> or
* <code>previous()</code> with the specified element. This call can be
* made only if neither <code>remove()</code> nor
* <code>add(ASTNode)</code> have been called after the last call to
* <code>next()</code> or <code>previous()</code>.
*
* @param n The element with which to replace the last element returned
* by <code>next()</code> or <code>previous()</code>.
**/
public void set(ASTNode n) { I.set(n); }
}
}