View Javadoc

1   /*
2    $Id: Reduction.java,v 1.2 2004/04/30 09:57:46 cpoirier Exp $
3   
4    Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
5   
6    Redistribution and use of this software and associated documentation
7    ("Software"), with or without modification, are permitted provided
8    that the following conditions are met:
9   
10   1. Redistributions of source code must retain copyright
11      statements and notices.  Redistributions must also contain a
12      copy of this document.
13  
14   2. Redistributions in binary form must reproduce the
15      above copyright notice, this list of conditions and the
16      following disclaimer in the documentation and/or other
17      materials provided with the distribution.
18  
19   3. The name "groovy" must not be used to endorse or promote
20      products derived from this Software without prior written
21      permission of The Codehaus.  For written permission,
22      please contact info@codehaus.org.
23  
24   4. Products derived from this Software may not be called "groovy"
25      nor may "groovy" appear in their names without prior written
26      permission of The Codehaus. "groovy" is a registered
27      trademark of The Codehaus.
28  
29   5. Due credit should be given to The Codehaus -
30      http://groovy.codehaus.org/
31  
32   THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
33   ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
34   NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
35   FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
36   THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
37   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
43   OF THE POSSIBILITY OF SUCH DAMAGE.
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    // INITIALIZATION AND SUCH
79  
80      private List    elements  = null;    // The set of child nodes   
81      private boolean marked    = false;   // Used for completion marking by some parts of the parser
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   // MEMBER ACCESS
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   // OPERATIONS
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             // It's not the greatest of design that the interface allows this, but it
242             // is a tradeoff with convenience, and the convenience is more important.
243 
244             throw new GroovyBugError( "attempt to set() a non-Token as root of a Reduction" );
245         }
246 
247 
248         //
249         // Fill slots with nulls, if necessary.
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         // Then set in the element.
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