1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 package org.codehaus.groovy.syntax;
48
49 import org.codehaus.groovy.GroovyBugError;
50 import org.codehaus.groovy.syntax.Token;
51
52 import java.util.List;
53 import java.util.ArrayList;
54 import java.util.Collections;
55
56
57 /***
58 * A syntax reduction, produced by the <code>Parser</code>.
59 *
60 * @see Parser
61 * @see Token
62 * @see CSTNode
63 * @see Types
64 *
65 * @author <a href="mailto:bob@werken.com">bob mcwhirter</a>
66 * @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
67 *
68 * @version $Id: Reduction.java,v 1.3 2005/04/12 15:04:59 jstrachan Exp $
69 */
70
71 public class Reduction extends CSTNode
72 {
73 public static final Reduction EMPTY = new Reduction();
74
75
76
77
78
79 private List elements = null;
80 private boolean marked = false;
81
82
83 /***
84 * Initializes the <code>Reduction</code> with the specified root.
85 */
86
87 public Reduction( Token root )
88 {
89 elements = new ArrayList();
90 set( 0, root );
91 }
92
93
94 /***
95 * Initializes the <code>Reduction</code> to empty.
96 */
97
98 private Reduction()
99 {
100 elements = Collections.EMPTY_LIST;
101 }
102
103
104 /***
105 * Creates a new <code>Reduction</code> with <code>Token.NULL</code>
106 * as it's root.
107 */
108
109 public static Reduction newContainer()
110 {
111 return new Reduction( Token.NULL );
112 }
113
114
115
116
117
118
119
120
121 /***
122 * Returns true if the node is completely empty (no root, even).
123 */
124
125 public boolean isEmpty()
126 {
127 return size() == 0;
128 }
129
130
131
132 /***
133 * Returns the number of elements in the node.
134 */
135
136 public int size()
137 {
138 return elements.size();
139 }
140
141
142
143 /***
144 * Returns the specified element, or null.
145 */
146
147 public CSTNode get( int index )
148 {
149 CSTNode element = null;
150
151 if( index < size() )
152 {
153 element = (CSTNode)elements.get( index );
154 }
155
156 return element;
157 }
158
159
160
161 /***
162 * Returns the root of the node, the Token that indicates it's
163 * type. Returns null if there is no root (usually only if the
164 * node is a placeholder of some kind -- see isEmpty()).
165 */
166
167 public Token getRoot()
168 {
169 if( size() > 0 )
170 {
171 return (Token)elements.get(0);
172 }
173 else
174 {
175 return null;
176 }
177 }
178
179
180
181 /***
182 * Marks the node a complete expression.
183 */
184
185 public void markAsExpression()
186 {
187 marked = true;
188 }
189
190
191
192 /***
193 * Returns true if the node is a complete expression.
194 */
195
196 public boolean isAnExpression()
197 {
198 if( isA(Types.COMPLEX_EXPRESSION) )
199 {
200 return true;
201 }
202
203 return marked;
204 }
205
206
207
208
209
210
211
212
213 /***
214 * Adds an element to the node.
215 */
216
217 public CSTNode add( CSTNode element )
218 {
219 return set( size(), element );
220 }
221
222
223
224 /***
225 * Sets an element in at the specified index.
226 */
227
228 public CSTNode set( int index, CSTNode element )
229 {
230
231 if( elements == null )
232 {
233 throw new GroovyBugError( "attempt to set() on a EMPTY Reduction" );
234 }
235
236 if( index == 0 && !(element instanceof Token) )
237 {
238
239
240
241
242
243 throw new GroovyBugError( "attempt to set() a non-Token as root of a Reduction" );
244 }
245
246
247
248
249
250 int count = elements.size();
251 if( index >= count )
252 {
253 for( int i = count; i <= index; i++ )
254 {
255 elements.add( null );
256 }
257 }
258
259
260
261
262 elements.set( index, element );
263
264 return element;
265 }
266
267
268
269 /***
270 * Removes a node from the <code>Reduction</code>. You cannot remove
271 * the root node (index 0).
272 */
273
274 public CSTNode remove( int index )
275 {
276 if( index < 1 )
277 {
278 throw new GroovyBugError( "attempt to remove() root node of Reduction" );
279 }
280
281 return (CSTNode)elements.remove( index );
282 }
283
284
285
286 /***
287 * Creates a <code>Reduction</code> from this node. Returns self if the
288 * node is already a <code>Reduction</code>.
289 */
290
291 public Reduction asReduction()
292 {
293 return this;
294 }
295
296 }
297