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 }