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