2016-05-23 244 views
0

要求是前缀运算符将像AND(a,b)OR(a,b)NOT(a)到中缀,这样的:(a && b)(a || b)(!(a))前缀中缀使用Java

我已经写了下面的代码,但它的作品,如果表达ISN”太复杂了。我能够转换: AND(OR(1<2, OR(3<4, 1<2, FUNC(5<6, 2<3))), 2<3)
(((1<2 || ((3<4 || (1<2 || FUNC(5<6, 2<3))))))&& 2<3)) 除了那些额外的括号外,这个表达式是可以接受的。但是当我运行这个表达式的代码有点复杂时,它里面有太多的函数和括号,或者失败或者返回表达式。例如这个表达式: AND(OR((NOT(A != null)), OR(FUNC(3<4, 1==1), 1<2, FUNC(5<6, 2<3))), 2<3)

它应该忽略除了And/Or/Not之外的其他函数。例如FUNC(5<6, 2<3)应输出为FUNC(5<6, 2<3),正如我在上面的例子中提到的那样。

代码:

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; 
    } 
} 
+0

[前缀中缀转换算法与图]可能重复(http://stackoverflow.com/questions/4374388/prefix-to-infix-conversion-algorithm-with-figure) –

+0

@JulienLopez,谢谢,但我检查发布Q之前的网站。他正在使用Stack。我不是。 – Enthusiastic

+0

@Enthusiastic尽管你的代码没有明确的引用栈,但你仍然通过递归来使用它。 – dasblinkenlight

回答

0

与实现的问题是,它是依赖于确定的子表达式的结束位置不必解析表达的能力。这不起作用 - 当你调用sExpr.lastIndexOf(")")时,你会得到整体表达式的结束,而不是你想要递归解析的嵌套子表达式。同样地,当另一个表达式嵌套在当前正在解析的表达式中时,可能不会在正确位置分解表达式。

编写递归下降解析器(如果你不知道你正在实现的是什么被调用)的诀窍是保持你正在读取字符串的位置。这可以通过几种方式来完成 - 例如,您可以不通过String sExpr,而是通过Scanner以及sExpr字符串。这样,每次递归调用将完全按照需要进行读取,并让下一级继续停止。

配置一个Scanner这样的:

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

现在,您的转换方法可以调用next通过扫描仪,:

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

从扫描仪获得下一个标记可能是这样一种方法,每次需要下一个令牌时都会得到下一个令牌。当您的递归方法返回时,Scanner已正确定位,以便先前的调用级别取下一个标记(demo)。