View Javadoc

    1   /*
    2    $Id: ExpressionSupport.java,v 1.1 2004/04/01 06:21:54 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.parser;
    48
    49  import org.codehaus.groovy.syntax.*;
    50
    51
    52
    53  /***
    54   *  A helper for the expression parsing system that provides in-depth
    55   *  analysis of <code>CSTNode</code>s.
    56   *
    57   *  @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
    58   */
    59
    60  public class ExpressionSupport
    61  {
    62
    63    //---------------------------------------------------------------------------
    64    // EXPRESSION IDENTIFICATION
    65
    66
    67     /***
    68      *  Returns true if the node is a complete expression (something that has
    69      *  a value).
    70      */
    71
    72      public static boolean isAnExpression( CSTNode node, boolean unknownReturns )
    73      {
    74          if( node.isA(Types.UNKNOWN) )
    75          {
    76              return unknownReturns;
    77          }
    78
    79          return node.isAnExpression();
    80      }
    81
    82
    83
    84     /***
    85      *  A synonym for <code>isAnExpression( node, false )</code>.
    86      */
    87
    88      public static boolean isAnExpression( CSTNode node )
    89      {
    90          return isAnExpression( node, false );
    91      }
    92
    93
    94
    95
    96    //---------------------------------------------------------------------------
    97    // OPERATOR IDENTIFICATION
    98
    99
    100    /***
    101     *  Returns true if the node is an operator and not an expression (see
    102     *  above).
    103     */
    104
    105     public static boolean isAnOperator( CSTNode node, boolean unknownReturns )
    106     {
    107         if( node.isA(Types.UNKNOWN) )
    108         {
    109             return unknownReturns;
    110         }
    111
    112         return !node.isAnExpression();
    113     }
    114
    115
    116
    117    /***
    118     *  A synonym for <code>isAnOperator(node, false)</code>.
    119     */
    120
    121     public static boolean isAnOperator( CSTNode node )
    122     {
    123         return isAnOperator( node, false );
    124     }
    125
    126
    127
    128
    129   //---------------------------------------------------------------------------
    130   // VARIABLE IDENTIFICATION
    131
    132
    133    /***
    134     *  Returns true if the node might be a variable.
    135     */
    136
    137     public static boolean isAVariable( CSTNode node )
    138     {
    139         switch( node.getMeaning() )
    140         {
    141             case Types.LEFT_SQUARE_BRACKET:
    142                 if( node.isAnExpression() )
    143                 {
    144                    return isAVariable( node.get(1) );
    145                 }
    146                 break;
    147
    148             case Types.DOT:
    149             case Types.NAVIGATE:
    150             {
    151                 if( node.isAnExpression() && node.get(2).getMeaning() == Types.IDENTIFIER )
    152                 {
    153                     return true;
    154                 }
    155                 break;
    156             }
    157
    158             case Types.IDENTIFIER:
    159             {
    160                 return true;
    161             }
    162         }
    163
    164         return false;
    165     }
    166
    167
    168
    169
    170   //---------------------------------------------------------------------------
    171   // METHOD IDENTIFICATION
    172
    173
    174    /***
    175     *  Returns true if the node might be a method.
    176     */
    177
    178     public static boolean isInvokable( CSTNode node )
    179     {
    180         switch( node.getMeaning() )
    181         {
    182             case Types.SYNTH_CLOSURE:
    183             case Types.SYNTH_METHOD_CALL:
    184             case Types.KEYWORD_SUPER:
    185             case Types.KEYWORD_THIS:
    186                 return true;
    187
    188             default:
    189                 return isAVariable(node);
    190         }
    191     }
    192
    193
    194
    195
    196   //---------------------------------------------------------------------------
    197   // ASSIGNMENT TARGET IDENTIFICATION
    198
    199
    200    /***
    201     *  Returns true if the node is a modifiable expression (ie. something that
    202     *  can be the target of an assignment).  Note that this determination is
    203     *  approximate: false negatives won't happen, but false positives are
    204     *  distinctly possible, and must be resolved in later phases.
    205     */
    206
    207     public static boolean isAModifiableExpression( CSTNode node, boolean unknownReturns )
    208     {
    209         if( isAnExpression(node, unknownReturns) )
    210         {
    211             if( isAVariable(node) )
    212             {
    213                 return true;
    214             }
    215
    216             else if( node.getMeaning() == Types.SYNTH_LIST )
    217             {
    218                 boolean is = true;
    219                 for( int i = 1; i < node.size(); i++ )
    220                 {
    221                     if( !isAModifiableExpression(node.get(i), unknownReturns) )
    222                     {
    223                         is = false;
    224                         break;
    225                     }
    226                 }
    227                 return is;
    228             }
    229
    230         }
    231
    232         return false;
    233     }
    234
    235
    236
    237    /***
    238     *  A synonym for <code>isAModifiableExpression( node, false )</code>.
    239     */
    240
    241     public static boolean isAModifiableExpression( CSTNode node )
    242     {
    243         return isAModifiableExpression( node, false );
    244     }
    245
    246
    247
    248
    249   //---------------------------------------------------------------------------
    250   // TYPE OPERATIONS IDENTIFICATION
    251
    252
    253    /***
    254     *  Returns true if the node is potentially a cast operator.
    255     */
    256
    257     public static boolean isPotentialCastOperator( CSTNode node )
    258     {
    259         if( node.isA(Types.LEFT_PARENTHESIS) && node.isAnExpression() )
    260         {
    261             return isAPotentialTypeName( node.get(1), false );
    262         }
    263
    264         return false;
    265     }
    266
    267
    268
    269    /***
    270     *  Returns true if the node is potentially a type name.
    271     */
    272
    273     public static boolean isAPotentialTypeName( CSTNode node, boolean allowVoid )
    274     {
    275         if( node.isA(allowVoid ? Types.TYPE_NAME : Types.CREATABLE_TYPE_NAME) )
    276         {
    277             return true;
    278         }
    279         else if( node.isA(Types.DOT) && node.isAnExpression() )
    280         {
    281             return isAPotentialTypeName(node.get(2), allowVoid) && isAPotentialTypeName(node.get(1), allowVoid);
    282         }
    283         else if( node.isA(Types.LEFT_SQUARE_BRACKET) && node.isAnExpression() && node.size() == 2 )
    284         {
    285             return isAPotentialTypeName(node.get(1), allowVoid );
    286         }
    287
    288         return false;
    289     }
    290
    291
    292
    293
    294 }