2009-09-15 22 views
1

我需要在正則表達式中標識(可能嵌套的)捕獲組並創建一棵樹。特定的目標是Java-1.6,我最好喜歡Java代碼。一個簡單的例子是:將正則表達式中的捕獲組解析爲樹的代碼

「(一(B | C)d(E(F * G))H)」

這將被解析以

"a(b|c)d(e(f*g))h" 
... "b|c" 
... "e(f*g)" 
    ... "f*g" 

溶液應理想地帳戶用於計數表達式,量詞等以及轉義級別。但是,如果不容易找到更簡單的方法就足夠了,因爲我們可以限制使用的語法。

編輯。澄清。我想解析正則表達式字符串本身。爲此,我需要知道BNF或Java 1.6正則表達式的等價物。我希望有人已經這樣做了。

結果的副產品是該過程將測試正則表達式的有效性。

回答

1

考慮加緊實際語法/詞法分析器: http://www.antlr.org/wiki/display/ANTLR3/FAQ+-+Getting+Started

看起來比較複雜,但如果你的語言是相當簡單的,這是相當簡單的。如果不是這樣,在正則表達式中執行它可能會讓你的生活變得很糟糕:)

+0

看到@anthony。我澄清了這個問題 – 2009-09-15 22:56:45

0

我想出了一個使用XML工具(XOM,http://www.xom.nu)來保存樹的部分解決方案。首先是代碼,然後是一個示例解析。首先,轉義字符(\,(和))被去掉(這裏我使用BS,LB和RB),然後將其餘的括號轉換爲XML標記,然後解析XML並重新轉義字符。還需要一個BNF for Java 1.6正則表達式量詞,如?:,{d,d}等等。

public static Element parseRegex(String regex) throws Exception { 
    regex = regex.replaceAll("\\\\", "BS"); 
    regex.replaceAll("BS\\(", "LB"); 
    regex.replaceAll("BS\\)", "RB"); 
    regex = regex.replaceAll("\\(", "<bracket>"); 
    regex.replaceAll("\\)", "</bracket>"); 
    Element regexX = new Builder().build(new StringReader(
     "<regex>"+regex+"</regex>")).getRootElement(); 
    extractCaptureGroupContent(regexX); 
    return regexX; 
} 

private static String extractCaptureGroupContent(Element regexX) { 
    StringBuilder sb = new StringBuilder(); 
    for (int i = 0; i < regexX.getChildCount(); i++) { 
     Node childNode = regexX.getChild(i); 
     if (childNode instanceof Text) { 
      Text t = (Text)childNode; 
      String s = t.getValue(); 
      s = s.replaceAll("BS", "\\\\").replaceAll("LB", 
         "\\(").replaceAll("RB", "\\)"); 
      t.setValue(s); 
      sb.append(s); 
     } else { 
      sb.append("("+extractCaptureGroupContent((Element)childNode)+")"); 
     } 
    } 
    String capture = sb.toString(); 
    regexX.addAttribute(new Attribute("capture", capture)); 
    return capture; 
} 

例如:

@Test 
public void testParseRegex2() throws Exception { 
    String regex = "(.*(\\(b\\))c(d(e)))"; 
    Element regexElement = ParserUtil.parseRegex(regex); 
    CMLUtil.debug(regexElement, "x"); 
} 

給出:

​​