1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/*
2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification
3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *             of Java bytecode.
4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
59f606f95f03a75961498803e24bee6799a7c0885Ying Wang * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
6b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
7b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is free software; you can redistribute it and/or modify it
8b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * under the terms of the GNU General Public License as published by the Free
9b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Software Foundation; either version 2 of the License, or (at your option)
10b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * any later version.
11b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
12b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is distributed in the hope that it will be useful, but WITHOUT
13b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * more details.
16b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
17b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * You should have received a copy of the GNU General Public License along
18b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * with this program; if not, write to the Free Software Foundation, Inc.,
19b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
21b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopackage proguard;
22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport java.io.*;
24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/**
27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * An abstract reader of words, with the possibility to include other readers.
28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Words are separated by spaces or broken off at delimiters. Words containing
29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * spaces or delimiters can be quoted with single or double quotes.
30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Comments (everything starting with '#' on a single line) are ignored.
31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune
33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @noinspection TailRecursion
34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic abstract class WordReader
36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{
37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static final char COMMENT_CHARACTER = '#';
38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private File       baseDir;
41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private WordReader includeWordReader;
42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String     currentLine;
43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private int        currentLineLength;
44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private int        currentIndex;
45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String     currentWord;
46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private String     currentComments;
47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new WordReader with the given base directory.
51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    protected WordReader(File baseDir)
53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.baseDir = baseDir;
55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Sets the base directory of this reader.
60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void setBaseDir(File baseDir)
62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (includeWordReader != null)
64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            includeWordReader.setBaseDir(baseDir);
66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        else
68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            this.baseDir = baseDir;
70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns the base directory of this reader, if any.
76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public File getBaseDir()
78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return includeWordReader != null ?
80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            includeWordReader.getBaseDir() :
81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            baseDir;
82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Specifies to start reading words from the given WordReader. When it is
87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * exhausted, this WordReader will continue to provide its own words.
88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *
89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param newIncludeWordReader the WordReader that will start reading words.
90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void includeWordReader(WordReader newIncludeWordReader)
92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (includeWordReader == null)
94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            includeWordReader = newIncludeWordReader;
96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        else
98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            includeWordReader.includeWordReader(newIncludeWordReader);
100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Reads a word from this WordReader, or from one of its active included
106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * WordReader objects.
107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *
108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @return the read word.
109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
1109f606f95f03a75961498803e24bee6799a7c0885Ying Wang    public String nextWord() throws IOException
111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        currentWord = null;
113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // See if we have an included reader to produce a word.
115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (includeWordReader != null)
116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Does the included word reader still produce a word?
1189f606f95f03a75961498803e24bee6799a7c0885Ying Wang            currentWord = includeWordReader.nextWord();
119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (currentWord != null)
120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Return it if so.
122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                return currentWord;
123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Otherwise close and ditch the word reader.
126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            includeWordReader.close();
127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            includeWordReader = null;
128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Get a word from this reader.
131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1329f606f95f03a75961498803e24bee6799a7c0885Ying Wang        // Skip leading whitespace.
1339f606f95f03a75961498803e24bee6799a7c0885Ying Wang        while (currentLine != null &&
1349f606f95f03a75961498803e24bee6799a7c0885Ying Wang               currentIndex < currentLineLength &&
1359f606f95f03a75961498803e24bee6799a7c0885Ying Wang               Character.isWhitespace(currentLine.charAt(currentIndex)))
136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
1379f606f95f03a75961498803e24bee6799a7c0885Ying Wang            currentIndex++;
138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Make sure we have a non-blank line.
141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        while (currentLine == null || currentIndex == currentLineLength)
142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            currentLine = nextLine();
144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (currentLine == null)
145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                return null;
147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1499f606f95f03a75961498803e24bee6799a7c0885Ying Wang            // Trim off any comments.
1509f606f95f03a75961498803e24bee6799a7c0885Ying Wang            int comments_start = currentLine.indexOf(COMMENT_CHARACTER);
1519f606f95f03a75961498803e24bee6799a7c0885Ying Wang            if (comments_start >= 0)
152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
1539f606f95f03a75961498803e24bee6799a7c0885Ying Wang                currentLineLength = comments_start;
154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Remember the comments.
1569f606f95f03a75961498803e24bee6799a7c0885Ying Wang                String comment = currentLine.substring(comments_start + 1);
157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                currentComments = currentComments == null ?
158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    comment :
159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    currentComments + '\n' + comment;
1609f606f95f03a75961498803e24bee6799a7c0885Ying Wang            }
1619f606f95f03a75961498803e24bee6799a7c0885Ying Wang            else
1629f606f95f03a75961498803e24bee6799a7c0885Ying Wang            {
1639f606f95f03a75961498803e24bee6799a7c0885Ying Wang                currentLineLength = currentLine.length();
1649f606f95f03a75961498803e24bee6799a7c0885Ying Wang            }
165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1669f606f95f03a75961498803e24bee6799a7c0885Ying Wang            // Skip leading whitespace.
1679f606f95f03a75961498803e24bee6799a7c0885Ying Wang            currentIndex = 0;
1689f606f95f03a75961498803e24bee6799a7c0885Ying Wang            while (currentIndex < currentLineLength &&
1699f606f95f03a75961498803e24bee6799a7c0885Ying Wang                   Character.isWhitespace(currentLine.charAt(currentIndex)))
1709f606f95f03a75961498803e24bee6799a7c0885Ying Wang            {
1719f606f95f03a75961498803e24bee6799a7c0885Ying Wang                currentIndex++;
172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Find the word starting at the current index.
176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int startIndex = currentIndex;
177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int endIndex;
178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        char startChar = currentLine.charAt(startIndex);
180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
1819f606f95f03a75961498803e24bee6799a7c0885Ying Wang        if (isDelimiter(startChar))
1829f606f95f03a75961498803e24bee6799a7c0885Ying Wang        {
1839f606f95f03a75961498803e24bee6799a7c0885Ying Wang            // The next word is a single delimiting character.
1849f606f95f03a75961498803e24bee6799a7c0885Ying Wang            endIndex = ++currentIndex;
1859f606f95f03a75961498803e24bee6799a7c0885Ying Wang        }
1869f606f95f03a75961498803e24bee6799a7c0885Ying Wang        else if (isQuote(startChar))
187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // The next word is starting with a quote character.
189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Skip the opening quote.
190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            startIndex++;
191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // The next word is a quoted character string.
193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Find the closing quote.
194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            do
195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                currentIndex++;
197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (currentIndex == currentLineLength)
199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    currentWord = currentLine.substring(startIndex-1, currentIndex);
201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    throw new IOException("Missing closing quote for "+locationDescription());
202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            while (currentLine.charAt(currentIndex) != startChar);
205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            endIndex = currentIndex++;
207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        else
209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // The next word is a simple character string.
211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Find the end of the line, the first delimiter, or the first
212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // white space.
213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            while (currentIndex < currentLineLength)
214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                char currentCharacter = currentLine.charAt(currentIndex);
2169f606f95f03a75961498803e24bee6799a7c0885Ying Wang                if (isDelimiter(currentCharacter) ||
2179f606f95f03a75961498803e24bee6799a7c0885Ying Wang                    Character.isWhitespace(currentCharacter))
2189f606f95f03a75961498803e24bee6799a7c0885Ying Wang                {
219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    break;
220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                currentIndex++;
223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            endIndex = currentIndex;
226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
227b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
228b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Remember and return the parsed word.
229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        currentWord = currentLine.substring(startIndex, endIndex);
230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return currentWord;
232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns the comments collected before returning the last word.
237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Starts collecting new comments.
238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *
239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @return the collected comments, or <code>null</code> if there weren't any.
240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
241b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public String lastComments() throws IOException
242b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (includeWordReader == null)
244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            String comments = currentComments;
246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            currentComments = null;
247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            return comments;
248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        else
250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            return includeWordReader.lastComments();
252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
254b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
255b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
256b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
257b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Constructs a readable description of the current position in this
258b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * WordReader and its included WordReader objects.
259b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *
260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @return the description.
261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public String locationDescription()
263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return
265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            (includeWordReader == null ?
266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                (currentWord == null ?
267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    "end of " :
268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    "'" + currentWord + "' in " ) :
269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                (includeWordReader.locationDescription() + ",\n" +
270b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                 "  included from ")) +
271b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            lineLocationDescription();
272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Reads a line from this WordReader, or from one of its active included
277b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * WordReader objects.
278b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *
279b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @return the read line.
280b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
281b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    protected abstract String nextLine() throws IOException;
282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
283b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
284b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
285b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Returns a readable description of the current WordReader position.
286b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *
287b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @return the description.
288b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
289b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    protected abstract String lineLocationDescription();
290b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
291b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
292b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
293b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Closes the FileWordReader.
294b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
295b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void close() throws IOException
296b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
297b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Close and ditch the included word reader, if any.
298b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (includeWordReader != null)
299b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
300b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            includeWordReader.close();
301b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            includeWordReader = null;
302b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
303b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
304b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
305b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
306b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Small utility methods.
307b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
308b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private boolean isDelimiter(char character)
309b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
310b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return character == '@' ||
311b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               character == '{' ||
312b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               character == '}' ||
313b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               character == '(' ||
314b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               character == ')' ||
315b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               character == ',' ||
316b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               character == ';' ||
317b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               character == File.pathSeparatorChar;
318b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
319b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
320b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
321b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private boolean isQuote(char character)
322b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
323b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return character == '\'' ||
324b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               character == '"';
325b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
326b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}
327