using System;
using System.IO;
using System.Text;
using GisSharpBlog.NetTopologySuite.IO;
// http://java.sun.com/j2se/1.4/docs/api/java/io/StreamTokenizer.html
// a better implementation could be written. Here is a good Java implementation of StreamTokenizer.
// http://www.flex-compiler.lcs.mit.edu/Harpoon/srcdoc/java/io/StreamTokenizer.html
// a C# StringTokenizer
// http://sourceforge.net/snippet/detail.php?type=snippet&id=101171
// Diego Guidi says: for my port i have used the RTools.Util.StreamTokenized, and seems very powerful!
// this code is present only for compatibility with GeoTools.NET code.
namespace GisSharpBlog.NetTopologySuite.Utilities
{
///
/// The StreamTokenizer class takes an input stream and parses it into "tokens",
/// allowing the tokens to be read one at a time.
/// The parsing process is controlled by a table and a number of flags that can be set to various states.
/// The stream tokenizer can recognize identifiers, numbers, quoted strings, and various comment style.
///
///
/// This is a crude c# implementation of Java's
/// StreamTokenizer class.
///
[Obsolete("This class is only for GeoTools.NET code compatibility: use RTools.Util.StreamTokenizer instead.")]
public class GeoToolsStreamTokenizer
{
private TokenType _currentTokenType;
private readonly TextReader _reader;
private string _currentToken;
private readonly bool _ignoreWhitespace = false;
private int _lineNumber = 1;
private int _colNumber = 1;
///
/// Initializes a new instance of the StreamTokenizer class.
///
/// A TextReader with some text to read.
/// Flag indicating whether whitespace should be ignored.
public GeoToolsStreamTokenizer(TextReader reader, bool ignoreWhitespace)
{
if (reader == null)
{
throw new ArgumentNullException("reader");
}
_reader = reader;
_ignoreWhitespace = ignoreWhitespace;
}
///
/// The current line number of the stream being read.
///
public int LineNumber
{
get
{
return _lineNumber;
}
}
///
/// The current column number of the stream being read.
///
public int Column
{
get
{
return _colNumber;
}
}
///
/// If the current token is a number, this field contains the value of that number.
///
///
/// If the current token is a number, this field contains the value of that number. The current token is a number when the value of the ttype field is TT_NUMBER.
///
/// Current token is not a number in a valid format.
public double GetNumericValue()
{
string number = GetStringValue();
if (GetTokenType() == TokenType.Number)
{
return double.Parse(number);
}
throw new ParseException(String.Format("The token '{0}' is not a number at line {1} column {2}.", number, LineNumber, Column));
;
}
///
/// If the current token is a word token, this field contains a string giving the characters of the word token.
///
public string GetStringValue()
{
return _currentToken;
}
///
/// Gets the token type of the current token.
///
///
public TokenType GetTokenType()
{
return _currentTokenType;
}
///
/// Returns the next token.
///
/// Determines is whitespace is ignored. True if whitespace is to be ignored.
/// The TokenType of the next token.
public TokenType NextToken(bool ignoreWhitespace)
{
TokenType nextTokenType;
if (ignoreWhitespace)
{
nextTokenType = NextNonWhitespaceToken();
}
else
{
nextTokenType = NextTokenAny();
}
return nextTokenType;
}
///
/// Returns the next token.
///
/// The TokenType of the next token.
public TokenType NextToken()
{
return NextToken(_ignoreWhitespace);
}
///
///
///
///
private TokenType NextTokenAny()
{
TokenType nextTokenType = TokenType.Eof;
char[] chars = new char[1];
_currentToken = String.Empty;
_currentTokenType = TokenType.Eof;
int finished = _reader.Read(chars, 0, 1);
bool isNumber = false;
bool isWord = false;
byte[] ba = null;
ASCIIEncoding AE = new ASCIIEncoding();
char[] ascii = null;
Char currentCharacter;
Char nextCharacter;
while (finished != 0)
{
// convert int to char
ba = new Byte[]
{
(byte) _reader.Peek()
};
ascii = AE.GetChars(ba);
currentCharacter = chars[0];
nextCharacter = ascii[0];
_currentTokenType = GetType(currentCharacter);
nextTokenType = GetType(nextCharacter);
// handling of words with _
if (isWord && currentCharacter == '_')
{
_currentTokenType = TokenType.Word;
}
// handing of words ending in numbers
if (isWord && _currentTokenType == TokenType.Number)
{
_currentTokenType = TokenType.Word;
}
if (_currentTokenType == TokenType.Word && nextCharacter == '_')
{
// enable words with _ inbetween
nextTokenType = TokenType.Word;
isWord = true;
}
if (_currentTokenType == TokenType.Word && nextTokenType == TokenType.Number)
{
// enable words ending with numbers
nextTokenType = TokenType.Word;
isWord = true;
}
// handle negative numbers
if (currentCharacter == '-' && nextTokenType == TokenType.Number && isNumber == false)
{
_currentTokenType = TokenType.Number;
nextTokenType = TokenType.Number;
}
// this handles numbers with a decimal point
if (isNumber && nextTokenType == TokenType.Number && currentCharacter == '.')
{
_currentTokenType = TokenType.Number;
}
if (_currentTokenType == TokenType.Number && nextCharacter == '.' && isNumber == false)
{
nextTokenType = TokenType.Number;
isNumber = true;
}
_colNumber++;
if (_currentTokenType == TokenType.Eol)
{
_lineNumber++;
_colNumber = 1;
}
_currentToken = _currentToken + currentCharacter;
if (_currentTokenType != nextTokenType)
{
finished = 0;
}
else if (_currentTokenType == TokenType.Symbol && currentCharacter != '-')
{
finished = 0;
}
else
{
finished = _reader.Read(chars, 0, 1);
}
}
return _currentTokenType;
}
///
/// Determines a characters type (e.g. number, symbols, character).
///
/// The character to determine.
/// The TokenType the character is.
private TokenType GetType(char character)
{
if (Char.IsDigit(character))
{
return TokenType.Number;
}
else if (Char.IsLetter(character))
{
return TokenType.Word;
}
else if (character == '\n')
{
return TokenType.Eol;
}
else if (Char.IsWhiteSpace(character) || Char.IsControl(character))
{
return TokenType.Whitespace;
}
else // (Char.IsSymbol(character))
{
return TokenType.Symbol;
}
}
///
/// Returns next token that is not whitespace.
///
///
private TokenType NextNonWhitespaceToken()
{
TokenType tokentype = NextTokenAny();
while (tokentype == TokenType.Whitespace || tokentype == TokenType.Eol)
{
tokentype = NextTokenAny();
}
return tokentype;
}
}
}