001: /*
002: * This file or a portion of this file is licensed under the terms of
003: * the Globus Toolkit Public License, found in file GTPL, or at
004: * http://www.globus.org/toolkit/download/license.html. This notice must
005: * appear in redistributions of this file, with or without modification.
006: *
007: * Redistributions of this Software, with or without modification, must
008: * reproduce the GTPL in: (1) the Software, or (2) the Documentation or
009: * some other similar material which is provided with the Software (if
010: * any).
011: *
012: * Copyright 1999-2004 University of Chicago and The University of
013: * Southern California. All rights reserved.
014: */
015: package org.griphyn.cPlanner.classes;
016:
017: import java.io.IOException;
018: import java.io.LineNumberReader;
019: import java.io.Reader;
020:
021: /**
022: * Implements the scanner for reserved words and other tokens that are
023: * generated from the input stream. This class is module-local on
024: * purpose.
025: *
026: * @author Jens Vöckler
027: */
028: class PoolConfigScanner {
029: /**
030: * Stores the stream from which we are currently scanning.
031: */
032: private LineNumberReader m_in;
033:
034: /**
035: * Captures the look-ahead character.
036: */
037: private int m_lookAhead;
038:
039: /**
040: * Starts to scan the given stream.
041: *
042: * @param reader the reader stream from which we are reading the site catalog.
043: */
044: public PoolConfigScanner(Reader reader) throws IOException {
045: this .m_in = new LineNumberReader(reader);
046: this .m_lookAhead = m_in.read();
047: // skipWhitespace();
048: }
049:
050: /**
051: * Obtains the current line number in the input stream from the outside.
052: *
053: * @return the current line number.
054: */
055: public int getLineNumber() {
056: return m_in.getLineNumber();
057: }
058:
059: /**
060: * Skips any white space and comments in the input. This method stops either
061: * at the end of file, or at any non-whitespace input character.
062: */
063: private void skipWhitespace() throws IOException {
064: // end of file?
065: if (m_lookAhead == -1)
066: return;
067:
068: // skip over whitespace
069: while (m_lookAhead != -1
070: && Character.isWhitespace((char) m_lookAhead))
071: m_lookAhead = m_in.read();
072:
073: // skip over comments until eoln
074: if (m_lookAhead == '#') {
075: m_in.readLine();
076: m_lookAhead = m_in.read();
077: skipWhitespace(); // FIXME: reformulate end-recursion into loop
078: }
079: }
080:
081: /**
082: * Checks for the availability of more input.
083: *
084: * @return true, if there is more to read, false for EOF.
085: */
086: public boolean hasMoreTokens() throws IOException {
087: skipWhitespace();
088: return (this .m_lookAhead != -1);
089: }
090:
091: /**
092: * Obtains the next token from the input stream.
093: *
094: * @return an instance conforming to the token interface, or null for eof.
095: * @throws IOException if something went wrong while reading
096: * @throws PoolConfigException if a lexical error was encountered.
097: */
098: public PoolConfigToken nextToken() throws IOException,
099: PoolConfigException {
100: // sanity check
101: skipWhitespace();
102: if (m_lookAhead == -1)
103: return null;
104:
105: // are we parsing a reserved word or identifier
106: if (Character.isJavaIdentifierStart((char) m_lookAhead)) {
107: StringBuffer identifier = new StringBuffer(8);
108: identifier.append((char) m_lookAhead);
109: m_lookAhead = m_in.read();
110: while (m_lookAhead != -1
111: && Character
112: .isJavaIdentifierPart((char) m_lookAhead)) {
113: identifier.append((char) m_lookAhead);
114: m_lookAhead = m_in.read();
115: }
116:
117: // done parsing identifier or reserved word
118: skipWhitespace();
119: String s = identifier.toString().toLowerCase();
120: if (PoolConfigReservedWord.symbolTable().containsKey(s)) {
121: // isa reserved word
122: return (PoolConfigReservedWord) PoolConfigReservedWord
123: .symbolTable().get(s);
124: } else {
125: // non-reserved identifier
126: return new PoolConfigIdentifier(identifier.toString());
127: }
128:
129: } else if (m_lookAhead == '{') {
130: m_lookAhead = m_in.read();
131: skipWhitespace();
132: return new PoolConfigOpenBrace();
133:
134: } else if (m_lookAhead == '}') {
135: m_lookAhead = m_in.read();
136: skipWhitespace();
137: return new PoolConfigCloseBrace();
138:
139: } else if (m_lookAhead == '(') {
140: m_lookAhead = m_in.read();
141: skipWhitespace();
142: return new PoolConfigOpenParanthesis();
143:
144: } else if (m_lookAhead == ')') {
145: m_lookAhead = m_in.read();
146: skipWhitespace();
147: return new PoolConfigCloseParanthesis();
148:
149: } else if (m_lookAhead == '"') {
150: // parser quoted string
151: StringBuffer result = new StringBuffer(16);
152: do {
153: m_lookAhead = m_in.read();
154: if (m_lookAhead == -1 || m_lookAhead == '\r'
155: || m_lookAhead == '\n') {
156: // eof is an unterminated string
157: throw new PoolConfigException(m_in,
158: "unterminated quoted string");
159: } else if (m_lookAhead == '\\') {
160: int temp = m_in.read();
161: if (temp == -1) {
162: throw new PoolConfigException(m_in,
163: "unterminated escape in quoted string");
164: } else {
165: // always add whatever is after the backslash
166: // FIXME: We could to fancy C-string style \012 \n \r escapes here ;-P
167: result.append((char) temp);
168: }
169: } else if (m_lookAhead != '"') {
170: result.append((char) m_lookAhead);
171: }
172: } while (m_lookAhead != '"');
173:
174: // skip over final quote
175: m_lookAhead = m_in.read();
176: skipWhitespace();
177: return new PoolConfigQuotedString(result.toString());
178:
179: } else {
180: // unknown material
181: throw new PoolConfigException(m_in, "unknown character "
182: + m_lookAhead);
183: }
184: }
185: }
|