001    package fj.parser;
002    
003    import fj.F;
004    import fj.F2;
005    import static fj.Function.curry;
006    
007    import java.util.Iterator;
008    import java.util.NoSuchElementException;
009    
010    /**
011     * A parse result made up of a value (A) and the remainder of the parse input (I).
012     *
013     * @version %build.number%<br>
014     *          <ul>
015     *          <li>$LastChangedRevision: 122 $</li>
016     *          <li>$LastChangedDate: 2009-04-25 08:24:38 +1000 (Sat, 25 Apr 2009) $</li>
017     *          </ul>
018     */
019    public final class Result<I, A> implements Iterable<A> {
020      private final I i;
021      private final A a;
022    
023      private Result(final I i, final A a) {
024        this.i = i;
025        this.a = a;
026      }
027    
028      /**
029       * The remainder of the parse input.
030       *
031       * @return The remainder of the parse input.
032       */
033      public I rest() {
034        return i;
035      }
036    
037      /**
038       * The parsed value.
039       *
040       * @return The parsed value.
041       */
042      public A value() {
043        return a;
044      }
045    
046      /**
047       * Maps the given function across the remainder of the parse input.
048       *
049       * @param f The function to map with.
050       * @return A result with a different parse input.
051       */
052      public <J> Result<J, A> mapRest(final F<I, J> f) {
053        return result(f.f(i), a);
054      }
055    
056      /**
057       * First-class function mapping across the remainder of the parse input.
058       *
059       * @return A first-class function mapping across the remainder of the parse input.
060       */
061      public <J> F<F<I, J>, Result<J, A>> mapRest() {
062        return new F<F<I, J>, Result<J, A>>() {
063          public Result<J, A> f(final F<I, J> f) {
064            return mapRest(f);
065          }
066        };
067      }
068    
069      /**
070       * Maps the given function across the parse value.
071       *
072       * @param f The function to map with.
073       * @return A result with a different parse value.
074       */
075      public <B> Result<I, B> mapValue(final F<A, B> f) {
076        return result(i, f.f(a));
077      }
078    
079      /**
080       * First-class function mapping across the parse value.
081       *
082       * @return A first-class function mapping across the parse value.
083       */
084      public <B> F<F<A, B>, Result<I, B>> mapValue() {
085        return new F<F<A, B>, Result<I, B>>() {
086          public Result<I, B> f(final F<A, B> f) {
087            return mapValue(f);
088          }
089        };
090      }
091    
092      /**
093       * A bifunctor map across both the remainder of the parse input and the parse value.
094       *
095       * @param f The function to map the remainder of the parse input with.
096       * @param g The function to map the parse value with.
097       * @return A result with a different parse input and parse value.
098       */
099      public <B, J> Result<J, B> bimap(final F<I, J> f, final F<A, B> g) {
100        return mapRest(f).mapValue(g);
101      }
102    
103      /**
104       * First-class bifunctor map.
105       *
106       * @return A first-class bifunctor map.
107       */
108      public <B, J> F<F<I, J>, F<F<A, B>, Result<J, B>>> bimap() {
109        return curry(new F2<F<I, J>, F<A, B>, Result<J, B>>() {
110          public Result<J, B> f(final F<I, J> f, final F<A, B> g) {
111            return bimap(f, g);
112          }
113        });
114      }
115    
116      /**
117       * Returns an iterator over the parse value. This method exists to permit the use in a <code>for</code>-each loop.
118       *
119       * @return An iterator over the parse value.
120       */
121      public Iterator<A> iterator() {
122        return new Iterator<A>() {
123          private boolean r;
124    
125          public boolean hasNext() {
126            return !r;
127          }
128    
129          public A next() {
130            if (r)
131              throw new NoSuchElementException();
132            else {
133              r = true;
134              return a;
135            }
136          }
137    
138          public void remove() {
139            throw new UnsupportedOperationException();
140          }
141        };
142      }
143    
144      /**
145       * Construct a result with the given remainder of the parse input and parse value.
146       *
147       * @param i The remainder of the parse input.
148       * @param a The parse value.
149       * @return A result with the given remainder of the parse input and parse value.
150       */
151      public static <A, I> Result<I, A> result(final I i, final A a) {
152        return new Result<I, A>(i, a);
153      }
154    
155      /**
156       * First-class construction of a result.
157       *
158       * @return A first-class function for construction of a result.
159       */
160      public static <A, I> F<I, F<A, Result<I, A>>> result() {
161        return curry(new F2<I, A, Result<I, A>>() {
162          public Result<I, A> f(final I i, final A a) {
163            return result(i, a);
164          }
165        });
166      }
167    }