View Javadoc

    1   /*
    2    $Id: Reduction.java 4032 2006-08-30 07:18:49Z mguillem $
    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 antlr.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 4032 2006-08-30 07:18:49Z mguillem $
    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