/* * xtc - The eXTensible Compiler * Copyright (C) 2004 Robert Grimm * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package xtc.util; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; /** * Implementation of a pair. Pairs are used to construct immutable * singly-linked lists, not unlike cons cells in Scheme (with the * differences that pairs are immutable and that the second pointer * always references another pair). * * @author Robert Grimm * @version $Revision: 1.1 $ */ public class Pair { /** * The pair representing the empty list. This object serves as a * sentinel to avoid special-casing <code>null</code>. */ public static final Pair EMPTY = new Pair(); /** The value. */ private final Object value; /** The next pair. */ private final Pair next; /** Create a new pair. */ private Pair() { value = null; next = null; } /** * Create a new pair. The newly created pair represents a singleton * list. * * @param value The value. */ public Pair(Object value) { this(value, EMPTY); } /** * Create a new pair. * * @param value The value. * @param next The next pair. * @throws NullPointerException * Signals that <code>next</code> is <code>null</code>. */ public Pair(Object value, Pair next) { if (null == next) { throw new NullPointerException(); } this.value = value; this.next = next; } /** * Determine whether the list starting at this pair is empty. * * @return <code>true</code> if the list is empty. */ public boolean isEmpty() { return (this == EMPTY); } /** * Get this pair's value. * * @return This pair's value. * @throws IllegalStateException * Signals that this pair represents the empty list. */ public Object value() { if (this == EMPTY) { throw new IllegalStateException(); } return value; } /** * Get the next pair. * * @return The next pair. * @throws IllegalStateException * Signals that this pair represents the empty list. */ public Pair next() { if (this == EMPTY) { throw new IllegalStateException(); } return next; } /** * Get the size of the list starting at this pair. * * @return The size. */ public int size() { Pair pair = this; int size = 0; while (pair != EMPTY) { size++; pair = pair.next; } return size; } /** * Get an iterator over the values of the list starting at this * pair. * * @return The iterator. */ public Iterator iterator() { return new Iterator() { private Pair pair = Pair.this; public boolean hasNext() { return (EMPTY != pair); } public Object next() { if (EMPTY == pair) { throw new NoSuchElementException(); } else { Object v = pair.value; pair = pair.next; return v; } } public void remove() { throw new UnsupportedOperationException(); } }; } /** * Get a Java Collections list with the values of the list starting * at this pair. * * @return The Java Collections list. */ public List list() { ArrayList list = new ArrayList(size()); Pair pair = this; while (EMPTY != pair) { list.add(pair.value); pair = pair.next; } return list; } }