CSC448: Parsing: Lists [5/26] Previous pageContentsNext page

file:List.java [source] [doc-public] [doc-private]
00001: package clogs.util;
00002: 
00003: import java.util.HashSet;
00004: import java.util.Iterator;
00005: import java.util.NoSuchElementException;
00006: 
00007: 
00008: public abstract class List<A> implements Iterable<A>
00009: {
00010:   public static <A> List<A> nil ()
00011:   {
00012:     return new ListNil<A> ();
00013:   }
00014: 
00015: 
00016:   public static <A> List<A> singleton (A head)
00017:   {
00018:     return List.<A>nil ().cons (head);
00019:   }
00020: 
00021: 
00022:   public List<A> cons (A head)
00023:   {
00024:     return new ListCons<A> (head, this);
00025:   }
00026: 
00027: 
00028:   public List<A> snoc (A last)
00029:   {
00030:     return this.concat (singleton (last));
00031:   }
00032: 
00033: 
00034:   public A get (int index) 
00035:   {
00036:     int i = index;
00037:     List<A> l = this;
00038:     while ((i > 0) && (!l.isNil ())) {
00039:       i--;
00040:       l = l.tail ();
00041:     }
00042: 
00043:     if ((i != 0) || l.isNil ()) {
00044:       throw new IndexOutOfBoundsException 
00045:         ("Attempt to access element " + i + " in list of length " + size () + "\n" + this);
00046:     }
00047: 
00048:     return l.head ();
00049:   }
00050: 
00051: 
00052:   public abstract boolean isNil ();
00053:   public abstract int size ();
00054: 
00055:   public abstract A head () throws EmptyListException;
00056:   public abstract List<A> tail () throws EmptyListException;
00057: 
00058:   public abstract List<A> concat (List<A> l);
00059:   public abstract List<A> reverse ();
00060:   abstract List<A> reverseAux (List<A> end);
00061: 
00062: 
00063:   public String toString ()
00064:   {
00065:     StringBuffer sb = new StringBuffer ();
00066: 
00067:     if (isNil ()) {
00068:       return ("[]");
00069:     }
00070: 
00071:     sb.append ("[ ");
00072:     List l = this;
00073:     boolean first = true;
00074:     while (!l.isNil ()) {
00075:       if (first) {
00076:         first = false;
00077:       } else {
00078:         sb.append (", ");
00079:       }
00080:       sb.append (l.head ());
00081:       l = l.tail ();
00082:     }
00083:     sb.append (" ]");
00084:     
00085:     return sb.toString ();
00086:   }
00087:   
00088:   
00089:   // Returns a duplicate in the list (upto .equals ()) if there is one, otherwise returns null.
00090:   public A findDuplicate ()
00091:   {
00092:     HashSet<A> set = new HashSet<A> ();
00093:     List<A> list = this;
00094:     while (!list.isNil ()) {
00095:       A o = list.head ();
00096:       if (!set.contains (o)) {
00097:         set.add (o);
00098:       } else {
00099:         return o;
00100:       }
00101:       list = list.tail ();
00102:     }
00103:     return null;
00104:   }
00105:   
00106:   
00107:   class ListIteratorImpl<A> implements Iterator<A> 
00108:   {
00109:     private List<A> contents;
00110:     
00111:     ListIteratorImpl (List<A> contents)
00112:     {
00113:       this.contents = contents;
00114:     }
00115:     
00116:     public boolean hasNext ()
00117:     {
00118:       return !contents.isNil ();
00119:     }
00120:     
00121:     public A next ()
00122:     {
00123:       if (contents.isNil ()) {
00124:         throw new NoSuchElementException ();
00125:       } else {
00126:         A result = contents.head ();
00127:         contents = contents.tail ();
00128:         return result;
00129:       }
00130:     }
00131:     
00132:     public void remove ()
00133:     {
00134:       throw new UnsupportedOperationException ();
00135:     }
00136:   }
00137:   
00138:   
00139:   public Iterator<A> iterator ()
00140:   {
00141:     return new ListIteratorImpl<A> (this);
00142:   }
00143:   
00144:   
00145:   // Applies fun.f to every object in the list to create a new list of the results.
00146:   // If fun.f returns null, the result is discarded (a combined map/filter).
00147:   public <B> List<B> map (Function<A,B> fun)
00148:   {
00149:     if (isNil ()) {
00150:       return nil ();
00151:     } else {
00152:       B newHead = fun.f (head ());
00153:       List<B> newTail = tail ().map (fun);
00154:       if (newHead == null) {
00155:         return newTail;
00156:       } else {
00157:         return newTail.cons (newHead);
00158:       }
00159:     }
00160:   }
00161: 
00162: 
00163:   public boolean contains (A o)
00164:   {
00165:     List<A> list = this;
00166:     while (!list.isNil ()) {
00167:       if (o.equals (list.head ())) {
00168:         return true;
00169:       }
00170:       list = list.tail ();
00171:     }
00172:     return false;
00173:   }
00174: }
00175: 
00176: 
00177: 

file:ListNil.java [source] [doc-public] [doc-private]
00001: package clogs.util;
00002: 
00003: 
00004: class ListNil<A> extends List<A>
00005: {
00006:   ListNil ()
00007:   {
00008:   }
00009: 
00010: 
00011:   public boolean isNil ()
00012:   {
00013:     return true;
00014:   }
00015: 
00016: 
00017:   public int size ()
00018:   {
00019:     return 0;
00020:   }
00021: 
00022: 
00023:   public A head () 
00024:     throws EmptyListException
00025:   {
00026:     throw new EmptyListException ();
00027:   }
00028: 
00029: 
00030:   public List<A> tail () 
00031:     throws EmptyListException
00032:   {
00033:     throw new EmptyListException ();
00034:   }
00035: 
00036: 
00037:   public List<A> concat (List<A> l)
00038:   {
00039:     return l;
00040:   }
00041: 
00042: 
00043:   public List<A> reverse ()
00044:   {
00045:     return this;
00046:   }
00047: 
00048: 
00049:   public List<A> reverseAux (List<A> end)
00050:   {
00051:     return end;
00052:   }
00053: 
00054: 
00055:   public boolean equals (Object o)
00056:   {
00057:     return (o instanceof ListNil);
00058:   }
00059: }
00060: 

file:ListCons.java [source] [doc-public] [doc-private]
00001: package clogs.util;
00002: 
00003: 
00004: class ListCons<A> extends List<A>
00005: {
00006:   final A head;
00007:   final List<A> tail;
00008: 
00009: 
00010:   ListCons (A head, List<A> tail)
00011:   {
00012:     NonNull.check (head, tail);
00013:     this.head = head;
00014:     this.tail = tail;
00015:   }
00016: 
00017: 
00018:   public boolean isNil ()
00019:   {
00020:     return false;
00021:   }
00022: 
00023: 
00024:   public int size ()
00025:   {
00026:     return 1 + tail.size ();
00027:   }
00028: 
00029: 
00030:   public A head () 
00031:     throws EmptyListException
00032:   {
00033:     return head;
00034:   }
00035: 
00036: 
00037:   public List<A> tail () 
00038:     throws EmptyListException
00039:   {
00040:     return tail;
00041:   }
00042: 
00043: 
00044:   public List<A> concat (List<A> l)
00045:   {
00046:     return tail.concat (l).cons (head);
00047:   }
00048: 
00049: 
00050:   public List<A> reverse ()
00051:   {
00052:     return reverseAux (List.<A>nil ());
00053:   }
00054: 
00055: 
00056:   public List<A> reverseAux (List<A> end)
00057:   {
00058:     return tail.reverseAux (end.cons (head));
00059:   }
00060: 
00061: 
00062:   @SuppressWarnings("unchecked")
00063:   public boolean equals (Object o)
00064:   {
00065:     if (o instanceof ListCons) {
00066:       ListCons<A> lCons = (ListCons) o;
00067:       return head.equals (lCons.head) && tail.equals (lCons.tail);
00068:     } else {
00069:       return false;
00070:     }
00071:   }
00072: }
00073: 

file:EmptyListException.java [source] [doc-public] [doc-private]
00001: package clogs.util;
00002: 
00003: 
00004: public class EmptyListException extends RuntimeException
00005: {
00006:   public EmptyListException ()
00007:   {
00008:     super ();
00009:   }
00010: 
00011: 
00012:   public EmptyListException (String s)
00013:   {
00014:     super (s);
00015:   }
00016: }
00017: 

Previous pageContentsNext page