001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.tax.decl.parser;
042:
043: import java.io.*;
044:
045: import org.netbeans.tax.*;
046:
047: /**
048: * A simple kind of reader with some enhanced methods
049: * suitable for parsing purposes.
050: */
051: public class ParserReader extends PushbackReader {
052:
053: /** */
054: // private TreeElementDecl elementDecl;
055:
056: //
057: // init
058: //
059: public ParserReader(String source) {
060: super (new StringReader(source), 20);
061:
062: // this.elementDecl = elementDecl;
063: }
064:
065: //
066: // itself
067: //
068:
069: // /**
070: // */
071: // public final TreeElementDecl getRoot () {
072: // return elementDecl;
073: // }
074:
075: /** Trim out starting whitespaces. */
076: public ParserReader trim() {
077: int ch;
078: while (true) {
079: // read until non WS or EOF
080: try {
081: ch = read();
082: if (ch == -1 || !Character.isWhitespace((char) ch))
083: break;
084: } catch (IOException ex) {
085: ex.printStackTrace();
086: }
087: }
088:
089: try {
090: if (ch != -1)
091: unread(ch);
092: } catch (IOException ex) {
093: ex.printStackTrace();
094: }
095:
096: return this ;
097: }
098:
099: /** SE: Move on if true with otherwise push back.
100: * @return true if prefix is at the beginig of the stream
101: */
102: public boolean startsWith(String prefix) {
103: char buf[] = new char[prefix.length()];
104: try {
105: read(buf);
106: // if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug("startsWith(" + prefix + " got " + new String(buf)); // NOI18N
107: boolean ret = new String(buf).equals(prefix);
108: if (ret)
109: return true;
110: } catch (IOException ex) {
111: ex.printStackTrace();
112: return false;
113: }
114:
115: try {
116: unread(buf);
117: } catch (IOException ex) {
118: ex.printStackTrace();
119: }
120: return false;
121: }
122:
123: /** @return next character or -1 */
124: public int peek() {
125: try {
126: int ch = read();
127: unread(ch);
128: return ch;
129: } catch (IOException ex) {
130: return -1;
131: }
132: }
133:
134: /** @return whitespace or "()?+*" separated token or "". */
135: // NOI18N
136: public String getToken() {
137: StringBuffer sb = new StringBuffer();
138:
139: int ch = -1;
140:
141: trim();
142:
143: boolean reading = true; //is a char in reading buffer
144: int len = 0;
145:
146: try {
147: readChars: while (reading) { //read until token recognized
148: ch = read();
149: if (ch == -1 || Character.isWhitespace((char) ch))
150: break;
151: switch (ch) {
152: //do not eat interesting chars
153: case ')':
154: case '(':
155: case '?':
156: case '+':
157: case '*':
158: break readChars;
159:
160: //these are tokens alone
161: case ',':
162: case '|':
163: if (len == 0) {
164: reading = false; // finnish, no unread
165: } else {
166: break readChars; // finnish current token
167: }
168: }
169:
170: sb.append((char) ch);
171: len++;
172: }
173: if (ch != -1 && reading)
174: unread(ch);
175: } catch (IOException ex) {
176: // return most of recognized
177: }
178:
179: String toret = sb.toString();
180: // if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug("Token: " + toret); // NOI18N
181: return toret;
182: }
183: }
|