2016-05-23 480 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)。