View Javadoc

1   /**
2    * Redistribution  and use  in source  and binary  forms, with  or without
3    * modification, are permitted provided  that the following conditions are
4    * met :
5    *
6    * . Redistributions  of  source  code  must  retain  the  above copyright
7    *   notice, this list of conditions and the following disclaimer.
8    *
9    * . Redistributions in  binary form  must reproduce  the above  copyright
10   *   notice, this list of conditions  and the following disclaimer in  the
11   *   documentation and/or other materials provided with the distribution.
12   *
13   * . The name of the author may not be used to endorse or promote products
14   *   derived from this software without specific prior written permission.
15   *
16   * THIS SOFTWARE IS  PROVIDED BY THE  AUTHOR ``AS IS''  AND ANY EXPRESS  OR
17   * IMPLIED  WARRANTIES,  INCLUDING,  BUT   NOT  LIMITED  TO,  THE   IMPLIED
18   * WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE ARE
19   * DISCLAIMED.  IN NO  EVENT SHALL  THE AUTHOR  BE LIABLE  FOR ANY  DIRECT,
20   * INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL  DAMAGES
21   * (INCLUDING,  BUT  NOT LIMITED  TO,  PROCUREMENT OF  SUBSTITUTE  GOODS OR
22   * SERVICES;  LOSS  OF USE,  DATA,  OR PROFITS;  OR  BUSINESS INTERRUPTION)
23   * HOWEVER CAUSED  AND ON  ANY THEORY  OF LIABILITY,  WHETHER IN  CONTRACT,
24   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25   * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE, EVEN  IF  ADVISED OF  THE
26   * POSSIBILITY OF SUCH DAMAGE.
27   */
28  
29  package cppncss.counter;
30  
31  import cppast.AbstractVisitor;
32  import cppast.AstFunctionBody;
33  import cppast.AstFunctionName;
34  import cppast.AstFunctionParameters;
35  import cppast.AstFunctionPointerPostfix;
36  import cppast.AstParameterType;
37  import cppast.AstParameterTypeQualifier;
38  import cppast.Parser;
39  import cppast.SimpleNode;
40  import cppast.Token;
41  
42  /**
43   * Provides a visitor implementation to extract a function name.
44   *
45   * @author Mathieu Champlon
46   */
47  public final class FunctionNameExtractor extends AbstractVisitor
48  {
49      private static final Filter FUNCTION_NAME_FILTER = new Filter()
50      {
51          public String decorate( final Token token )
52          {
53              final String value = token.image;
54              switch( token.kind )
55              {
56                  case Parser.SCOPE :
57                  case Parser.TILDE :
58                      return value;
59              }
60              switch( token.next.kind )
61              {
62                  case Parser.SCOPE :
63                  case Parser.LPARENTHESIS :
64                  case Parser.RPARENTHESIS :
65                  case Parser.AMPERSAND :
66                  case Parser.STAR :
67                  case Parser.LESSTHAN :
68                  case Parser.COMMA :
69                      return value;
70              }
71              return value + " ";
72          }
73      };
74      private static final Filter PARAMETER_TYPE_FILTER = new Filter()
75      {
76          public String decorate( final Token token )
77          {
78              final String value = token.image;
79              switch( token.kind )
80              {
81                  case Parser.CONST :
82                  case Parser.SIGNED :
83                  case Parser.UNSIGNED :
84                  case Parser.LESSTHAN :
85                  case Parser.COMMA :
86                      return value + " ";
87                  case Parser.GREATERTHAN :
88                      return " " + value;
89              }
90              return value;
91          }
92      };
93      private static final Filter PARAMETER_TYPE_QUALIFIER_FILTER = new Filter()
94      {
95          public String decorate( final Token token )
96          {
97              final String value = token.image;
98              switch( token.kind )
99              {
100                 case Parser.CONST :
101                 case Parser.LPARENTHESIS :
102                     return " " + value;
103             }
104             return value;
105         }
106     };
107     private boolean isFirstParameter;
108 
109     /**
110      * {@inheritDoc}
111      */
112     public Object visit( final AstFunctionName node, final Object data )
113     {
114         return node.resolve( build( node, FUNCTION_NAME_FILTER ) );
115     }
116 
117     /**
118      * {@inheritDoc}
119      */
120     public Object visit( final AstFunctionParameters node, final Object data )
121     {
122         return data + "(" + process( node ) + ")";
123     }
124 
125     private String process( final SimpleNode node )
126     {
127         isFirstParameter = true;
128         final String result = (String)node.accept( this, "" );
129         if( !isFirstParameter )
130             return result + " ";
131         return result;
132     }
133 
134     /**
135      * {@inheritDoc}
136      */
137     public Object visit( final AstParameterType node, final Object data )
138     {
139         final String result = " " + build( node, PARAMETER_TYPE_FILTER );
140         if( !isFirstParameter )
141             return data + "," + result;
142         isFirstParameter = false;
143         return data + result;
144     }
145 
146     /**
147      * {@inheritDoc}
148      */
149     public Object visit( final AstParameterTypeQualifier node, final Object data )
150     {
151         return data + build( node, PARAMETER_TYPE_QUALIFIER_FILTER );
152     }
153 
154     /**
155      * {@inheritDoc}
156      */
157     public Object visit( final AstFunctionBody node, final Object data )
158     {
159         return data;
160     }
161 
162     /**
163      * {@inheritDoc}
164      */
165     public Object visit( final AstFunctionPointerPostfix node, final Object data )
166     {
167         return data;
168     }
169 
170     private interface Filter // FIXME to be moved into SimpleNode ?
171     {
172         String decorate( final Token token );
173     }
174 
175     private String build( final SimpleNode node, final Filter filter ) // FIXME to be moved into SimpleNode ?
176     {
177         final StringBuffer buffer = new StringBuffer();
178         for( Token token = node.getFirstToken(); token != node.getLastToken().next; token = token.next )
179             buffer.append( filter.decorate( token ) );
180         return buffer.toString();
181     }
182 }