Search code examples
javafunctionparsingdefined

Java - parse user defined functions


I am working on a program, where I want users to define a simple functions like randomInt(0,10) or randomString(10) instead of static arguments. What is the best way to parse and process such functions ?

I have not found any examples of such problem, the parser does not have to be ultra-efficient, it will not be called often, but mainly I want to focus on good code readability and scalability.

Example of user input:

"This is user randomString(5) and he is randomInt(18,60) years old!"

Expected output(s):

"This is user phiob and he is 45 years old!"

"This is user sdfrt and he is 30 years old!"


Solution

  • One option is to use Spring SPEL. But it forces you to change the expression a little and use Spring library:

    The expression can look like this:

    'This is user ' + randomString(5) + ' and he is ' + randomInt(18,60) + ' years old!'

    or this:

    This is user #{randomString(5)} and he is #{randomInt(18,60)} years old!

    or you can implement your own by having a custom TemplateParserContext.

    And here is the code:

    import org.springframework.expression.Expression;
    import org.springframework.expression.ExpressionParser;
    import org.springframework.expression.spel.standard.SpelExpressionParser;
    import org.springframework.expression.spel.support.StandardEvaluationContext;
    
    public class SomeTest {
    
            @Test
            public void test() {
                ExpressionParser parser = new SpelExpressionParser();
    
                Expression exp = parser.parseExpression(
                    "This is user #{randomString(5)} and he is #{randomInt(18,60)} years old!", 
                    new TemplateParserContext() );
    
                //alternative
                //Expression exp = parser.parseExpression(
                //        "'This is user ' + randomString(5) + ' and he is ' + randomInt(18,60) + ' years old!'");
                //    String message = (String) exp.getValue( new StandardEvaluationContext(this) );
    
    
                String message = (String) exp.getValue( new StandardEvaluationContext(this) );
            }
    
            public String randomString(int i) {
                return "rs-" + i;
            }
    
            public String randomInt(int i, int j) {
                return "ri-" + i + ":" + "j";
            }
    
        }
    

    Whatever object you pass to StandardEvaluationContext should have those methods. I put them in the same class that also runs the expression.