All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.graphstream.stream.file.FileSourceBase Maven / Gradle / Ivy

/*
 * This file is part of GraphStream .
 * 
 * GraphStream is a library whose purpose is to handle static or dynamic
 * graph, create them from scratch, file or any source and display them.
 * 
 * This program is free software distributed under the terms of two licenses, the
 * CeCILL-C license that fits European law, and the GNU Lesser General Public
 * License. You can  use, modify and/ or redistribute the software under the terms
 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
 * URL  or under the terms of the GNU LGPL as published by
 * the Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 * 
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
 */

/**
 * @since 2009-02-19
 * 
 * @author Yoann Pigné 
 * @author Antoine Dutot 
 * @author Guilhelm Savin 
 * @author Richard O. Legendi 
 * @author kitskub 
 * @author Hicham Brahimi 
 */
package org.graphstream.stream.file;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StreamTokenizer;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

import org.graphstream.stream.SourceBase;
import org.graphstream.ui.geom.Point3;

/**
 * Base for various graph file input.
 * 
 * 

* This class is a piece of crap. However it is still used in many places... :-( * TODO use a parser generator to replace it. *

* *

* This class provides parsing utilities to help the creation of new graph * readers/parsers. It handles a stack of input files that allow to easily * implements "includes" (that is interrupting the parsing of a file to input * another one). It wraps stream tokenizers allowing to eat or get specific * token types easily. *

* *

* It is well suited for graph formats using text (not binary), but not for XML * based files where a real XML parser would probably be better. *

*/ public abstract class FileSourceBase extends SourceBase implements FileSource { // Attributes /** * The quote character. Can be changed in descendants. */ protected int QUOTE_CHAR = '"'; /** * The comment character. Can be changed in descendants. */ protected int COMMENT_CHAR = '#'; /** * Is EOL significant?. */ protected boolean eol_is_significant = false; /** * Stack of tokenizers/filenames. Each tokenizer is open on a file. When an * include is found, the current tokenizer is pushed on the stack and a new one * for the included file is created. Once the included file is parsed, the * tokenizer is popped of the stack and the previous one is used. */ protected ArrayList tok_stack = new ArrayList(); /** * Current tokenizer. */ protected StreamTokenizer st; /** * Current file name. */ protected String filename; /** * Map of unknown attributes to corresponding classes. */ protected HashMap attribute_classes = new HashMap(); // Constructors /** * No-op constructor. */ protected FileSourceBase() { } /** * Setup the reader End-Of-Line policy. * * @param eol_is_significant * If true EOL will be returned as a token, else it is ignored. */ protected FileSourceBase(boolean eol_is_significant) { this.eol_is_significant = eol_is_significant; } /** * Setup the reader End-Of-Line policy and specific comment and quote * characters. * * @param eol_is_significant * If true EOL will be returned as a token, else it is ignored. * @param commentChar * Character used for one line comments. * @param quoteChar * Character used to enclose quotations. */ protected FileSourceBase(boolean eol_is_significant, int commentChar, int quoteChar) { this.eol_is_significant = eol_is_significant; this.COMMENT_CHAR = commentChar; this.QUOTE_CHAR = quoteChar; } // Access // Command -- Complete modeField. public void readAll(String filename) throws IOException { begin(filename); while (nextEvents()) ; end(); } public void readAll(URL url) throws IOException { begin(url); while (nextEvents()) ; end(); } public void readAll(InputStream stream) throws IOException { begin(stream); while (nextEvents()) ; end(); } public void readAll(Reader reader) throws IOException { begin(reader); while (nextEvents()) ; end(); } // Commands -- By-event modeField. public void begin(String filename) throws IOException { pushTokenizer(filename); } public void begin(InputStream stream) throws IOException { pushTokenizer(stream); } public void begin(URL url) throws IOException { pushTokenizer(url); } public void begin(Reader reader) throws IOException { pushTokenizer(reader); } public abstract boolean nextEvents() throws IOException; public void end() throws IOException { popTokenizer(); } // Command /** * Declare that when attribute is found, the corresponding * attribute_class must be instantiated and inserted in the current * element being parsed. This is equivalent to the "map" keyword of the GML * file. An attribute appears in a GML file as a name followed by a "[...]" * block. The contents of this block defines sub-attributes that must map to * public fields of the attribute. Only attributes that are not handled * specifically by this parser can be added. * * @param attribute * must name the attribute. * @param attribute_class * must be the complete name of a Java class that will represent the * attribute. */ public void addAttributeClass(String attribute, String attribute_class) { attribute_classes.put(attribute, attribute_class); } // Command -- Parsing -- Include mechanism /** * Include the content of a file. This pushes a new tokenizer on * the input stack, calls the {@link #continueParsingInInclude()} method (that * must be implemented to read the include contents) and when finished pops the * tokenizer of the input stack. */ protected void include(String file) throws IOException { pushTokenizer(file); continueParsingInInclude(); popTokenizer(); } /** * Must be implemented to read the content of an include. The current tokenizer * will be set to the included file. When this method returns, the include file * will be closed an parsing will continue where it was before inclusion. */ protected abstract void continueParsingInInclude() throws IOException; /** * Push a tokenizer created from a file name on the file stack and make it * current. * * @param file * Name of the file used as source for the tokenizer. */ protected void pushTokenizer(String file) throws IOException { StreamTokenizer tok; CurrentFile cur; Reader reader; try { reader = createReaderFrom(file); tok = createTokenizer(reader); cur = new CurrentFile(file, tok, reader); } catch (FileNotFoundException e) { throw new IOException("cannot read file '" + file + "', not found: " + e.getMessage()); } configureTokenizer(tok); tok_stack.add(cur); st = tok; filename = file; } /** * Create a reader for by the tokenizer. * * @param file * File name to be opened. * @return a reader for the tokenizer. * @throws FileNotFoundException * If the given file does not exist or un readable. */ protected Reader createReaderFrom(String file) throws FileNotFoundException { return new BufferedReader(new FileReader(file)); } /** * Create a stream that can be read by the tokenizer. * * @param stream * Input stream to be open as a reader. * @return a reader for the tokenizer. */ protected Reader createReaderFrom(InputStream stream) { return new BufferedReader(new InputStreamReader(stream)); } /** * Push a tokenizer created from a stream on the file stack and make it current. * * @param url * The URL used as source for the tokenizer. */ protected void pushTokenizer(URL url) throws IOException { pushTokenizer(url.openStream(), url.toString()); } /** * Push a tokenizer created from a stream on the file stack and make it current. * * @param stream * The stream used as source for the tokenizer. */ protected void pushTokenizer(InputStream stream) throws IOException { pushTokenizer(stream, ""); } /** * Push a tokenizer created from a stream on the file stack and make it current. * * @param stream * The stream used as source for the tokenizer. * @param name * The name of the input stream. */ protected void pushTokenizer(InputStream stream, String name) throws IOException { StreamTokenizer tok; CurrentFile cur; Reader reader; reader = createReaderFrom(stream); tok = createTokenizer(reader); cur = new CurrentFile(name, tok, reader); configureTokenizer(tok); tok_stack.add(cur); st = tok; filename = name; } /** * Push a tokenizer created from a reader on the file stack and make it current. * * @param reader * The reader used as source for the tokenizer. */ protected void pushTokenizer(Reader reader) throws IOException { StreamTokenizer tok; CurrentFile cur; tok = createTokenizer(reader); cur = new CurrentFile("", tok, reader); configureTokenizer(tok); tok_stack.add(cur); st = tok; filename = ""; } /** * Create a tokenizer from an input source. * * @param reader * The reader. * @return The new tokenizer. * @throws IOException * For any I/O error. */ private StreamTokenizer createTokenizer(Reader reader) throws IOException { return new StreamTokenizer(new BufferedReader(reader)); } /** * Method to override to configure the tokenizer behaviour. It is called each * time a tokenizer is created (for the parsed file and all included files). */ protected void configureTokenizer(StreamTokenizer tok) throws IOException { if (COMMENT_CHAR > 0) tok.commentChar(COMMENT_CHAR); tok.quoteChar(QUOTE_CHAR); tok.eolIsSignificant(eol_is_significant); tok.wordChars('_', '_'); tok.parseNumbers(); } /** * Remove the current tokenizer from the stack and restore the previous one (if * any). */ protected void popTokenizer() throws IOException { int n = tok_stack.size(); if (n <= 0) throw new RuntimeException("poped one too many tokenizer"); n -= 1; CurrentFile cur = tok_stack.remove(n); cur.reader.close(); if (n > 0) { n -= 1; cur = tok_stack.get(n); st = cur.tok; filename = cur.file; } } // Low level parsing /** * Push back the last read thing, so that it can be read anew. This allows to * explore one token ahead, and if not corresponding to what is expected, go * back. */ protected void pushBack() { st.pushBack(); } /** * Read EOF or report garbage at end of file. */ protected void eatEof() throws IOException { int tok = st.nextToken(); if (tok != StreamTokenizer.TT_EOF) parseError("garbage at end of file, expecting EOF, " + gotWhat(tok)); } /** * Read EOL. */ protected void eatEol() throws IOException { int tok = st.nextToken(); if (tok != StreamTokenizer.TT_EOL) parseError("expecting EOL, " + gotWhat(tok)); } /** * Read EOL or EOF. * * @return The token read StreamTokenizer.TT_EOL or StreamTokenizer.TT_EOF. */ protected int eatEolOrEof() throws IOException { int tok = st.nextToken(); if (tok != StreamTokenizer.TT_EOL && tok != StreamTokenizer.TT_EOF) parseError("expecting EOL or EOF, " + gotWhat(tok)); return tok; } /** * Read an expected word token or generate a parse error. */ protected void eatWord(String word) throws IOException { int tok = st.nextToken(); if (tok != StreamTokenizer.TT_WORD) parseError("expecting `" + word + "', " + gotWhat(tok)); if (!st.sval.equals(word)) parseError("expecting `" + word + "' got `" + st.sval + "'"); } /** * Read an expected word among the given word list or generate a parse error. * * @param words * The expected words. */ protected void eatWords(String... words) throws IOException { int tok = st.nextToken(); if (tok != StreamTokenizer.TT_WORD) parseError("expecting one of `[" + Arrays.toString(words) + "]', " + gotWhat(tok)); boolean found = false; for (String word : words) { if (st.sval.equals(word)) { found = true; break; } } if (!found) parseError("expecting one of `[" + Arrays.toString(words) + "]', got `" + st.sval + "'"); } /** * Eat either a word or another, and return the eated one. * * @param word1 * The first word to eat. * @param word2 * The alternative word to eat. * @return The word eaten. */ protected String eatOneOfTwoWords(String word1, String word2) throws IOException { int tok = st.nextToken(); if (tok != StreamTokenizer.TT_WORD) parseError("expecting `" + word1 + "' or `" + word2 + "', " + gotWhat(tok)); if (st.sval.equals(word1)) return word1; if (st.sval.equals(word2)) return word2; parseError("expecting `" + word1 + "' or `" + word2 + "' got `" + st.sval + "'"); return null; } /** * Eat the expected symbol or generate a parse error. */ protected void eatSymbol(char symbol) throws IOException { int tok = st.nextToken(); if (tok != symbol) parseError("expecting symbol `" + symbol + "', " + gotWhat(tok)); } /** * Eat one of the list of expected symbols or generate a parse * error none of symbols can be found. */ protected int eatSymbols(String symbols) throws IOException { int tok = st.nextToken(); int n = symbols.length(); boolean f = false; for (int i = 0; i < n; ++i) { if (tok == symbols.charAt(i)) { f = true; i = n; } } if (!f) parseError("expecting one of symbols `" + symbols + "', " + gotWhat(tok)); return tok; } /** * Eat the expected word or push back what was read so that it can * be read anew. */ protected void eatWordOrPushbak(String word) throws IOException { int tok = st.nextToken(); if (tok != StreamTokenizer.TT_WORD) pushBack(); if (!st.sval.equals(word)) pushBack(); } /** * Eat the expected symbol or push back what was read so that it * can be read anew. */ protected void eatSymbolOrPushback(char symbol) throws IOException { int tok = st.nextToken(); if (tok != symbol) pushBack(); } /** * Eat all until an EOL is found. The EOL is also eaten. This works only if EOL * is significant (else it does nothing). */ protected void eatAllUntilEol() throws IOException { if (!eol_is_significant) return; int tok = st.nextToken(); if (tok == StreamTokenizer.TT_EOF) return; while ((tok != StreamTokenizer.TT_EOL) && (tok != StreamTokenizer.TT_EOF)) { tok = st.nextToken(); } } /** * Eat all availables EOLs. */ protected void eatAllEols() throws IOException { if (!eol_is_significant) return; int tok = st.nextToken(); while (tok == StreamTokenizer.TT_EOL) tok = st.nextToken(); pushBack(); } /** * Read a word or generate a parse error. */ protected String getWord() throws IOException { int tok = st.nextToken(); if (tok != StreamTokenizer.TT_WORD) parseError("expecting a word, " + gotWhat(tok)); return st.sval; } /** * Get a symbol. */ protected char getSymbol() throws IOException { int tok = st.nextToken(); if (tok > 0 && tok != StreamTokenizer.TT_WORD && tok != StreamTokenizer.TT_NUMBER && tok != StreamTokenizer.TT_EOL && tok != StreamTokenizer.TT_EOF && tok != QUOTE_CHAR && tok != COMMENT_CHAR) { return (char) tok; } parseError("expecting a symbol, " + gotWhat(tok)); return (char) 0; // Never reached. } /** * Get a symbol or push back what was read so that it can be read anew. If no * symbol is found, 0 is returned. */ protected char getSymbolOrPushback() throws IOException { int tok = st.nextToken(); if (tok > 0 && tok != StreamTokenizer.TT_WORD && tok != StreamTokenizer.TT_NUMBER && tok != StreamTokenizer.TT_EOL && tok != StreamTokenizer.TT_EOF && tok != QUOTE_CHAR && tok != COMMENT_CHAR) { return (char) tok; } pushBack(); return (char) 0; } /** * Read a string constant (between quotes) or generate a parse error. Return the * content of the string without the quotes. */ protected String getString() throws IOException { int tok = st.nextToken(); if (tok != QUOTE_CHAR) parseError("expecting a string constant, " + gotWhat(tok)); return st.sval; } /** * Read a word or number or generate a parse error. If it is a number it is * converted to a string before being returned. */ protected String getWordOrNumber() throws IOException { int tok = st.nextToken(); if (tok != StreamTokenizer.TT_WORD && tok != StreamTokenizer.TT_NUMBER) parseError("expecting a word or number, " + gotWhat(tok)); if (tok == StreamTokenizer.TT_NUMBER) { // If st.nval is an integer, as it is stored into a double, // toString() will transform it by automatically adding ".0", we // prevent this. The tokenizer does not allow to read integers. if ((st.nval - ((int) st.nval)) == 0) return Integer.toString((int) st.nval); else return Double.toString(st.nval); } else { return st.sval; } } /** * Read a string or number or generate a parse error. If it is a number it is * converted to a string before being returned. */ protected String getStringOrNumber() throws IOException { int tok = st.nextToken(); if (tok != QUOTE_CHAR && tok != StreamTokenizer.TT_NUMBER) parseError("expecting a string constant or a number, " + gotWhat(tok)); if (tok == StreamTokenizer.TT_NUMBER) { if ((st.nval - ((int) st.nval)) == 0) return Integer.toString((int) st.nval); else return Double.toString(st.nval); } else { return st.sval; } } /** * Read a string or number or pushback and return null. If it is a number it is * converted to a string before being returned. */ protected String getStringOrWordOrNumberOrPushback() throws IOException { int tok = st.nextToken(); if (tok == StreamTokenizer.TT_EOL || tok == StreamTokenizer.TT_EOF) { pushBack(); return null; } if (tok == StreamTokenizer.TT_NUMBER) { if ((st.nval - ((int) st.nval)) == 0) return Integer.toString((int) st.nval); else return Double.toString(st.nval); } else if (tok == StreamTokenizer.TT_WORD || tok == QUOTE_CHAR) { return st.sval; } else { pushBack(); return null; } } /** * Read a string or number or generate a parse error. If it is a number it is * converted to a string before being returned. */ protected String getStringOrWordOrNumber() throws IOException { int tok = st.nextToken(); if (tok == StreamTokenizer.TT_EOL || tok == StreamTokenizer.TT_EOF) parseError("expecting word, string or number, " + gotWhat(tok)); if (tok == StreamTokenizer.TT_NUMBER) { if ((st.nval - ((int) st.nval)) == 0) return Integer.toString((int) st.nval); else return Double.toString(st.nval); } else { return st.sval; } } /** * Read a string or number or generate a parse error. The returned value is * converted to a Number of a String depending on its type. */ protected Object getStringOrWordOrNumberO() throws IOException { int tok = st.nextToken(); if (tok == StreamTokenizer.TT_EOL || tok == StreamTokenizer.TT_EOF) parseError("expecting word, string or number, " + gotWhat(tok)); if (tok == StreamTokenizer.TT_NUMBER) { return st.nval; } else { return st.sval; } } /** * Read a string or number or generate a parse error. The returned value is * converted to a Number of a String depending on its type. */ protected Object getStringOrWordOrSymbolOrNumberO() throws IOException { int tok = st.nextToken(); if (tok == StreamTokenizer.TT_EOL || tok == StreamTokenizer.TT_EOF) parseError("expecting word, string or number, " + gotWhat(tok)); if (tok == StreamTokenizer.TT_NUMBER) { return st.nval; } else if (tok == StreamTokenizer.TT_WORD) { return st.sval; } else return Character.toString((char) tok); } /** * Read a word or string or generate a parse error. */ protected String getWordOrString() throws IOException { int tok = st.nextToken(); if (tok == StreamTokenizer.TT_WORD || tok == QUOTE_CHAR) return st.sval; parseError("expecting a word or string, " + gotWhat(tok)); return null; } /** * Read a word or symbol or generate a parse error. */ protected String getWordOrSymbol() throws IOException { int tok = st.nextToken(); if (tok == StreamTokenizer.TT_NUMBER || tok == QUOTE_CHAR || tok == StreamTokenizer.TT_EOF) parseError("expecting a word or symbol, " + gotWhat(tok)); if (tok == StreamTokenizer.TT_WORD) return st.sval; else return Character.toString((char) tok); } /** * Read a word or symbol or push back the read thing so that it is readable * anew. In the second case, null is returned. */ protected String getWordOrSymbolOrPushback() throws IOException { int tok = st.nextToken(); if (tok == StreamTokenizer.TT_NUMBER || tok == QUOTE_CHAR || tok == StreamTokenizer.TT_EOF) { pushBack(); return null; } if (tok == StreamTokenizer.TT_WORD) return st.sval; else return Character.toString((char) tok); } /** * Read a word or symbol or string or generate a parse error. */ protected String getWordOrSymbolOrString() throws IOException { int tok = st.nextToken(); if (tok == StreamTokenizer.TT_NUMBER || tok == StreamTokenizer.TT_EOF) parseError("expecting a word, symbol or string, " + gotWhat(tok)); if (tok == QUOTE_CHAR) return st.sval; if (tok == StreamTokenizer.TT_WORD) return st.sval; else return Character.toString((char) tok); } /** * Read a word or symbol or string or number or generate a parse error. */ protected String getAllExceptedEof() throws IOException { int tok = st.nextToken(); if (tok == StreamTokenizer.TT_EOF) parseError("expecting all excepted EOF, " + gotWhat(tok)); if (tok == StreamTokenizer.TT_NUMBER || tok == StreamTokenizer.TT_EOF) { if ((st.nval - ((int) st.nval)) == 0) return Integer.toString((int) st.nval); else return Double.toString(st.nval); } if (tok == QUOTE_CHAR) return st.sval; if (tok == StreamTokenizer.TT_WORD) return st.sval; else return Character.toString((char) tok); } /** * Read a word, a symbol or EOF, or generate a parse error. If this is EOF, the * string "EOF" is returned. */ protected String getWordOrSymbolOrEof() throws IOException { int tok = st.nextToken(); if (tok == StreamTokenizer.TT_NUMBER || tok == QUOTE_CHAR) parseError("expecting a word or symbol, " + gotWhat(tok)); if (tok == StreamTokenizer.TT_WORD) return st.sval; else if (tok == StreamTokenizer.TT_EOF) return "EOF"; else return Character.toString((char) tok); } /** * Read a word or symbol or string or EOL/EOF or generate a parse error. If EOL * is read the "EOL" string is returned. If EOF is read the "EOF" string is * returned. * * @return A string. */ protected String getWordOrSymbolOrStringOrEolOrEof() throws IOException { int tok = st.nextToken(); if (tok == StreamTokenizer.TT_NUMBER) parseError("expecting a word, symbol or string, " + gotWhat(tok)); if (tok == QUOTE_CHAR) return st.sval; if (tok == StreamTokenizer.TT_WORD) return st.sval; if (tok == StreamTokenizer.TT_EOF) return "EOF"; if (tok == StreamTokenizer.TT_EOL) return "EOL"; return Character.toString((char) tok); } /** * Read a word or number or string or EOL/EOF or generate a parse error. If EOL * is read the "EOL" string is returned. If EOF is read the "EOF" string is * returned. If a number is returned, it is converted to a string as follows: if * it is an integer, only the integer part is converted to a string without dot * or comma and no leading zeros. If it is a float the fractional part is also * converted and the dot is used as separator. * * @return A string. */ protected String getWordOrNumberOrStringOrEolOrEof() throws IOException { int tok = st.nextToken(); if (tok == StreamTokenizer.TT_NUMBER) { if (st.nval - ((int) st.nval) != 0) return Double.toString(st.nval); return Integer.toString((int) st.nval); } if (tok == QUOTE_CHAR) return st.sval; if (tok == StreamTokenizer.TT_WORD) return st.sval; if (tok == StreamTokenizer.TT_EOF) return "EOF"; if (tok == StreamTokenizer.TT_EOL) return "EOL"; parseError("expecting a word, a number, a string, EOL or EOF, " + gotWhat(tok)); return null; // Never happen, parseError throws unconditionally an // exception. } /** * Read a word or string or EOL/EOF or generate a parse error. If EOL is read * the "EOL" string is returned. If EOF is read the "EOF" string is returned. * * @return A string. */ protected String getWordOrStringOrEolOrEof() throws IOException { int tok = st.nextToken(); if (tok == StreamTokenizer.TT_WORD) return st.sval; if (tok == QUOTE_CHAR) return st.sval; if (tok == StreamTokenizer.TT_EOL) return "EOL"; if (tok == StreamTokenizer.TT_EOF) return "EOF"; parseError("expecting a word, a string, EOL or EOF, " + gotWhat(tok)); return null; // Never happen, parseError throws unconditionally an // exception. } // Order: Word | String | Symbol | Number | Eol | Eof /** * Read a word or number or string or EOL/EOF or generate a parse error. If EOL * is read the "EOL" string is returned. If EOF is read the "EOF" string is * returned. If a number is returned, it is converted to a string as follows: if * it is an integer, only the integer part is converted to a string without dot * or comma and no leading zeros. If it is a float the fractional part is also * converted and the dot is used as separator. * * @return A string. */ protected String getWordOrSymbolOrNumberOrStringOrEolOrEof() throws IOException { int tok = st.nextToken(); if (tok == StreamTokenizer.TT_NUMBER) { if (st.nval - ((int) st.nval) != 0) return Double.toString(st.nval); return Integer.toString((int) st.nval); } if (tok == QUOTE_CHAR) return st.sval; if (tok == StreamTokenizer.TT_WORD) return st.sval; if (tok == StreamTokenizer.TT_EOF) return "EOF"; if (tok == StreamTokenizer.TT_EOL) return "EOL"; return Character.toString((char) tok); } /** * Read a number or generate a parse error. */ protected double getNumber() throws IOException { int tok = st.nextToken(); if (tok != StreamTokenizer.TT_NUMBER) parseError("expecting a number, " + gotWhat(tok)); return st.nval; } /** * Read a number (possibly with an exponent) or generate a parse error. */ protected double getNumberExp() throws IOException { int tok = st.nextToken(); if (tok != StreamTokenizer.TT_NUMBER) parseError("expecting a number, " + gotWhat(tok)); double nb = st.nval; tok = st.nextToken(); if (tok == StreamTokenizer.TT_WORD && (st.sval.startsWith("e-") || st.sval.startsWith("e+"))) { double exp = Double.parseDouble(st.sval.substring(2)); return Math.pow(nb, exp); } else { st.pushBack(); } return nb; } /** * Return a string containing "got " then the content of the current * token. */ protected String gotWhat(int token) { switch (token) { case StreamTokenizer.TT_NUMBER: return "got number `" + st.nval + "'"; case StreamTokenizer.TT_WORD: return "got word `" + st.sval + "'"; case StreamTokenizer.TT_EOF: return "got EOF"; default: if (token == QUOTE_CHAR) return "got string constant `" + st.sval + "'"; else return "unknown symbol `" + token + "' (" + ((char) token) + ")"; } } /** * Generate a parse error. */ protected void parseError(String message) throws IOException { throw new IOException("parse error: " + filename + ": " + st.lineno() + ": " + message); } // Access /** * True if the string represents a truth statement ("1", "true", * "yes", "on"). */ protected boolean isTrue(String string) { string = string.toLowerCase(); if (string.equals("1")) return true; if (string.equals("true")) return true; if (string.equals("yes")) return true; if (string.equals("on")) return true; return false; } /** * True if the string represents a false statement ("0", "false", * "no", "off"). */ protected boolean isFalse(String string) { string = string.toLowerCase(); if (string.equals("0")) return true; if (string.equals("false")) return true; if (string.equals("no")) return true; if (string.equals("off")) return true; return false; } /** * Uses {@link #isTrue(String)} and {@link #isFalse(String)} to determine if * value is a truth value and return the corresponding boolean. * * @throws NumberFormatException * if the value is not a truth value. */ protected boolean getBoolean(String value) throws NumberFormatException { if (isTrue(value)) return true; if (isFalse(value)) return false; throw new NumberFormatException("not a truth value `" + value + "'"); } /** * Try to transform value into a double. * * @throws NumberFormatException * if the value is not a double. */ protected double getReal(String value) throws NumberFormatException { return Double.parseDouble(value); } /** * Try to transform value into a long. * * @throws NumberFormatException * if the value is not a long. */ protected long getInteger(String value) throws NumberFormatException { return Long.parseLong(value); } /** * Get a number triplet with numbers separated by comas and return a new point * for it. For example "0,1,2". */ protected Point3 getPoint3(String value) throws NumberFormatException { int p0 = value.indexOf(','); int p1 = value.indexOf(',', p0 + 1); if (p0 > 0 && p1 > 0) { String n0, n1, n2; float v0, v1, v2; n0 = value.substring(0, p0); n1 = value.substring(p0 + 1, p1); n2 = value.substring(p1 + 1); v0 = Float.parseFloat(n0); v1 = Float.parseFloat(n1); v2 = Float.parseFloat(n2); return new Point3(v0, v1, v2); } throw new NumberFormatException("value '" + value + "' not in a valid point3 format"); } /* * Get a number triplet with numbers separated by comas and return new bounds * for it. For example "0,1,2". protected Bounds3 getBounds3(String value) * throws NumberFormatException { int p0 = value.indexOf(','); int p1 = * value.indexOf(',', p0 + 1); * * if (p0 > 0 && p1 > 0) { String n0, n1, n2; float v0, v1, v2; * * n0 = value.substring(0, p0); n1 = value.substring(p0 + 1, p1); n2 = * value.substring(p1 + 1); * * v0 = Float.parseFloat(n0); v1 = Float.parseFloat(n1); v2 = * Float.parseFloat(n2); * * return new Bounds3(v0, v1, v2); } * * throw new NumberFormatException("value '" + value + * "' not in a valid point3 format"); } */ // Nested classes /** * Currently processed file. *

* The graph reader base can process includes in files, and handles a stack of * files. *

* */ protected static class CurrentFile { /** * The file name. */ public String file; /** * The stream tokenizer. */ public StreamTokenizer tok; public Reader reader; public CurrentFile(String f, StreamTokenizer t, Reader reader) { file = f; tok = t; this.reader = reader; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy