1 package io.github.reggert.reb4j;
2
3 import fj.F;
4 import fj.F2;
5 import fj.data.LazyString;
6 import fj.data.List;
7
8
9
10
11
12
13
14
15
16
17 public abstract class Raw extends AbstractSequenceableAlternative
18 {
19 private static final long serialVersionUID = 1L;
20 private final LazyString rawExpression;
21
22 Raw(final LazyString rawExpression)
23 {
24 assert rawExpression != null;
25 this.rawExpression = rawExpression;
26 }
27
28 @Override
29 public final LazyString expression()
30 {return rawExpression;}
31
32
33
34
35 @Deprecated
36 public Compound then(final Raw right)
37 {return andThen(right);}
38
39
40
41
42 @Deprecated
43 public Compound then(final Compound right)
44 {return andThen(right);}
45
46
47
48
49 @Deprecated
50 public Compound then(final Literal right)
51 {return andThen(right);}
52
53
54
55
56
57
58
59
60
61
62
63 public Compound andThen(final Raw right)
64 {
65 if (right == null) throw new NullPointerException("right");
66 return new Compound(List.list(this, right));
67 }
68
69
70
71
72
73
74
75
76
77
78 public Compound andThen(final Compound right)
79 {
80 if (right == null) throw new NullPointerException("right");
81 return new Compound(right.components.cons(this));
82 }
83
84
85
86
87
88
89
90
91
92
93 public Compound andThen(final Literal right)
94 {
95 if (right == null) throw new NullPointerException("right");
96 return this.then(new EscapedLiteral(right));
97 }
98
99
100
101
102
103 public static final class Compound extends Raw
104 {
105 private static final long serialVersionUID = 1L;
106 public final List<Raw> components;
107
108 private Compound(final List<Raw> components)
109 {
110 super(compoundExpression(components));
111 this.components = components;
112 }
113
114 private static LazyString compoundExpression(final List<Raw> components)
115 {
116 return components.foldLeft(
117 new F2<LazyString, Raw, LazyString>()
118 {
119 @Override
120 public LazyString f(final LazyString a, final Raw b)
121 {return a.append(b.rawExpression);}
122 },
123 LazyString.empty
124 );
125 }
126
127 @Override
128 @Deprecated
129 public Compound then(final Raw right)
130 {return andThen(right);}
131
132 @Override
133 @Deprecated
134 public Compound then(final Compound right)
135 {return andThen(right);}
136
137 @Override
138 public Compound andThen(final Raw right)
139 {
140 return new Compound(components.append(List.single(right)));
141 }
142
143 @Override
144 public Compound andThen(final Compound right)
145 {
146 return new Compound(components.append(right.components));
147 }
148
149 @Override
150 public Integer boundedLength()
151 {
152 final Long maximumLength = components.foldLeft(
153 new F2<Long, Raw, Long>()
154 {
155 @Override public Long f(final Long a, final Raw b)
156 {
157 if (a == null)
158 return null;
159 final Integer next = b.boundedLength();
160 if (next == null)
161 return null;
162 return a + next;
163 }
164 },
165 0L
166 );
167 if (maximumLength == null || maximumLength > 0xfffffffL)
168 return null;
169 return maximumLength.intValue();
170 }
171
172 @Override
173 public boolean repetitionInvalidatesBounds()
174 {
175 return components.forall(
176 new F<Raw, Boolean>()
177 {
178 @Override public Boolean f(final Raw a)
179 {return a.repetitionInvalidatesBounds();}
180 }
181 );
182 }
183
184 @Override
185 public boolean possiblyZeroLength()
186 {
187 return components.forall(
188 new F<Raw, Boolean>()
189 {
190 @Override public Boolean f(final Raw a)
191 {return a.possiblyZeroLength();}
192 }
193 );
194 }
195 }
196
197
198
199
200
201
202 public static final class EscapedLiteral extends Raw
203 {
204 private static final long serialVersionUID = 1L;
205 public final Literal literal;
206
207 public EscapedLiteral(final Literal literal)
208 {
209 super(literal.escaped());
210 this.literal = literal;
211 }
212
213 @Override
214 public Integer boundedLength()
215 {
216 return literal.boundedLength();
217 }
218
219 @Override
220 public boolean repetitionInvalidatesBounds()
221 {
222 return possiblyZeroLength();
223 }
224
225 @Override
226 public boolean possiblyZeroLength()
227 {
228 return literal.possiblyZeroLength();
229 }
230 }
231
232
233 @Override
234 public int hashCode()
235 {
236 final int prime = 31;
237 int result = 1;
238 result = prime * result + rawExpression.hashCode();
239 return result;
240 }
241
242 @Override
243 public boolean equals(final Object obj)
244 {
245 if (this == obj)
246 return true;
247 if (obj == null)
248 return false;
249 if (getClass() != obj.getClass())
250 return false;
251 final Raw other = (Raw) obj;
252 return rawExpression.equals(other.rawExpression);
253 }
254
255 }
256
257
258