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    }