/*
* JMEP - Java Mathematical Expression Parser.
* Copyright (C) 1999 Jo Desmet
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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 library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* You can contact the Original submitter of this library by
* email at: Jo_Desmet@yahoo.com.
*
*/
package com.iabcinc.jmep.tokens;
import com.iabcinc.jmep.XExpression;
import com.iabcinc.jmep.XIllegalOperation;
import com.iabcinc.jmep.XIllegalStatus;
public class BINToken extends Token {
public enum Operator {
POW (9,false), /* Raise to a power */
MUL (8,true ), /* Multiply */
DIV (8,false), /* divide (non-strict: int/int=float) */
MOD (8,false), /* Modulus for a division */
ADD (7,true ), /* Add */
SUB (7,false), /* Substract */
LT (6,false), /* Test for Less Than */
GT (6,false), /* Test for More Than */
LE (6,false), /* Test for Less or Equal */
GE (6,false), /* Test for More or Equal */
NE (6,true ), /* Test for non-Equality */
EQ (6,true ), /* Test for Equality */
AND (4,true ), /* Bitwise AND */
OR (2,true ), /* Bitwise OR */
XOR (3,true ), /* Bitwise XOR */
LAND (1,true ), /* Logical AND */
LOR (0,true ), /* Logical OR */
SDIV (8,false); /* Strict division (int/int = int) */
public final int precedence;
public final boolean commutative;
public boolean isCommutative() {
return commutative;
}
Operator(int precedence,boolean commutative) {
this.precedence = precedence;
this.commutative = commutative;
}
}
private final Operator m_kBINToken;
//private int m_iPrecedence;
static int resolvePrecedence(Operator kBINToken) {
return kBINToken.precedence;
}
public BINToken(Operator kBINToken,int iPosition) {
super(Token.BIN,iPosition);
m_kBINToken = kBINToken;
//m_iPrecedence = resolvePrecedence(kBINToken);
}
public int getPrecedence() {
return m_kBINToken.precedence;
}
private int[][] intArrays = new int[1][1];
private float[][] floatArrays = new float[1][1];
public Object evaluate(Object oValue1, Object oValue2, int contextID) throws XExpression {
int i = contextID;
//Fast
if (oValue1 instanceof int[]) {
int dValue1 = ((int[])oValue1)[0];
if (oValue2 instanceof int[]) {
int dValue2 = ((int[])oValue2)[0];
switch (m_kBINToken) {
case POW:
/*
* RESTRICTION: always returns float. Example: 2^2 will
* always give 4.0 as result and not 4 !!
*/
floatArrays[i][0] = (float)Math.pow(dValue1,dValue2); return floatArrays[i];
case MUL: intArrays[i][0] = dValue1*dValue2; return intArrays[i];
case SDIV: intArrays[i][0] = dValue1/dValue2; return intArrays[i];
case DIV: floatArrays[i][0] = (float)dValue1/dValue2; return floatArrays[i];
case MOD: intArrays[i][0] = dValue1%dValue2; return intArrays[i];
case ADD: intArrays[i][0] = dValue1+dValue2; return intArrays[i];
case SUB: intArrays[i][0] = dValue1-dValue2; return intArrays[i];
case LT: intArrays[i][0] = (dValue1 < dValue2)?1:0; return intArrays[i];
case GT: intArrays[i][0] = (dValue1 > dValue2)?1:0; return intArrays[i];
case LE: intArrays[i][0] = (dValue1 <= dValue2)?1:0; return intArrays[i];
case GE: intArrays[i][0] = (dValue1 >= dValue2)?1:0; return intArrays[i];
case NE: intArrays[i][0] = (dValue1 != dValue2)?1:0; return intArrays[i];
case EQ: intArrays[i][0] = (dValue1 == dValue2)?1:0; return intArrays[i];
case AND: intArrays[i][0] = dValue1&dValue2; return intArrays[i];
case XOR: intArrays[i][0] = dValue1^dValue2; return intArrays[i];
case OR: intArrays[i][0] = dValue1|dValue2; return intArrays[i];
case LAND: intArrays[i][0] = ((dValue1 != 0) && (dValue2 != 0))?1:0; return intArrays[i];
case LOR: intArrays[i][0] = ((dValue1 != 0) || (dValue2 != 0))?1:0; return intArrays[i];
default: throw new XIllegalStatus(getPosition());
}
}
else if (oValue2 instanceof float[]) {
float fValue2 = ((float[])oValue2)[0];
switch (m_kBINToken) {
case POW: floatArrays[i][0] = (float)Math.pow(dValue1,fValue2); return floatArrays[i];
case MUL: floatArrays[i][0] = dValue1*fValue2; return floatArrays[i];
case SDIV: /* continue with next */
case DIV: floatArrays[i][0] = dValue1/fValue2; return floatArrays[i];
case MOD: throw new XIllegalOperation(this,oValue1,oValue2);
case ADD: floatArrays[i][0] = dValue1+fValue2; return floatArrays[i];
case SUB: floatArrays[i][0] = dValue1-fValue2; return floatArrays[i];
case LT: intArrays[i][0] = (dValue1 < fValue2)?1:0; return intArrays[i];
case GT: intArrays[i][0] = (dValue1 > fValue2)?1:0; return intArrays[i];
case LE: intArrays[i][0] = (dValue1 <= fValue2)?1:0; return intArrays[i];
case GE: intArrays[i][0] = (dValue1 >= fValue2)?1:0; return intArrays[i];
/*
* REMARK: NE and EQ will be considdered illegal operations here
* because of the statistical probability of meeting the condition.
*/
case NE: throw new XIllegalOperation(this,oValue1,oValue2);
case EQ: throw new XIllegalOperation(this,oValue1,oValue2);
case AND: throw new XIllegalOperation(this,oValue1,oValue2);
case XOR: throw new XIllegalOperation(this,oValue1,oValue2);
case OR: throw new XIllegalOperation(this,oValue1,oValue2);
case LAND: throw new XIllegalOperation(this,oValue1,oValue2);
case LOR: throw new XIllegalOperation(this,oValue1,oValue2);
default: throw new XIllegalStatus(getPosition());
}
}
else if (oValue2 instanceof String) {
String sValue2 = (String)oValue2;
switch (m_kBINToken) {
case POW: throw new XIllegalOperation(this,oValue1,oValue2);
case MUL: {
String sValue = sValue2;
if (dValue1 <= 0) throw new XIllegalOperation(this,oValue1,oValue2);
for (int iCount = 1; iCount < dValue1; iCount++) {
sValue = sValue + sValue2;
}
return sValue;
}
case SDIV: /* continue with next */
case DIV: throw new XIllegalOperation(this,oValue1,oValue2);
case MOD: throw new XIllegalOperation(this,oValue1,oValue2);
case ADD: return Integer.toString(dValue1) + sValue2;
case SUB: throw new XIllegalOperation(this,oValue1,oValue2);
case LT: throw new XIllegalOperation(this,oValue1,oValue2);
case GT: throw new XIllegalOperation(this,oValue1,oValue2);
case LE: throw new XIllegalOperation(this,oValue1,oValue2);
case GE: throw new XIllegalOperation(this,oValue1,oValue2);
case NE: throw new XIllegalOperation(this,oValue1,oValue2);
case EQ: throw new XIllegalOperation(this,oValue1,oValue2);
case AND: throw new XIllegalOperation(this,oValue1,oValue2);
case XOR: throw new XIllegalOperation(this,oValue1,oValue2);
case OR: throw new XIllegalOperation(this,oValue1,oValue2);
case LAND: throw new XIllegalOperation(this,oValue1,oValue2);
case LOR: throw new XIllegalOperation(this,oValue1,oValue2);
default: throw new XIllegalStatus(getPosition());
}
}
else {
System.out.println(oValue1.getClass()+" "+oValue2.getClass());
throw new XIllegalStatus(getPosition());
}
}
else if (oValue1 instanceof float[]) {
float fValue1 = ((float[])oValue1)[0];
if (oValue2 instanceof int[]) {
int dValue2 = ((int[])oValue2)[0];
/*
* REMARK: NE and EQ will be considdered illegal operations here
* because of the statistical probability of meeting the condition.
*/
switch (m_kBINToken) {
case POW: floatArrays[i][0] = (float)Math.pow(fValue1,dValue2); return floatArrays[i];
case MUL: floatArrays[i][0] = fValue1*dValue2; return floatArrays[i];
case SDIV: /* continue with next */
case DIV: floatArrays[i][0] = fValue1/dValue2; return floatArrays[i];
case MOD: throw new XIllegalOperation(this,oValue1,oValue2);
case ADD: floatArrays[i][0] = fValue1+dValue2; return floatArrays[i];
case SUB: floatArrays[i][0] = fValue1-dValue2; return floatArrays[i];
case LT: intArrays[i][0] = (fValue1 < dValue2)?1:0; return intArrays[i];
case GT: intArrays[i][0] = (fValue1 > dValue2)?1:0; return intArrays[i];
case LE: intArrays[i][0] = (fValue1 <= dValue2)?1:0; return intArrays[i];
case GE: intArrays[i][0] = (fValue1 >= dValue2)?1:0; return intArrays[i];
/*
* REMARK: NE and EQ will be considdered illegal operations here
* because of the statistical probability of meeting the condition.
*/
case NE: throw new XIllegalOperation(this,oValue1,oValue2);
case EQ: throw new XIllegalOperation(this,oValue1,oValue2);
case AND: throw new XIllegalOperation(this,oValue1,oValue2);
case XOR: throw new XIllegalOperation(this,oValue1,oValue2);
case OR: throw new XIllegalOperation(this,oValue1,oValue2);
case LAND: throw new XIllegalOperation(this,oValue1,oValue2);
case LOR: throw new XIllegalOperation(this,oValue1,oValue2);
default: throw new XIllegalStatus(getPosition());
}
}
else if (oValue2 instanceof float[]) {
float fValue2 = ((float[])oValue2)[0];
switch (m_kBINToken) {
case POW: floatArrays[i][0] = (float)Math.pow(fValue1,fValue2); return floatArrays[i];
case MUL: floatArrays[i][0] = fValue1*fValue2; return floatArrays[i];
case SDIV: /* continue with next */
case DIV: floatArrays[i][0] = fValue1/fValue2; return floatArrays[i];
case MOD: throw new XIllegalOperation(this,oValue1,oValue2);
case ADD: floatArrays[i][0] = fValue1+fValue2; return floatArrays[i];
case SUB: floatArrays[i][0] = fValue1-fValue2; return floatArrays[i];
case LT: intArrays[i][0] = (fValue1 < fValue2)?1:0; return intArrays[i];
case GT: intArrays[i][0] = (fValue1 > fValue2)?1:0; return intArrays[i];
case LE: intArrays[i][0] = (fValue1 <= fValue2)?1:0; return intArrays[i];
case GE: intArrays[i][0] = (fValue1 >= fValue2)?1:0; return intArrays[i];
/*
* REMARK: NE and EQ will be considdered illegal operations here
* because of the statistical probability of meeting the condition.
*/
case NE: throw new XIllegalOperation(this,oValue1,oValue2);
case EQ: throw new XIllegalOperation(this,oValue1,oValue2);
case AND: throw new XIllegalOperation(this,oValue1,oValue2);
case XOR: throw new XIllegalOperation(this,oValue1,oValue2);
case OR: throw new XIllegalOperation(this,oValue1,oValue2);
case LAND: throw new XIllegalOperation(this,oValue1,oValue2);
case LOR: throw new XIllegalOperation(this,oValue1,oValue2);
default: throw new XIllegalStatus(getPosition());
}
}
else if (oValue2 instanceof String) {
String sValue2 = (String)oValue2;
switch (m_kBINToken) {
case POW: throw new XIllegalOperation(this,oValue1,oValue2);
case MUL: throw new XIllegalOperation(this,oValue1,oValue2);
case SDIV: /* continue with next */
case DIV: throw new XIllegalOperation(this,oValue1,oValue2);
case MOD: throw new XIllegalOperation(this,oValue1,oValue2);
case ADD: return Float.toString(fValue1) + sValue2;
case SUB: throw new XIllegalOperation(this,oValue1,oValue2);
case LT: throw new XIllegalOperation(this,oValue1,oValue2);
case GT: throw new XIllegalOperation(this,oValue1,oValue2);
case LE: throw new XIllegalOperation(this,oValue1,oValue2);
case GE: throw new XIllegalOperation(this,oValue1,oValue2);
case NE: throw new XIllegalOperation(this,oValue1,oValue2);
case EQ: throw new XIllegalOperation(this,oValue1,oValue2);
case AND: throw new XIllegalOperation(this,oValue1,oValue2);
case XOR: throw new XIllegalOperation(this,oValue1,oValue2);
case OR: throw new XIllegalOperation(this,oValue1,oValue2);
case LAND: throw new XIllegalOperation(this,oValue1,oValue2);
case LOR: throw new XIllegalOperation(this,oValue1,oValue2);
default: throw new XIllegalStatus(getPosition());
}
}
else
throw new XIllegalStatus(getPosition());
}
else if (oValue1 instanceof String) {
String sValue1 = (String)oValue1;
if (oValue2 instanceof int[]) {
int dValue2 = ((int[])oValue2)[0];
switch (m_kBINToken) {
case POW: throw new XIllegalOperation(this,oValue1,oValue2);
case MUL: {
String sValue = sValue1;
if (dValue2 <= 0) throw new XIllegalOperation(this,oValue1,oValue2);
for (int iCount = 1; iCount < dValue2; iCount++) {
sValue = sValue + sValue1;
}
return sValue;
}
case SDIV: /* continue with next */
case DIV: throw new XIllegalOperation(this,oValue1,oValue2);
case MOD: throw new XIllegalOperation(this,oValue1,oValue2);
case ADD: return sValue1 + Integer.toString(dValue2);
case SUB: throw new XIllegalOperation(this,oValue1,oValue2);
case LT: throw new XIllegalOperation(this,oValue1,oValue2);
case GT: throw new XIllegalOperation(this,oValue1,oValue2);
case LE: throw new XIllegalOperation(this,oValue1,oValue2);
case GE: throw new XIllegalOperation(this,oValue1,oValue2);
case NE: throw new XIllegalOperation(this,oValue1,oValue2);
case EQ: throw new XIllegalOperation(this,oValue1,oValue2);
case AND: throw new XIllegalOperation(this,oValue1,oValue2);
case XOR: throw new XIllegalOperation(this,oValue1,oValue2);
case OR: throw new XIllegalOperation(this,oValue1,oValue2);
case LAND: throw new XIllegalOperation(this,oValue1,oValue2);
case LOR: throw new XIllegalOperation(this,oValue1,oValue2);
default: throw new XIllegalStatus(getPosition());
}
}
else if (oValue2 instanceof float[]) {
float fValue2 = ((float[])oValue2)[0];
switch (m_kBINToken) {
case POW: throw new XIllegalOperation(this,oValue1,oValue2);
case MUL: throw new XIllegalOperation(this,oValue1,oValue2);
case SDIV: /* continue with next */
case DIV: throw new XIllegalOperation(this,oValue1,oValue2);
case MOD: throw new XIllegalOperation(this,oValue1,oValue2);
case ADD: return sValue1 + Float.toString(fValue2);
case SUB: throw new XIllegalOperation(this,oValue1,oValue2);
case LT: throw new XIllegalOperation(this,oValue1,oValue2);
case GT: throw new XIllegalOperation(this,oValue1,oValue2);
case LE: throw new XIllegalOperation(this,oValue1,oValue2);
case GE: throw new XIllegalOperation(this,oValue1,oValue2);
case NE: throw new XIllegalOperation(this,oValue1,oValue2);
case EQ: throw new XIllegalOperation(this,oValue1,oValue2);
case AND: throw new XIllegalOperation(this,oValue1,oValue2);
case XOR: throw new XIllegalOperation(this,oValue1,oValue2);
case OR: throw new XIllegalOperation(this,oValue1,oValue2);
case LAND: throw new XIllegalOperation(this,oValue1,oValue2);
case LOR: throw new XIllegalOperation(this,oValue1,oValue2);
default: throw new XIllegalStatus(getPosition());
}
}
else if (oValue2 instanceof String) {
String sValue2 = (String)oValue2;
switch (m_kBINToken) {
case POW: throw new XIllegalOperation(this,oValue1,oValue2);
case MUL: throw new XIllegalOperation(this,oValue1,oValue2);
case SDIV: /* continue with next */
case DIV: throw new XIllegalOperation(this,oValue1,oValue2);
case MOD: throw new XIllegalOperation(this,oValue1,oValue2);
case ADD: return sValue1 + sValue2;
case SUB: throw new XIllegalOperation(this,oValue1,oValue2);
case LT: intArrays[i][0] = sValue1.compareTo(sValue2) < 0 ?1:0; return intArrays[i];
case GT: intArrays[i][0] = sValue1.compareTo(sValue2) > 0 ?1:0; return intArrays[i];
case LE: intArrays[i][0] = sValue1.compareTo(sValue2) <= 0 ?1:0; return intArrays[i];
case GE: intArrays[i][0] = sValue1.compareTo(sValue2) >= 0 ?1:0; return intArrays[i];
case NE: intArrays[i][0] = sValue1.equals(sValue2)?0:1; return intArrays[i];
case EQ: intArrays[i][0] = sValue1.equals(sValue2)?1:0; return intArrays[i];
case AND: throw new XIllegalOperation(this,oValue1,oValue2);
case XOR: throw new XIllegalOperation(this,oValue1,oValue2);
case OR: throw new XIllegalOperation(this,oValue1,oValue2);
case LAND: throw new XIllegalOperation(this,oValue1,oValue2);
case LOR: throw new XIllegalOperation(this,oValue1,oValue2);
default: throw new XIllegalStatus(getPosition());
}
}
else
throw new XIllegalStatus(getPosition());
}
else
throw new XIllegalStatus(getPosition());
/*
* The code should never reach here. However, the JDK currently does not allow
* to write unreacheable code, so there is no way to throw an exception. Luckely
* in this case a return value is expected, so if by any uncatched state the code
* could be reached there will be a warning at compile time.
*/
/* return null; */
}
}