/*
* $Id: BulletmlUtil.java,v 1.3 2001/06/03 00:19:12 ChoK Exp $
*
* Copyright 2001 Kenta Cho. All rights reserved.
*/
package jp.gr.java_conf.abagames.bulletml_demo;
import java.util.Hashtable;
/**
* Utility class for BulletML.
*
* @version $Revision: 1.3 $
*/
public class BulletmlUtil
{
private static Hashtable<String, Expression> expressions = new Hashtable<String, Expression>();
private static char[] expChr;
private static float rank = 0.5f;
public static int getIntValue(String v, float[] prms)
{
return (int) evalExpression(v, prms);
}
public static float getFloatValue(String v, float[] prms)
{
return evalExpression(v, prms);
}
public static void setRank(float rk)
{
rank = rk;
}
public static float getRank()
{
return rank;
}
private static void evalFloatValue(Expression ep, int stIdx, int lgt, float sign)
{
if (expChr[stIdx] == '$')
{
String label = new String(expChr, stIdx + 1, lgt - 1);
if (label.equals("rand"))
{
//return rnd.nextFloat();
ep.push(0, Expression.STACK_RAND);
}
else if (label.equals("rank"))
{
//return rank;
ep.push(0, Expression.STACK_RANK);
}
else
{
int idx;
try
{
idx = new Integer(label).intValue() - 1;
}
catch (NumberFormatException e)
{
//return 0;
ep.push(0, Expression.STACK_NUM);
return;
}
//return prms[idx];
ep.push(0, Expression.STACK_VARIABLE + idx);
}
}
else
{
try
{
//return new Float(new String(expChr, stIdx, lgt)).floatValue();
ep.push(new Float(new String(expChr, stIdx, lgt)).floatValue() * sign, Expression.STACK_NUM);
}
catch (NumberFormatException e)
{
//return 0;
ep.push(0, Expression.STACK_NUM);
}
}
}
private static void evalExpPart(Expression ep, int stIdx, int edIdx)
{
int[] op = new int[] { -1, -1 };
while ((expChr[stIdx] == '(') && (expChr[edIdx - 1] == ')'))
{
stIdx++;
edIdx--;
}
for (int i = edIdx - 1; i >= stIdx; i--)
{
char c = expChr[i];
if (c == ')')
{
do
{
i--;
}
while (expChr[i] != '(');
}
else if ((op[0] < 0) && ((c == '*') || (c == '/') || (c == '%')))
{
op[0] = i;
}
else if ((c == '+') || (c == '-'))
{
op[1] = i;
break;
}
}
if (op[1] < 0)
{
if (op[0] < 0)
{
//return evalFloatValue(stIdx, edIdx-stIdx);
evalFloatValue(ep, stIdx, edIdx - stIdx, 1);
}
else
{
switch (expChr[op[0]])
{
case '*':
//return evalExpPart(stIdx, op[0]) * evalExpPart(op[0]+1, edIdx);
evalExpPart(ep, stIdx, op[0]);
evalExpPart(ep, op[0] + 1, edIdx);
ep.setOperator(Expression.MULTIPLE);
break;
case '/':
//return evalExpPart(stIdx, op[0]) / evalExpPart(op[0]+1, edIdx);
evalExpPart(ep, stIdx, op[0]);
evalExpPart(ep, op[0] + 1, edIdx);
ep.setOperator(Expression.DIVISION);
break;
case '%':
//return evalExpPart(stIdx, op[0]) % evalExpPart(op[0]+1, edIdx);
evalExpPart(ep, stIdx, op[0]);
evalExpPart(ep, op[0] + 1, edIdx);
ep.setOperator(Expression.MODULO);
break;
}
}
}
else
{
if (op[1] == stIdx)
{
switch (expChr[op[1]])
{
case '-':
//return -evalFloatValue(stIdx+1, edIdx-stIdx-1);
evalFloatValue(ep, stIdx + 1, edIdx - stIdx - 1, -1);
break;
case '+':
//return evalFloatValue(stIdx+1, edIdx-stIdx-1);
evalFloatValue(ep, stIdx + 1, edIdx - stIdx - 1, 1);
break;
}
}
else
{
switch (expChr[op[1]])
{
case '+':
//return evalExpPart(stIdx, op[1]) + evalExpPart(op[1]+1, edIdx);
evalExpPart(ep, stIdx, op[1]);
evalExpPart(ep, op[1] + 1, edIdx);
ep.setOperator(Expression.PLUS);
break;
case '-':
//return evalExpPart(stIdx, op[1]) - evalExpPart(op[1]+1, edIdx);
evalExpPart(ep, stIdx, op[1]);
evalExpPart(ep, op[1] + 1, edIdx);
ep.setOperator(Expression.MINUS);
break;
}
}
}
}
public static float evalExpression(String exp, float[] p)
{
Expression ep = (Expression) expressions.get(exp);
if (ep == null)
{
expChr = new char[exp.length()];
int ecIdx = 0;
boolean skip = false;
StringBuffer buf = new StringBuffer(exp);
int depth = 0;
boolean balance = true;
char ch;
for (int i = 0; i < buf.length(); i++)
{
ch = buf.charAt(i);
switch (ch)
{
case ' ':
case '\n':
skip = true;
break;
case ')':
depth--;
if (depth < 0)
{
balance = false;
}
break;
case '(':
depth++;
break;
}
if (skip)
{
skip = false;
}
else
{
expChr[ecIdx] = ch;
ecIdx++;
}
}
if ((depth != 0) || !balance)
{
return 0;
}
ep = new Expression();
evalExpPart(ep, 0, ecIdx);
expressions.put(exp, ep);
}
return ep.calc(p);
}
}