6

I am trying to evaluate the following from a string

boolean value = evaluate("false || true && true && false || true");

I need to get a boolean value of true for this one.
Any ideas on how to solve this problem in the most efficient way?

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
Adnan
  • 25,882
  • 18
  • 81
  • 110
  • 3
    look at the question: http://stackoverflow.com/questions/2605032/using-eval-in-java – Thierry Jun 04 '10 at 13:10
  • thanx Thierry, will take a look now. – Adnan Jun 04 '10 at 13:11
  • @Thierry I think this is not the most efficient way to load entire intepreter – ant Jun 04 '10 at 13:16
  • don't use the accepted answer method. Look at the next one (in term of vote) i think it summarizes well your possibilities, but yes it do not answer directly your question ;-) – Thierry Jun 04 '10 at 13:18
  • Can your string contain parentheses, and other operators such as ^ or ! ? – JRL Jun 04 '10 at 14:06

4 Answers4

7
String value = ("false || true && true && false || true");
boolean result = false;
for (String conj : value.split("\\|\\|")) {
    boolean b = true;
    for (String litteral : conj.split("&&"))
        b &= Boolean.parseBoolean(litteral.trim());
    result |= b;
}
System.out.println(result); // prints true
aioobe
  • 413,195
  • 112
  • 811
  • 826
  • 1
    thank you @aioobe, this is good as no 3rd party lib is needed. – Adnan Jun 04 '10 at 13:29
  • 2
    you could optimize the outer loop by breaking out of it (using a while instead of a for, or using a break at the end of the for) as soon as result is true: there is no way it can become false again – Thierry Jun 04 '10 at 13:36
  • @Thierry, Sure. Doing a split using a regular expression is not the most efficient solution either :P – aioobe Jun 04 '10 at 13:40
  • 1
    @aioobe that does |= b mean ? – ant Jun 04 '10 at 13:42
  • @c0mrade `result = result | b`... similar to `i += 5` but with or instead of plus. – aioobe Jun 04 '10 at 13:47
  • @aioobe Yes I assumed that was the full syntax, but what does `result = result | b` mean? like i+=5 adds 5 with i and stores it in i what does this or do – ant Jun 04 '10 at 13:51
  • @c0mrade: `|` is interpreted as *or*. `true|true`, `true|false` and `false|true` evaluate to `true` and `false|false` evaluate to `false`. – aioobe Jun 04 '10 at 13:56
  • What about parentheses, and other operators such as ^ and ! ? – JRL Jun 04 '10 at 14:05
  • Well, then the situation gets a bit uglier, and I would go for a parser generator. However there are a few tricks: For parethesis, you can evaluate them from the inner ones out, by looking for the first `)`, and go back to the closest `(`, evaluate that sub-expression, and iterate. For other operators, you could simply split on those too. – aioobe Jun 04 '10 at 14:12
1

If the only operators are && and ||, then I think this will work:

  static boolean eval(String str) {
    String s = str.replaceAll("\\s|\\|\\|false|false\\|\\|", "");
    return !s.contains("false") || s.contains("||true");
  }

For more complicated expressions, I found this library just for that. Don't know how efficient it is though.

JRL
  • 76,767
  • 18
  • 98
  • 146
0

You'll need a small boolean expressions grammar. A bit of recursive parsing should do the trick.

If you don't know how to write such a parser, you may use JavaCC or something similar.

cadrian
  • 7,332
  • 2
  • 33
  • 42
0

there are parsergenerators available for which you can define a grammar.

But if you only got || and && as operators and true and false as values you can easily do this by yourself, by implmenting a very simple finite state machine:

1.) Split the string into the tokens

2.) parse the left most value by using Boolean.parseBoolean(token) and safe it's value in some instance variable (your state)

3.) combine your instance variable with the next boolean token using the given operator

4.) Repeat step3 until you finished through the whole string

This seems to work although i havent thorougly tested it :)

public class BooleanFSParser {

    private boolean parse(String data) {
        String[] tokens=data.split("\\s");
        boolean state=Boolean.parseBoolean(tokens[0]);
        for (int i=1;i<(tokens.length / 2) + 1;i=i+2){
            if (tokens[i].equals("&&")){
                state=state && Boolean.parseBoolean(tokens[i+1]);
            }else{
                state=state || Boolean.parseBoolean(tokens[i+1]);
            }
        }
        return state;
    }

    public static void main(String[] args) {
        BooleanFSParser parser = new BooleanFSParser();
        boolean val = parser.parse("true && true || false");
        System.out.println(String.valueOf(val));
    }
}

thats should give you a cirrectly parsed value, but it will get a bit more complex if you allow brackets for example ;)

have fun and check here for the theory Finite-state_machine

fasseg
  • 17,504
  • 8
  • 62
  • 73