blob: 566e672b2f33e510098108f8ad6f03af54496d88 [file] [log] [blame]
/* Copyright (c) 2001-2007, The HSQL Development Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the HSQL Development Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.hsqldb.util.preprocessor;
/* $Id: Tokenizer.java 610 2008-12-22 15:54:18Z unsaved $ */
/**
* Simple preprocessor directive tokenizer.
*
* @author boucherb@users
* @version 1.8.1
* @since 1.8.1
*/
final class Tokenizer {
private final String command;
private final int commandLength;
private int tokenType;
private int startIndex;
private int currentIndex;
Tokenizer(final String cmd) {
this.command = cmd + " ";
this.commandLength = command.length();
this.startIndex = 0;
this.currentIndex = 0;
this.tokenType = Token.UNKNOWN;
}
void skipBlanks() {
final String cmd = this.command;
final int len = this.commandLength;
top:
while (currentIndex < len) {
switch(cmd.charAt(currentIndex)) {
case ' ' :
case '\t' : {
currentIndex++;
continue top;
}
}
break;
}
}
int next() throws PreprocessorException {
skipBlanks();
startIndex = currentIndex;
final String cmd = this.command;
final int len = this.commandLength;
if (currentIndex >= len) {
tokenType = Token.EOI;
return tokenType;
}
char ch = cmd.charAt(currentIndex);
if (Character.isJavaIdentifierStart(ch)) {
tokenType = Token.IDENT;
currentIndex++;
while (currentIndex < len &&
Character.isJavaIdentifierPart(cmd.charAt(currentIndex))) {
currentIndex++;
}
return tokenType;
} else if (Character.isDigit(ch)) {
tokenType = Token.NUMBER;
currentIndex++;
while(currentIndex < len &&
Character.isDigit(cmd.charAt(currentIndex))) {
currentIndex++;
}
if (currentIndex < len && cmd.charAt(currentIndex) == '.') {
currentIndex++;
}
while(currentIndex < len &&
Character.isDigit(cmd.charAt(currentIndex))) {
currentIndex++;
}
return tokenType;
} else if (ch == '"') {
tokenType = Token.STRING;
currentIndex++;
int pos = cmd.indexOf('"', currentIndex);
if (pos == -1) {
throw new PreprocessorException("Unclosed string literal: " +
cmd.substring(startIndex)); //NOI18N
}
currentIndex = pos + 1;
return tokenType;
}
switch(ch) {
case Token.LPAREN :
case Token.RPAREN :
case Token.XOR :
case Token.NOT : {
currentIndex++;
return (tokenType = ch);
}
case Token.ASSIGN : {
currentIndex++;
if(currentIndex < len &&
cmd.charAt(currentIndex) == Token.ASSIGN) {
currentIndex++;
tokenType = Token.EQ;
} else {
tokenType = Token.ASSIGN;
}
return tokenType;
}
case Token.LT : {
currentIndex++;
if (currentIndex < len &&
cmd.charAt(currentIndex) == Token.ASSIGN) {
currentIndex++;
tokenType = Token.LTE;
} else {
tokenType = Token.LT;
}
return tokenType;
}
case Token.GT : {
currentIndex++;
if (currentIndex < len &&
cmd.charAt(currentIndex) == Token.ASSIGN) {
currentIndex++;
tokenType = Token.GTE;
} else {
tokenType = Token.GT;
}
return tokenType;
}
case Token.AND :
case Token.OR : {
currentIndex++;
if (currentIndex < len && cmd.charAt(currentIndex) == ch) {
currentIndex++;
}
return (tokenType = ch);
}
default : {
throw new PreprocessorException("Syntax error: " +
cmd.substring(currentIndex)); //NOI18N
}
}
}
int getTokenType() {
return tokenType;
}
boolean isToken(final int type) {
return (this.tokenType == type);
}
String getIdent() {
return isToken(Token.EOI) ? null
: this.command.substring(startIndex, currentIndex);
}
Number getNumber() {
return (isToken(Token.EOI)) ? null
: new Double(Double.parseDouble(this.command.
substring(startIndex, currentIndex)));
}
String getString() {
return isToken(Token.EOI) ? null
: this.command.substring(startIndex + 1, currentIndex - 1);
}
int getStartIndex() {
return this.startIndex;
}
int currentIndex() {
return this.currentIndex;
}
String getSource() {
return this.command;
}
}