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 public final class Sequence extends AbstractExpression
13 implements Alternative, Sequenceable
14 {
15 private static final long serialVersionUID = 1L;
16
17
18
19
20 public final List<Sequenceable> components;
21
22 private Sequence(final List<Sequenceable> components)
23 {
24 if (components == null) throw new NullPointerException("components");
25 this.components = components;
26 }
27
28 Sequence(final Sequence left, final Sequence right)
29 {
30 if (left == null) throw new NullPointerException("left");
31 if (right == null) throw new NullPointerException("right");
32 this.components = left.components.append(right.components);
33 }
34
35 Sequence(final Sequence left, final Sequenceable right)
36 {
37 if (left == null) throw new NullPointerException("left");
38 if (right == null) throw new NullPointerException("right");
39 this.components = left.components.append(List.single(right));
40 }
41
42 Sequence(final Sequenceable left, final Sequence right)
43 {
44 if (left == null) throw new NullPointerException("left");
45 if (right == null) throw new NullPointerException("right");
46 this.components = right.components.cons(left);
47 }
48
49 Sequence(final Sequenceable left, final Sequenceable right)
50 {
51 if (left == null) throw new NullPointerException("left");
52 if (right == null) throw new NullPointerException("right");
53 this.components = List.list(left, right);
54 }
55
56
57
58
59
60
61
62
63
64
65
66
67
68 public static Sequence sequence(
69 final Sequenceable first,
70 final Sequenceable second,
71 final Sequenceable... rest
72 )
73 {
74 if (first == null) throw new NullPointerException("first");
75 if (second == null) throw new NullPointerException("second");
76 if (rest == null) throw new NullPointerException("rest");
77 return new Sequence(List.list(rest).cons(second).cons(first));
78 }
79
80
81 @Override
82 public LazyString expression()
83 {
84 return components.foldLeft(
85 new F2<LazyString, Sequenceable, LazyString>()
86 {
87 @Override
88 public LazyString f(final LazyString a, final Sequenceable b)
89 {return a.append(b.expression());}
90 },
91 LazyString.empty
92 );
93 }
94
95 @Override
96 public Alternation or(final Alternation right)
97 {return new Alternation(this, right);}
98
99 @Override
100 public Alternation or(final Alternative right)
101 {return new Alternation(this, right);}
102
103 @Override
104 @Deprecated
105 public Sequence then(final Sequenceable right)
106 {return andThen(right);}
107
108 @Override
109 @Deprecated
110 public Sequence then(final Sequence right)
111 {return andThen(right);}
112
113 @Override
114 public Sequence andThen(final Sequenceable right)
115 {return new Sequence(this, right);}
116
117 @Override
118 public Sequence andThen(final Sequence right)
119 {return new Sequence(this, right);}
120
121 @Override
122 public int hashCode()
123 {
124 final int prime = 31;
125 int result = 1;
126 result = prime * result + components.hashCode();
127 return result;
128 }
129
130 @Override
131 public boolean equals(final Object obj)
132 {
133 if (this == obj)
134 return true;
135 if (obj == null)
136 return false;
137 if (getClass() != obj.getClass())
138 return false;
139 final Sequence other = (Sequence) obj;
140 return components.equals(other.components);
141 }
142
143 @Override
144 public Integer boundedLength()
145 {
146 final Long maximumLength = components.foldLeft(
147 new F2<Long, Sequenceable, Long>()
148 {
149 @Override public Long f(final Long a, final Sequenceable b)
150 {
151 if (a == null)
152 return null;
153 final Integer next = b.boundedLength();
154 if (next == null)
155 return null;
156 return a + next;
157 }
158 },
159 0L
160 );
161 if (maximumLength == null || maximumLength > 0xfffffffL)
162 return null;
163 return maximumLength.intValue();
164 }
165
166 @Override
167 public boolean repetitionInvalidatesBounds()
168 {
169 return components.exists(
170 new F<Sequenceable, Boolean>()
171 {
172 @Override public Boolean f(final Sequenceable a)
173 {return a.repetitionInvalidatesBounds();}
174 }
175 );
176 }
177
178 @Override
179 public boolean possiblyZeroLength()
180 {
181 return components.forall(
182 new F<Sequenceable, Boolean>()
183 {
184 @Override public Boolean f(final Sequenceable a)
185 {return a.possiblyZeroLength();}
186 }
187 );
188 }
189 }
190