// file: ClosedStringList.java // author: Robert Keller // purpose: closed list of Strings // This class can be used as a closed-list stack // or as open list (but be careful). // In the stack operations, push and // The empty list is called nil. // To create an empty modifiable stack, use the constructor ClosedStringList // // cons(F, R) creates a list from a String F and a list R // R.cons(F) creates a list from a String F and a list R // L.first() returns the first of a non-empty list L // L. rest() returns all but the first of a non-empty list // L.isEmpty() tells whether L is empty. // L.toString() creates a String representation of L // L.push(F) modifies L in-place to have new top element F // L.pop() returns the top element of L and removes it import java.io.PrintStream; class ClosedStringList { StringCell handle; // pointer to the first cell in the list ClosedStringList() // create new empty modifiable list { handle = null; } String first() // return the first element of the list { return handle.first; } ClosedStringList rest() // return the rest of the list { return new ClosedStringList(handle.rest); } boolean isEmpty() // check for emptiness { return handle == null; } // create new list given first and rest static ClosedStringList cons(String first, ClosedStringList rest) { return new ClosedStringList(new StringCell(first, rest.handle)); } // create new list with first and this as rest ClosedStringList cons(String first) { return cons(first, this); } // create list with StringCell as its first cell ClosedStringList(StringCell handle) { this.handle = handle; } // note that nil != null final static ClosedStringList nil = new ClosedStringList(null); // mutating methods for Stack // add a new first element to list, destructively changing this void push(String s) { handle = new StringCell(s, handle); } // remove first element and return it, destructively changing this String pop() { String top = first(); handle = rest().handle; return top; } // make a String representation of the list public String toString() { StringBuffer b = new StringBuffer(); ClosedStringList L = this; b.append("("); if( !L.isEmpty() ) { b.append(L.first()); L = L.rest(); while( !L.isEmpty() ) { b.append(" "); b.append(L.first()); L = L.rest(); } } b.append(")"); return b.toString(); } // Test program public static void main(String arg[]) { // The first tests are of the open-list variety, for contrast // These are followed by tests of the stack aspect // Create initial list System.out.println(); System.out.println("Treating L as open list"); ClosedStringList L = nil.cons("delta").cons("gamma").cons("beta"); System.out.println("L = " + L); System.out.println("L.first() = " + L.first()); System.out.println("L.rest(L) = " + L.rest()); System.out.println("L.rest().first() = " + L.rest().first()); System.out.println("L.rest().rest() = " + L.rest().rest()); System.out.println("nil = " + nil); System.out.println("L = " + L); // The next tests exploit the closed-list aspect, treating S as a stack System.out.println(); System.out.println("Treating S as a stack"); ClosedStringList S = new ClosedStringList(); System.out.println("S = " + S); S.push("alpha"); System.out.println("S = " + S); S.push("beta"); System.out.println("S = " + S); S.push("gamma"); System.out.println("S = " + S); S.push("delta"); System.out.println("S = " + S); while( !S.isEmpty() ) { System.out.println("S = " + S); System.out.println("S.pop() = " + S.pop()); } System.out.println("S = " + S); } } // StringCell is the building block for ClosedStringList class StringCell { String first; StringCell rest; StringCell(String first, StringCell rest) { this.first = first; this.rest = rest; } } /* output of ClosedStringList.main Treating L as open list L = (beta gamma delta) L.first() = beta L.rest(L) = (gamma delta) L.rest().first() = gamma L.rest().rest() = (delta) nil = () L = (beta gamma delta) Treating S as a stack S = () S = (alpha) S = (beta alpha) S = (gamma beta alpha) S = (delta gamma beta alpha) S = (delta gamma beta alpha) S.pop() = delta S = (gamma beta alpha) S.pop() = gamma S = (beta alpha) S.pop() = beta S = (alpha) S.pop() = alpha S = () */