0

Requirement is to convert Prefix operators like AND(a,b), OR(a,b) or NOT(a) to infix, like this: (a && b), (a || b), (!(a))

I've written below code, but it works if the expression isn't too complicated. I was able to convert: AND(OR(1<2, OR(3<4, 1<2, FUNC(5<6, 2<3))), 2<3) to
(((1<2 || ((3<4 || (1<2 || FUNC(5<6, 2<3))))))&& 2<3)) except those extra brackets, this expression is acceptable. But when I run this code for expression a little complicated, that have too many functions and brackets within it either fails or returns the expression as is. For example this expr: AND(OR((NOT(A != null)), OR(FUNC(3<4, 1==1), 1<2, FUNC(5<6, 2<3))), 2<3)

It should ignore other functions apart from And/Or/Not. For example FUNC(5<6, 2<3) should be output as FUNC(5<6, 2<3) as I mentioned in the above example.

Code:

  public String ConvertToJS(String sExpr, String Operator)
{
    //String subExpr[] = sExpr.split(",");
    sExpr = sExpr.trim();
    String resolved = "";
    String resolved2 = "";
    if(sExpr.indexOf(",") != -1 || sExpr.indexOf("(") != -1)
    {
        if((sExpr.indexOf(",") != -1 && sExpr.indexOf("(") != -1 && sExpr.indexOf(",") < sExpr.indexOf("(")) || sExpr.indexOf("(") == -1)
        {
            if(sExpr.indexOf(",") > 0)
            {
                if("AND".equalsIgnoreCase(Operator))
                    return "(" + sExpr.substring(0, sExpr.indexOf(",")) + " && " + ConvertToJS(sExpr.substring(sExpr.indexOf(",")+1, sExpr.length()), Operator) + ")";
                else if("OR".equalsIgnoreCase(Operator))
                    return "(" + sExpr.substring(0, sExpr.indexOf(",")) + " || " + ConvertToJS(sExpr.substring(sExpr.indexOf(",")+1, sExpr.length()), Operator) + ")";
                else
                    return sExpr;
            }
            else
            {
                if("AND".equalsIgnoreCase(Operator))
                    return " && " + ConvertToJS(sExpr.substring(sExpr.indexOf(",")+1, sExpr.length()), Operator) + ")";
                else if("OR".equalsIgnoreCase(Operator))
                    return " || " + ConvertToJS(sExpr.substring(sExpr.indexOf(",")+1, sExpr.length()), Operator) + ")";
                else
                    return sExpr;
            }
        }
        else
        {
            if(sExpr.indexOf("(") < 2)
            {
                resolved = sExpr.substring(0, sExpr.indexOf("(")) + "(" + ConvertToJS(sExpr.substring(sExpr.indexOf("(")+1, sExpr.lastIndexOf(")")), "") + ")";
                if(sExpr.lastIndexOf(")")< sExpr.length()-1)
                    resolved += ConvertToJS(sExpr.substring(sExpr.lastIndexOf(")") + 1), Operator);

                return resolved;
            }
            else if(sExpr.indexOf("(") == 2)
            {
                if(sExpr.substring(0, sExpr.indexOf("(")).equalsIgnoreCase("OR"))
                {
                    resolved = "(" + ConvertToJS(sExpr.substring(sExpr.indexOf("(")+1, sExpr.lastIndexOf(")")), "OR") + ")";
                    if(sExpr.lastIndexOf(")")< sExpr.length()-1)
                        resolved += ConvertToJS(sExpr.substring(sExpr.lastIndexOf(")") + 1), Operator);

                    return resolved;
                }
                else
                {
                    resolved = sExpr.substring(0, sExpr.indexOf("(")) + "(" + ConvertToJS(sExpr.substring(sExpr.indexOf("(")+1, sExpr.lastIndexOf(")")), "") + ")";
                    if(sExpr.lastIndexOf(")")< sExpr.length()-1)
                        resolved += ConvertToJS(sExpr.substring(sExpr.lastIndexOf(")") + 1), Operator);

                    return resolved;
                }
            }

            else if(sExpr.indexOf("(") == 3)
            {
                if(sExpr.substring(0, sExpr.indexOf("(")).equalsIgnoreCase("AND"))
                {
                    resolved = "(" + ConvertToJS(sExpr.substring(sExpr.indexOf("(")+1, sExpr.lastIndexOf(")")), "AND") + ")";
                    if(sExpr.lastIndexOf(")")< sExpr.length()-1)
                        resolved += ConvertToJS(sExpr.substring(sExpr.lastIndexOf(")") + 1), Operator);

                    return resolved;
                }
                else if(sExpr.substring(0, sExpr.indexOf("(")).equalsIgnoreCase("NOT"))
                {
                    resolved = "(" + ConvertToJS(sExpr.substring(sExpr.indexOf("(")+1, sExpr.lastIndexOf(")")), "NOT") + ")";
                    if(sExpr.lastIndexOf(")")< sExpr.length()-1)
                        resolved += ConvertToJS(sExpr.substring(sExpr.lastIndexOf(")") + 1), Operator);

                    return resolved;
                }
                else
                {
                    resolved = sExpr.substring(0, sExpr.indexOf("(")) + "(" + ConvertToJS(sExpr.substring(sExpr.indexOf("(")+1, sExpr.lastIndexOf(")")), "") + ")";
                    if(sExpr.lastIndexOf(")")< sExpr.length()-1)
                        resolved += ConvertToJS(sExpr.substring(sExpr.lastIndexOf(")") + 1), Operator);

                    return resolved;
                }
            }

            else
            {
                resolved = sExpr.substring(0, sExpr.indexOf("(")) + "(" + ConvertToJS(sExpr.substring(sExpr.indexOf("(")+1, sExpr.lastIndexOf(")")), "") + ")";
                if(sExpr.lastIndexOf(")")< sExpr.length()-1)
                        resolved += ConvertToJS(sExpr.substring(sExpr.lastIndexOf(")") + 1), Operator);

                    return resolved;
            }

        }
    }
    else
    {
        if("NOT".equalsIgnoreCase(Operator))
            return " !(" + sExpr + ") ";
        else
            return sExpr;
    }
}
Enthusiastic
  • 549
  • 4
  • 8
  • 23
  • Possible duplicate of [Prefix to Infix Conversion Algorithm with figure](http://stackoverflow.com/questions/4374388/prefix-to-infix-conversion-algorithm-with-figure) – Julien Lopez May 23 '16 at 11:33
  • @JulienLopez, thanks but I checked the site before posting Q. He's using Stack. and I'm not. – Enthusiastic May 23 '16 at 13:30
  • @Enthusiastic Alshough your code does not have an explicit reference to stack, you are still using it through recursion. – Sergey Kalinichenko May 23 '16 at 13:36

1 Answers1

0

The problem with your implementation is that it is relying on the ability to determine the end position of subexpression without parsing the expression. This does not work - when you call sExpr.lastIndexOf(")") you get the end of overall expression, not the nested subexpression that you want to parse recursively. Similarly, commas that you get with sExpr.indexOf(",") may not be breaking up the expression in the right spot when another expression is nested inside the one you are currently parsing.

The trick to writing recursive descent parsers (in case you didn't know what the thing you are implementing is called) is to keep around a position at which you are currently reading the string. This can be done in several ways - for example, instead of passing a String sExpr, you can pass Scanner with the sExpr string inside. This way each recursive invocation will read exactly as much as it needs, and let the next level up continue where it stopped.

Configure a Scanner like this:

Scanner scanner = new Scanner(s);
scanner.useDelimiter("\\s|\\b|(?<=[()])");

A method to obtain next token from the scanner may look like this:

static String next(Scanner scanner) {
    String tok;
    do {
        tok = scanner.next();
    } while (scanner.hasNext() && tok.trim().length() == 0);
    return tok;
}

Now your conversion method can call next passing the scanner, and get the next token each time that it needs one. When your recursive method returns, the Scanner is properly positioned for the prior invocation level to take the next token (demo).

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523