KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > proguard > WordReader


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

21 package proguard;
22
23 import java.io.*;
24
25
26 /**
27  * An abstract reader of words, with the possibility to include other readers.
28  * Words are separated by spaces or broken off at delimiters. Words containing
29  * spaces or delimiters can be quoted with single or double quotes.
30  * Comments (everything starting with '#' on a single line) are ignored.
31  *
32  * @author Eric Lafortune
33  */

34 public abstract class WordReader
35 {
36     private static final char COMMENT_CHARACTER = '#';
37
38
39     private File baseDir;
40     private WordReader includeWordReader;
41     private String JavaDoc currentLine;
42     private int currentLineLength;
43     private int currentIndex;
44     private String JavaDoc currentWord;
45     private String JavaDoc currentComments;
46
47
48     /**
49      * Creates a new WordReader with the given base directory.
50      */

51     protected WordReader(File baseDir)
52     {
53         this.baseDir = baseDir;
54     }
55
56
57     /**
58      * Sets the base directory of this reader.
59      */

60     public void setBaseDir(File baseDir)
61     {
62         if (includeWordReader != null)
63         {
64             includeWordReader.setBaseDir(baseDir);
65         }
66         else
67         {
68             this.baseDir = baseDir;
69         }
70     }
71
72
73     /**
74      * Returns the base directory of this reader, if any.
75      */

76     public File getBaseDir()
77     {
78         return includeWordReader != null ?
79             includeWordReader.getBaseDir() :
80             baseDir;
81     }
82
83
84     /**
85      * Specifies to start reading words from the given WordReader. When it is
86      * exhausted, this WordReader will continue to provide its own words.
87      *
88      * @param newIncludeWordReader the WordReader that will start reading words.
89      */

90     public void includeWordReader(WordReader newIncludeWordReader)
91     {
92         if (includeWordReader == null)
93         {
94             includeWordReader = newIncludeWordReader;
95         }
96         else
97         {
98             includeWordReader.includeWordReader(newIncludeWordReader);
99         }
100     }
101
102
103     /**
104      * Reads a word from this WordReader, or from one of its active included
105      * WordReader objects.
106      *
107      * @return the read word.
108      */

109     public String JavaDoc nextWord() throws IOException
110     {
111         currentWord = null;
112
113         // See if we have an included reader to produce a word.
114
if (includeWordReader != null)
115         {
116             // Does the included word reader still produce a word?
117
currentWord = includeWordReader.nextWord();
118             if (currentWord != null)
119             {
120                 // Return it if so.
121
return currentWord;
122             }
123
124             // Otherwise close and ditch the word reader.
125
includeWordReader.close();
126             includeWordReader = null;
127         }
128
129         // Get a word from this reader.
130

131         // Skip leading whitespace.
132
while (currentLine != null &&
133                currentIndex < currentLineLength &&
134                Character.isWhitespace(currentLine.charAt(currentIndex)))
135         {
136             currentIndex++;
137         }
138
139         // Make sure we have a non-blank line.
140
while (currentLine == null || currentIndex == currentLineLength)
141         {
142             currentLine = nextLine();
143             if (currentLine == null)
144             {
145                 return null;
146             }
147
148             // Trim off any comments.
149
int comments_start = currentLine.indexOf(COMMENT_CHARACTER);
150             if (comments_start >= 0)
151             {
152                 currentLineLength = comments_start;
153
154                 // Remember the comments.
155
String JavaDoc comment = currentLine.substring(comments_start + 1);
156                 currentComments = currentComments == null ?
157                     comment :
158                     currentComments + '\n' + comment;
159             }
160             else
161             {
162                 currentLineLength = currentLine.length();
163             }
164
165             // Skip leading whitespace.
166
currentIndex = 0;
167             while (currentIndex < currentLineLength &&
168                    Character.isWhitespace(currentLine.charAt(currentIndex)))
169             {
170                 currentIndex++;
171             }
172         }
173
174         // Find the word starting at the current index.
175
int startIndex = currentIndex;
176         int endIndex;
177
178         char startChar = currentLine.charAt(startIndex);
179
180         if (isDelimiter(startChar))
181         {
182             // The next word is a single delimiting character.
183
endIndex = ++currentIndex;
184         }
185         else if (isQuote(startChar))
186         {
187             // The next word is starting with a quote character.
188
// Skip the opening quote.
189
startIndex++;
190
191             // The next word is a quoted character string.
192
// Find the closing quote.
193
do
194             {
195                 currentIndex++;
196
197                 if (currentIndex == currentLineLength)
198                 {
199                     currentWord = currentLine.substring(startIndex-1, currentIndex);
200                     throw new IOException("Missing closing quote for "+locationDescription());
201                 }
202             }
203             while (currentLine.charAt(currentIndex) != startChar);
204
205             endIndex = currentIndex++;
206         }
207         else
208         {
209             // The next word is a simple character string.
210
// Find the end of the line, the first delimiter, or the first
211
// white space.
212
while (currentIndex < currentLineLength)
213             {
214                 char currentCharacter = currentLine.charAt(currentIndex);
215                 if (isDelimiter(currentCharacter) ||
216                     Character.isWhitespace(currentCharacter))
217                 {
218                     break;
219                 }
220
221                 currentIndex++;
222             }
223
224             endIndex = currentIndex;
225         }
226
227         // Remember and return the parsed word.
228
currentWord = currentLine.substring(startIndex, endIndex);
229
230         return currentWord;
231     }
232
233
234     /**
235      * Returns the comments collected before returning the last word.
236      * Starts collecting new comments.
237      *
238      * @return the collected comments, or <code>null</code> if there weren't any.
239      */

240     public String JavaDoc lastComments() throws IOException
241     {
242         if (includeWordReader == null)
243         {
244             String JavaDoc comments = currentComments;
245             currentComments = null;
246             return comments;
247         }
248         else
249         {
250             return includeWordReader.lastComments();
251         }
252     }
253
254
255     /**
256      * Constructs a readable description of the current position in this
257      * WordReader and its included WordReader objects.
258      *
259      * @return the description.
260      */

261     public String JavaDoc locationDescription()
262     {
263         return
264             (includeWordReader == null ?
265                 (currentWord == null ?
266                     "end of " :
267                     "'" + currentWord + "' in " ) :
268                 (includeWordReader.locationDescription() + ",\n" +
269                  " included from ")) +
270             lineLocationDescription();
271     }
272
273
274     /**
275      * Reads a line from this WordReader, or from one of its active included
276      * WordReader objects.
277      *
278      * @return the read line.
279      */

280     protected abstract String JavaDoc nextLine() throws IOException;
281
282
283     /**
284      * Returns a readable description of the current WordReader position.
285      *
286      * @return the description.
287      */

288     protected abstract String JavaDoc lineLocationDescription();
289
290
291     /**
292      * Closes the FileWordReader.
293      */

294     public void close() throws IOException
295     {
296         // Close and ditch the included word reader, if any.
297
if (includeWordReader != null)
298         {
299             includeWordReader.close();
300             includeWordReader = null;
301         }
302     }
303
304
305     // Small utility methods.
306

307     private boolean isDelimiter(char character)
308     {
309         return character == '@' ||
310                character == '{' ||
311                character == '}' ||
312                character == '(' ||
313                character == ')' ||
314                character == ',' ||
315                character == ';' ||
316                character == File.pathSeparatorChar;
317     }
318
319
320     private boolean isQuote(char character)
321     {
322         return character == '\'' ||
323                character == '"';
324     }
325 }
326
Popular Tags