2012-05-04 49 views
7

我做一些簡單的RTF文本解析,我需要糾正的國際空間站。鑑於以下字符串:字符串轉換爲樹表示與規則

{aaaaaaa\}aaaa\{aaaaa{bbbbbbbb{ccccc\{cccc}bbb{eeeee}{{gggg}ffff}bbbbbb}aaaaa} 

其中:

\ means ignore next character 
{ means expand 
} means collapse up to parent 

在字符串中的任何點的狀態可能會被除了在封閉的標籤字符的任意一個字符的影響。例如{} GGGG不會FFFF但AAAAAAA} AAA影響..會影響bbbb, ccc, eee, ggg, fff等。

由此我們可以分割上述只是有意義塊

A1 = aaaaaaa\}aaaa\{aaaaa 
B1 = bbbbbbbb 
C = ccccc\{cccc 
B2 = bbb 
E = eeeee 
G = gggg 
F = ffff 
B3 = bbbbbb 
A2 = aaaaa 

產量:

{A1{B1{C}B2{E}{{G}F}B3}A2} 

爲了描述我使用的依賴性X> Y也就是說,Y取決於X(如在X可以改變Y的意思)

A1 
A1 > B1 
A1 > B1 > C 
A1 > B1 > B2 
A1 > B1 > B2 > E 
A1 > B1 > B2 > G 
A1 > B1 > B2 > F 
A1 > B1 > B2 > B3 
A1 > B1 > B2 > A2 
A1 > A2 

因此,如果我們再有,可以有一個值和有序的節點子值列表。這樣的價值樹是這樣的:

A1 
- B1 
- - C 
- - B2 
- - - E 
- - - G 
- - - F 
- - - B3 
- A2 

然後得到那個影響任何節點的角色,我可以通過每個家長加緊遞歸。

我一直陷在試圖分析字符串到我的節點類什麼:

public class myNode 
{ 
    public myNode Parent; 
    public string Value; 
    public List<myNode> subNodes; 
} 

我讀通過字符串字符,當我遇到一個\我被兩個遞增。當我遇到一個{我保存以前的文本部分爲節點的值,並進入孩子,當我遇到一個}我下臺。

,但我一直搞亂了的邏輯,特別是對GA2。在紙上做這件事很簡單,但是當我嘗試不得不做下臺的實際邏輯時,我總是把它搞亂。

有沒有使這個結構更加簡單的方法是什麼? (或者我應該使用更好的結構)。我認爲應該有一些庫允許將字符串轉換爲樹,但我似乎無法找到任何。

+0

http://www.antlr.org/ ..它應該能夠解析你的結構...雖然 –

+0

可能是這個項目的矯枉過正如果我是正確的,你的問題可以用AST http:///en.wikipedia.org/wiki/Abstract_syntax_tree ..如果是這樣,你可以使用任何你喜歡的ast語法分析器/解析器生成器。我相信他們生成的表格有助於更快的解析...完全忘記了表格被稱爲 –

+0

好問題描述。我冒昧地編輯了標題,因爲它實際上並不是你需要的二叉樹。 –

回答

5

使用 「狀態機」 的方法,其中狀態是當前節點,逃生標誌:

string rtf = @"{aaaaaaa\}aaaa\{aaaaa{bbbbbbbb{ccccc\{cccc}bbb{eeeee}{{gggg}ffff}bbbbbb}aaaaa}"; 

Node root = new Node { Parent = null, Value = "root", SubNodes = new List<Node>() }; 
Node node = root; 
bool escape = false; 
foreach (char c in rtf) { 
    if (escape) { 
    node.Value += c; 
    escape = false; 
    } else { 
    switch (c) { 
     case '{': 
     node = new Node { Parent = node, Value = String.Empty, SubNodes = new List<Node>() }; 
     node.Parent.SubNodes.Add(node); 
     break; 
     case '}': 
     node = new Node { Parent = node.Parent.Parent, Value = String.Empty, SubNodes = new List<Node>() }; 
     if (node.Parent != null) node.Parent.SubNodes.Add(node); 
     break; 
     case '\\': 
     escape = true; 
     break; 
     default: 
     node.Value += c; 
     break; 
    } 
    } 
} 

PrintNode(root, String.Empty); 

Node類(剛剛更名爲一點點):

public class Node { 
    public Node Parent; 
    public string Value; 
    public List<Node> SubNodes; 
} 

對於顯示:

private static void PrintNode(Node node, string level) { 
    if (node.Value.Length > 0) Console.WriteLine(level + node.Value); 
    foreach (Node n in node.SubNodes) { 
    PrintNode(n, level + " "); 
    } 
} 

輸出:

root 
    aaaaaaa}aaaa{aaaaa 
    bbbbbbbb 
     ccccc{cccc 
    bbb 
     eeeee 
     gggg 
     ffff 
    bbbbbb 
    aaaaa 

注意其G節點不是對E節點的孩子,但一個節點和一個空值的子項。

當然,你還必須添加一些錯誤處理。

+0

謝謝,這已經足夠接近了;然後,我通過'Parent.SubNodes'向後循環以獲取父節點的相關節點之前的相關節點。因爲'bbb'取決於'bbbbbbbb'中的值。 – Seph

+0

我需要改變的另外一件事是'case'\\':'仍然需要在輸出中附加'\'字符,因爲這些字符被跳過後面解析的其他字符對,否則很好回答:D – Seph

+0

@ Seph:我明白了。這通常不是如何逃避的。 :) – Guffa