package org.sinnlabs.dbvim.evaluator;
import org.sinnlabs.dbvim.ui.IField;
/** A token.
* <br>When evaluating an expression, it is first split into tokens.
* These tokens can be operators, constants, etc ...
* @author Jean-Marc Astesana
*/
public class Token {
private enum Kind {
OPEN_BRACKET,
CLOSE_BRACKET,
FUNCTION_SEPARATOR,
FUNCTION,
OPERATOR,
LITERAL,
FIELD,
JOIN_FIELD
}
static final Token FUNCTION_ARG_SEPARATOR = new Token(Kind.FUNCTION_SEPARATOR, null);
private Kind kind;
private Object content;
static Token buildLiteral(String literal) {
return new Token(Kind.LITERAL, literal);
}
static Token buildOperator(Operator ope) {
return new Token(Kind.OPERATOR, ope);
}
static Token buildFunction(Function function) {
return new Token(Kind.FUNCTION, function);
}
static Token buildOpenToken(BracketPair pair) {
return new Token(Kind.OPEN_BRACKET, pair);
}
static Token buildCloseToken(BracketPair pair) {
return new Token(Kind.CLOSE_BRACKET, pair);
}
static Token buildFieldToken(IField<?> field) {
return new Token(Kind.FIELD, field);
}
static Token buildJoinFieldToken(IField<?> field) {
return new Token(Kind.JOIN_FIELD, field);
}
private Token(Kind kind, Object content) {
super();
if ((kind.equals(Kind.OPERATOR) && !(content instanceof Operator)) ||
(kind.equals(Kind.FUNCTION) && !(content instanceof Function)) ||
(kind.equals(Kind.LITERAL) && !(content instanceof String))) {
throw new IllegalArgumentException();
}
this.kind = kind;
this.content = content;
}
BracketPair getBrackets() {
return (BracketPair) this.content;
}
Operator getOperator() {
return (Operator) this.content;
}
Function getFunction() {
return (Function) this.content;
}
IField<?> getField() {
return (IField<?>) this.content;
}
Kind getKind() {
return kind;
}
/** Tests whether the token is an operator.
* @return true if the token is an operator
*/
public boolean isOperator() {
return kind.equals(Kind.OPERATOR);
}
/** Tests whether the token is a function.
* @return true if the token is a function
*/
public boolean isFunction() {
return kind.equals(Kind.FUNCTION);
}
/** Tests whether the token is an open bracket.
* @return true if the token is an open bracket
*/
public boolean isOpenBracket() {
return kind.equals(Kind.OPEN_BRACKET);
}
/** Tests whether the token is a close bracket.
* @return true if the token is a close bracket
*/
public boolean isCloseBracket() {
return kind.equals(Kind.CLOSE_BRACKET);
}
/** Tests whether the token is a function argument separator.
* @return true if the token is a function argument separator
*/
public boolean isFunctionArgumentSeparator() {
return kind.equals(Kind.FUNCTION_SEPARATOR);
}
/** Tests whether the token is a literal or a constant or a variable name.
* @return true if the token is a literal, a constant or a variable name
*/
public boolean isLiteral() {
return kind.equals(Kind.LITERAL);
}
/**
* Tests whether the token is a field
* @return true if token is a field
*/
public boolean isField() {
return kind.equals(Kind.FIELD) || kind.equals(Kind.JOIN_FIELD);
}
/**
* Tests whether the token is a join field (field from right form)
* @return true if token is a join field
*/
public boolean isJoinField() {
return kind.equals(Kind.JOIN_FIELD);
}
Operator.Associativity getAssociativity() {
return getOperator().getAssociativity();
}
int getPrecedence() {
return getOperator().getPrecedence();
}
String getLiteral() {
if (!this.kind.equals(Kind.LITERAL)) {
throw new IllegalArgumentException();
}
return (String)this.content;
}
}