Reputation: 997
So I've spent most of the day Googling and StackExchanging for answers or guidance and I've given up. I have to ask the following:
I want to make a Java application that asks for the user to enter an expression similar to this:
t>>7|t|t>>6
Let's assume that this is then stored as a String. What I want is to convert this String into an expression where t
becomes a variable and >>
and |
become operators. Basically I would like to figure out how implement this http://www.redcode.nl/blog/2011/12/bytebeat-algorithmic-symphonies/ but somehow pass user input to private static int f(int t)
instead of hard coding the expression.
I've been reading a bit about ScriptEngineManager and using JavaScript but I don't know if that's the way to go.
Anyway, this is just for personal education and entertainment. Thanks in advance.
Upvotes: 0
Views: 282
Reputation: 9295
You can do this using javassist library. Download ithe library from http://sourceforge.net/projects/jboss/files/Javassist/3.16.1-GA/ and add it your project.
//ExpressionEvaluator.java
public class ExpressionEvaluator {
}
//AudioPump.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.Loader;
import javassist.NotFoundException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
public class AudioPump {
private static String expression;
public static void main(String[] args) throws Exception {
System.out.print("Enter expression(use t as variable):");
BufferedReader consoleReader = new BufferedReader(
new InputStreamReader(System.in));
expression = consoleReader.readLine();
generateMethod(expression);
AudioFormat format = new AudioFormat(8000f, 8, 1, false, false);
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
SourceDataLine soundLine = (SourceDataLine) AudioSystem.getLine(info);
soundLine.open(format, 32000);
soundLine.start();
byte[] buffer = new byte[8];
int t = 0;
while (true) {
for (int n = 0; n < buffer.length; n++) {
buffer[n] = (byte) invokeF(t++);
}
soundLine.write(buffer, 0, buffer.length);
}
}
private static byte invokeF(int i) {
java.lang.reflect.Method method = null;
try {
ClassPool pool = ClassPool.getDefault();
Loader cl = new Loader(pool);
Class expressionEvaluatorClass = cl.loadClass("ExpressionEvaluator");
method = expressionEvaluatorClass.getMethod("f", Integer.TYPE);
} catch (SecurityException e) {
e.printStackTrace();System.exit(-1);
} catch (NoSuchMethodException e) {
e.printStackTrace();System.exit(-1);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();System.exit(-1);
}
try {
return (Byte) method.invoke(null, i);
} catch (IllegalArgumentException e) {
e.printStackTrace();System.exit(-1);
} catch (IllegalAccessException e) {
e.printStackTrace();System.exit(-1);
} catch (InvocationTargetException e) {
e.printStackTrace();System.exit(-1);
}
return 0;
}
private static void generateMethod(String expression2) {
ClassPool pool = ClassPool.getDefault();
try {
CtClass pt = pool.get("ExpressionEvaluator");
String methodString = "public static byte f(int t) { return (byte)(" + expression2 + ");}";
System.out.println(methodString);
CtMethod m = CtNewMethod.make(methodString, pt);
pt.addMethod(m);
pt.writeFile();
} catch (NotFoundException e) {
e.printStackTrace();System.exit(-1);
} catch (CannotCompileException e) {
e.printStackTrace();System.exit(-1);
} catch (IOException e) {
e.printStackTrace();System.exit(-1);
}
}
// return (t*(t>>5|t>>8))>>(t>>16);
// return t*(((t>>12)|(t>>8))&(63&(t>>4)));
}
Here we are dynamically generating a method using user provided expression and adding it to ExpressionEvaluator class using Javassist.
Hope it helps.
Upvotes: 1