View Javadoc

1   /*
2    $Id: Reduction.java,v 1.3 2005/04/12 15:04:59 jstrachan 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.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    // INITIALIZATION AND SUCH
78  
79      private List    elements  = null;    // The set of child nodes   
80      private boolean marked    = false;   // Used for completion marking by some parts of the parser
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   // MEMBER ACCESS
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   // OPERATIONS
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             // It's not the greatest of design that the interface allows this, but it
241             // is a tradeoff with convenience, and the convenience is more important.
242 
243             throw new GroovyBugError( "attempt to set() a non-Token as root of a Reduction" );
244         }
245 
246 
247         //
248         // Fill slots with nulls, if necessary.
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         // Then set in the element.
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