2014-09-01 83 views
2

如何驗證如果碼塊,如在一個構建體:檢查代碼塊是否在Java中正確嵌套?

{ 
    // Any amount of characters that aren't '{' or '}' 
} 

正確嵌套,優選具有正則表達式?

{} { 
    {} {} 
} // Properly nested 
{{ 
    {{}} 
} {} // Not properly nested 

As referred to from this thread,方法,如遞歸和平衡組不能在這裏適用,因爲regular expression constructs中不存在Java Pattern

+6

我不會使用這類問題的正則表達式。我可能會使用堆棧。 – 2014-09-01 15:02:34

+0

@HovercraftFullOfEels用戶輸入是一個String。在這種情況下有沒有辦法使用堆棧? – Unihedron 2014-09-01 15:04:05

+0

是的。我不是這方面的專家,但是不存在這樣的解析器嗎? – 2014-09-01 15:05:11

回答

3

爲什麼使用正則表達式?我建議構建你自己的解析器。這樣的事情:

public static boolean isProperlyNested(String toTest) { 
    int countOpen = 0; 
    for (char c : toTest.toCharArray()) { 
     if (c == '{') { 
      countOpen++; 
     } else if (c == '}') { 
      countOpen--; 
      if (countOpen < 0) return false; 
     } 
    } 
    return countOpen == 0; 
} 
+1

請注意,這是一個簡化。例如,如何處理一段代碼,其中在評論中隱藏了打開或關閉大括號;那就是順便說一句堆棧或狀態機進來的地方。 – 2014-09-01 15:17:12

+0

@MarkRotteveel堆棧實際上並沒有更好的工作。只需包含一些布爾值,可以切換註釋/字符串/字符/等,如果其中一個爲真,則不要更改計數。 – Justin 2014-09-01 15:23:49

+0

對於這個特定的例子,堆棧可能是矯枉過正的(但是如果我想跟蹤平衡括號**和**括號),儘管我會盡快選擇枚舉而不是一組布爾值來跟蹤解析器的當前狀態(我實際上只是爲Jaybird做了這個工作,它允許將狀態轉換到狀態:http://sourceforge.net/p/firebird/code/HEAD/tree/client-java/trunk/src/main/ org/firebirdsql/jdbc/escape/FBEscapedParser.java#l364)。 – 2014-09-01 15:32:55

0

我可以解決這個使用兩個步驟,一個循環:

{ 
    String str1 = "{} {\n" + 
        " {} {}\n" + 
        "} // Properly nested", 
      str2 = "{{\n" + 
        " {{}}\n" + 
        "} {} // Not properly nested"; 
    final Pattern pattern = Pattern.compile("\\Q{}\\E"); 

    Matcher matcher = pattern.matcher(str1.replaceAll("[^{}]", "")); 
    while (matcher.find()) 
     matcher = pattern.matcher(str1 = matcher.replaceAll("")); 
    System.out.println(str1.isEmpty()); 

    matcher = pattern.matcher(str2.replaceAll("[^{}]", "")); 
    while (matcher.find()) 
     matcher = pattern.matcher(str2 = matcher.replaceAll("")); 
    System.out.println(str2.isEmpty()); 
} 

Here is an online code demoDemo與我在此處編寫的代碼略有不同,以便顯示原始字符串方向。