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
171 {
172 String decorate( final Token token );
173 }
174
175 private String build( final SimpleNode node, final Filter filter )
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 }