KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > j > CppTagger


1 /*
2  * CppTagger.java
3  *
4  * Copyright (C) 1998-2003 Peter Graves
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */

20
21 package org.armedbear.j;
22
23 import java.util.ArrayList JavaDoc;
24 import java.util.Stack JavaDoc;
25
26 public final class CppTagger extends JavaTagger implements Constants
27 {
28     // States.
29
private static final int NEUTRAL = 0;
30     private static final int CLASS_NAME = 1;
31     private static final int CLASS_PROLOG = 2;
32     private static final int METHOD_NAME = 3;
33     private static final int METHOD_PROLOG = 4;
34     private static final int INITIALIZATION_LIST = 5;
35
36     private static final String JavaDoc classSeparator = "::";
37
38     public CppTagger(SystemBuffer buffer)
39     {
40         super(buffer);
41     }
42
43     public void run()
44     {
45         ArrayList JavaDoc tags = new ArrayList JavaDoc();
46         String JavaDoc className = null;
47         Stack JavaDoc classNames = new Stack JavaDoc();
48         pos = new Position(buffer.getFirstLine(), 0);
49         token = null;
50         tokenStart = null;
51         int state = NEUTRAL;
52         while (!pos.atEnd()) {
53             char c = pos.getChar();
54             if (Character.isWhitespace(c)) {
55                 pos.skipWhitespace();
56                 continue;
57             }
58             if (c == '\'' || c == '"') {
59                 pos.skipQuote();
60                 continue;
61             }
62             if (pos.lookingAt("/*")) {
63                 skipComment(pos);
64                 continue;
65             }
66             if (pos.lookingAt("//")) {
67                 skipSingleLineComment(pos);
68                 continue;
69             }
70             if (c == '#' && pos.getOffset() == 0) {
71                 skipPreprocessor(pos);
72                 continue;
73             }
74             if (state == METHOD_NAME) {
75                 if (c == '{') {
76                     if (className != null)
77                         token = className + classSeparator + token;
78                     tags.add(new CppTag(token, tokenStart, TAG_METHOD));
79                     skipBrace();
80                     state = NEUTRAL;
81                     continue;
82                 }
83                 if (c == ':') {
84                     if (className != null)
85                         token = className + classSeparator + token;
86                     tags.add(new CppTag(token, tokenStart, TAG_METHOD));
87                     state = INITIALIZATION_LIST;
88                     pos.skip(1);
89                     continue;
90                 }
91                 if (pos.lookingAt("throw")) {
92                     if (className != null)
93                         token = className + classSeparator + token;
94                     state = METHOD_PROLOG;
95                     pos.skip(5); // Skip over "throw".
96
continue;
97                 }
98                 if (pos.lookingAt("const")) {
99                     if (className != null)
100                         token = className + classSeparator + token;
101                     state = METHOD_PROLOG;
102                     pos.skip(5); // Skip over "const".
103
continue;
104                 }
105                 state = NEUTRAL; // Fall through...
106
}
107             if (state == INITIALIZATION_LIST) {
108                 if (c == '{') {
109                     skipBrace();
110                     state = NEUTRAL;
111                     continue;
112                 }
113                 pos.next();
114                 continue;
115             }
116             if (state == CLASS_PROLOG){
117                 if (c == '{') {
118                     if (className != null)
119                         classNames.push(className);
120                     className = token;
121                     // Add a tag for the class itself.
122
tags.add(new CppTag("class " + token, tokenStart, TAG_CLASS));
123                     state = NEUTRAL;
124                     pos.next();
125                     continue;
126                 }
127                 if (c == ';') {
128                     // It was just a declaration.
129
pos.next();
130                     state = NEUTRAL;
131                     continue;
132                 }
133                 pos.next();
134                 continue;
135             }
136             if (state == METHOD_PROLOG) {
137                 if (c == '{') {
138                     // Opening brace of method body.
139
tags.add(new CppTag(token, tokenStart, TAG_METHOD));
140                     skipBrace();
141                     state = NEUTRAL;
142                     continue;
143                 }
144                 if (c == ';') {
145                     // It was just a declaration.
146
pos.next();
147                     state = NEUTRAL;
148                     continue;
149                 }
150                 pos.next();
151                 continue;
152             }
153             if (c == '}') {
154                 if (classNames.empty())
155                     className = null;
156                 else
157                     className = (String JavaDoc) classNames.pop();
158                 pos.next();
159                 continue;
160             }
161             if (isIdentifierStart(c)) {
162                 gatherToken();
163                 if (state == CLASS_NAME)
164                     state = CLASS_PROLOG;
165                 else if (token.equals("class"))
166                     state = CLASS_NAME;
167                 else if (token.equals("operator") || token.endsWith("::operator")) {
168                     gatherOperatorName();
169                     token = "operator " + token;
170                     state = METHOD_NAME;
171                 }
172                 continue;
173             }
174             if (c == '(') {
175                 skipParen();
176                 state = METHOD_NAME;
177                 continue;
178             }
179             pos.next();
180         }
181         buffer.setTags(tags);
182     }
183
184     private void gatherToken()
185     {
186         tokenStart = new Position(pos);
187         FastStringBuffer sb = new FastStringBuffer();
188         char c;
189         while (isIdentifierPart(c = pos.getChar())) {
190             sb.append(c);
191             if (!pos.next())
192                 break;
193         }
194         // Token can't end with ':'.
195
while (sb.length() > 0 && sb.charAt(sb.length()-1) == ':')
196             sb.setLength(sb.length()-1);
197         token = sb.toString();
198     }
199
200     private void gatherOperatorName()
201     {
202         pos.skipWhitespace();
203         tokenStart = new Position(pos);
204         FastStringBuffer sb = new FastStringBuffer();
205         char c;
206         while ((c = pos.getChar()) != '(') {
207             sb.append(c);
208             if (!pos.next())
209                 break;
210         }
211         token = sb.toString();
212     }
213
214     private static final boolean isIdentifierStart(char c)
215     {
216         if (c >= 'a' && c <= 'z')
217             return true;
218         if (c >='A' && c <= 'Z')
219             return true;
220         if (c == '_' || c == ':' || c == '~')
221             return true;
222         return false;
223     }
224
225     private static final boolean isIdentifierPart(char c)
226     {
227         if (c >= 'a' && c <= 'z')
228             return true;
229         if (c >='A' && c <= 'Z')
230             return true;
231         if (c >= '0' && c <= '9')
232             return true;
233         if (c == '_' || c == ':' || c == '~')
234             return true;
235         return false;
236     }
237 }
238
Popular Tags