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