/* * 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; */ } }