/*
Parser.java
This class provides some extra utility methods to apply to a
StreamTokenizer to make parsing the GASH files easier.
The Parser code assumes that the tokenizer has been set up to
treat ':', ',', and '\n' as distinct tokens, with everything else
treated as word chars.
Created: 6 August 1998
Module By: Jonathan Abbey, jonabbey@arlut.utexas.edu
-----------------------------------------------------------------------
Ganymede Directory Management System
Copyright (C) 1996-2010
The University of Texas at Austin
Contact information
Author Email: ganymede_author@arlut.utexas.edu
Email mailing list: ganymede@arlut.utexas.edu
US Mail:
Computer Science Division
Applied Research Laboratories
The University of Texas at Austin
PO Box 8029, Austin TX 78713-8029
Telephone: (512) 835-3200
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package arlut.csd.Util;
import java.io.IOException;
import java.io.StreamTokenizer;
/*------------------------------------------------------------------------------
class
Parser
------------------------------------------------------------------------------*/
/**
* This class provides some extra utility methods to apply to a
* StreamTokenizer to make parsing the GASH files easier.<br><br>
*
* The Parser code assumes that the tokenizer has been set up to
* treat ':', ',', and '\n' as distinct tokens, with everything else
* treated as word chars.
*/
public class Parser {
StreamTokenizer tokens;
/* -- */
public Parser (StreamTokenizer tokens)
{
this.tokens = tokens;
}
/**
*
* This method connects this Parser object to a different
* StreamTokenizer.
*
*/
public void setStream(StreamTokenizer tokens)
{
this.tokens = tokens;
}
/**
*
* Returns true if we're at EOL
*
*/
public boolean atEOL()
{
return tokens.ttype == StreamTokenizer.TT_EOL;
}
/**
*
* Returns true if we're at EOF
*
*/
public boolean atEOF()
{
return tokens.ttype == StreamTokenizer.TT_EOF;
}
/**
*
* Returns true if the next thing to be read is EOL
*
*/
public boolean EOLnext() throws IOException
{
return checkNextToken() == StreamTokenizer.TT_EOL;
}
/**
*
* Returns true if the next thing to be read is EOF
*
*/
public boolean EOFnext() throws IOException
{
return checkNextToken() == StreamTokenizer.TT_EOF;
}
/**
*
* This method runs tokens to the end of the line.
*
*/
public void skipToEndLine() throws IOException
{
while (!atEOL() && !atEOF())
{
tokens.nextToken();
}
}
/**
*
* getNextBit() returns the next String from the StreamTokenizer
* that this Parser was initialized with.
*
*/
public int getNextInt() throws IOException, NumberFormatException
{
String nextBit = getNextBit();
try
{
return Integer.parseInt(nextBit);
}
catch (NumberFormatException ex)
{
System.err.println("Parser.getNextInt(): couldn't turn '" + nextBit + "' to an Integer");
throw ex;
}
}
/**
*
* getNextBit() returns the next String from the StreamTokenizer
* that this Parser was initialized with, skipping a single leading
* ':'s and ','s along the way, up to the next ',' or ':'.
*
*/
public String getNextBit() throws IOException
{
return getNextBit(tokens, false, false);
}
/**
*
* getNextLongBit() returns the next String from the StreamTokenizer
* that this Parser was initialized with, skipping a single leading
* ':'s along the way, up to the next ':'.
*
*/
public String getNextLongBit() throws IOException
{
StringBuilder buffer = new StringBuilder();
/* -- */
if (checkNextToken() == ':')
{
tokens.nextToken();
}
while ((checkNextToken() != ':') && !EOLnext() && !EOFnext())
{
if (checkNextToken() == ',')
{
tokens.nextToken();
buffer.append(",");
}
// handle back-slashed colons
if (checkNextToken() == '\\')
{
tokens.nextToken();
if (checkNextToken() == ':')
{
tokens.nextToken();
buffer.append(":");
}
}
buffer.append(getNextBit(tokens, false, true));
}
return buffer.toString();
}
/**
*
* getNextBit() returns the next String from the StreamTokenizer
* that this Parser was initialized with.
*
* @param skipleading if true, getNextBit will chew through leading
* commas and colons until it gets to either a normal string or
* eol/eof.
*
*/
public String getNextBit(boolean skipleading) throws IOException
{
return getNextBit(tokens, skipleading, false);
}
/**
*
* getNextBit() returns the next String from the StreamTokenizer,
* where the bits are separated by colons and commas.
*
* @param tokens The StreamTokenizer to read from
*
*/
public String getNextBit(StreamTokenizer tokens) throws IOException
{
return getNextBit(tokens, true, false);
}
/**
*
* getNextBit() returns the next String from the StreamTokenizer,
* where the bits are separated by colons and commas.
*
* @param skipleading if true, getNextBit will chew through leading
* commas and colons until it gets to either a normal string or
* eol/eof.
*
* @param includeCommas if true, getNextBit will not treat commas as
* field separators
*
*/
public String getNextBit(StreamTokenizer tokens, boolean skipleading, boolean includeCommas) throws IOException
{
String result;
/* -- */
tokens.nextToken();
if (atEOL())
{
tokens.nextToken();
}
if (atEOF())
{
return "";
}
if (includeCommas)
{
// make , just part of a word for parsing purposes
tokens.wordChars(',', ',');
}
try
{
// eat any leading :'s or ,'s
if (!skipleading)
{
// skip only the single leading token
if (tokens.ttype == ':' || tokens.ttype == ',')
{
tokens.nextToken();
}
}
else
{
// skip any leading colons and commas
while (tokens.ttype == ':' || tokens.ttype == ',')
{
tokens.nextToken();
}
}
if (tokens.ttype == StreamTokenizer.TT_WORD)
{
return tokens.sval;
}
if (tokens.ttype == StreamTokenizer.TT_NUMBER)
{
result = Integer.toString((int) tokens.nval);
return result;
}
return null;
}
finally
{
// turn , back into a separate token
if (includeCommas)
{
tokens.ordinaryChar(',');
}
}
}
/**
*
* This method returns a peek at the next token in the
* StreamTokenizer that this Parser was initialized with.
*
*/
public int checkNextToken() throws IOException
{
return checkNextToken(tokens);
}
/**
*
* This method returns a peek at the next token in the
* StreamTokenizer passed in.
*
*/
public int checkNextToken(StreamTokenizer tokens) throws IOException
{
tokens.nextToken();
int result = tokens.ttype;
tokens.pushBack();
return result;
}
}