Roberto
Roberto

Reputation: 997

Converting a string from user input to an expression

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

Answers (2)

krishnakumarp
krishnakumarp

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

Ivan
Ivan

Reputation: 2262

It sounds like language recognition job. Have you tried antlr. As far as I know it's used for complex parsing in solr, hibernate, etc.

Upvotes: 0

Related Questions