001 package sexp; 002 003 import java.util.Iterator; 004 import java.util.NoSuchElementException; 005 006 /** 007 * SNonEmpty represents a list that starts with an element and is followed by a list 008 * of more elements. 009 */ 010 public class SNonEmpty implements SList { 011 private final SExp first; 012 private final SList rest; 013 014 private void checkRep() { 015 assert first != null; 016 assert rest != null; 017 } 018 019 public SNonEmpty(SExp first, SList rest) { 020 if (first == null || rest == null) throw new IllegalArgumentException("list can't contain null elements"); 021 this.first = first; 022 this.rest = rest; 023 checkRep(); 024 } 025 026 public boolean isEmpty() { 027 return false; 028 } 029 030 public SExp first() { 031 return first; 032 } 033 034 public SList rest() { 035 return rest; 036 } 037 038 public SExp get(int i) { 039 if (i == 0) return first; 040 else return rest.get(i-1); 041 } 042 043 public int size() { 044 return 1 + rest.size(); 045 } 046 047 public Iterator<SExp> iterator() { 048 final SList thisList = this; 049 return new Iterator<SExp>() { 050 SList p = thisList; 051 052 public boolean hasNext() { 053 return !p.isEmpty(); 054 } 055 056 public SExp next() { 057 if (!hasNext()) throw new NoSuchElementException(); 058 SExp e = p.first(); 059 p = p.rest(); 060 return e; 061 } 062 063 public void remove() { 064 throw new UnsupportedOperationException(); 065 } 066 }; 067 } 068 069 public <T> T accept(SExpVisitor<T> visitor) { 070 return visitor.visit(this); 071 } 072 073 @Override 074 public String toString() { 075 return "(" + first + " " + rest.toString().substring(1); 076 } 077 078 @Override 079 public int hashCode() { 080 final int prime = 31; 081 int result = 1; 082 result = prime * result + ((first == null) ? 0 : first.hashCode()); 083 result = prime * result + ((rest == null) ? 0 : rest.hashCode()); 084 return result; 085 } 086 087 @Override 088 public boolean equals(Object obj) { 089 if (this == obj) 090 return true; 091 if (obj == null) 092 return false; 093 if (getClass() != obj.getClass()) 094 return false; 095 final SNonEmpty other = (SNonEmpty) obj; 096 return first.equals(other.first) && rest.equals(other.rest); 097 } 098 099 }