2012-12-10 124 views
2

我想用ANTLR在目標語言C#中創建一個分析樹(不是AST)。這似乎不那麼微不足道,也許我正在尋找所有錯誤的地方。創建ParseTree(而不是AST)

到目前爲止,我試圖實現在生成的解析器諧音如下:

public partial class TestParser 
{ 

    ParseTree pt = new ParseTree("root", null); 

    partial void EnterRule(string ruleName, int ruleIndex) 
    { 
    ParseTree child = new ParseTree(ruleName, pt); 
    pt.Children.Add(child); 
    this.pt = child; 
    } 

    partial void LeaveRule(string ruleName, int ruleIndex) 
    { 
    this.pt = pt.Parent; 
    } 

} 

ParseTree

public class ParseTree 
{ 
    private List<ParseTree> children = new List<ParseTree>(); 

    public ParseTree(string name, ParseTree parent) 
    { 
     this.Parent = parent; 
     this.Rule = name; 
    } 

    public ParseTree Parent { get; private set; } 
    public string Rule { get; private set; } 
    public List<ParseTree> Children { get { return children; } } 

    public Boolean IsTerminal 
    { 
     get 
     { 
      return (children.Count == 0); 
     } 
    } 

} 

這工作,但不能滿足我的目標:我可以不會從這棵樹中獲得匹配的標記/文本。除此之外,它還有一個缺點:如果我想爲多個語法做到這一點,我必須在任何地方複製粘貼部分類,因爲它是TestParser的一部分,沒有更高的食物鏈。

我已經看過http://www.antlr.org/wiki/pages/viewpage.action?pageId=1760但生成的解析器沒有一個構造函數,需要ParseTreeBuilder

哪裏現在?

回答

2

我發現或多或少的合理的解決我的問題。它有一個主要的缺點:它只處理僅由令牌組成的生產規則的文本。這對我來說是足夠的,但可能不適合你。正確的實現應該也有令牌節點,所以它可以正確地走。

適配器:

public class ParseAdaptor : CommonTreeAdaptor 
    { 
     private C<ParseTree> container; 

     public ParseAdaptor(C<ParseTree> container) 
      : base() 
     { 
      this.container = container; 
     } 

     public override void AddChild(object t, object child) 
     { 
      base.AddChild(t, child); 
      this.container.Value.Text += base.GetTree(child).Text; 
     } 


    } 

分析樹的實現:

public class ParseTree 
{ 
    private string ownText; 
    private List<ParseTree> children = new List<ParseTree>(); 

    public ParseTree(string name, ParseTree parent) 
    { 
     this.Parent = parent; 
     this.Rule = name; 
    } 

    public String Text 
    { 
     get 
     { 
      if (this.IsTerminal) return this.ownText; 
      else 
      { 
       StringBuilder builder = new StringBuilder(); 
       foreach (ParseTree child in children) 
       { 
        builder.Append(child.Text); 
       } 
       return builder.ToString(); 
      } 
     } 
     set 
     { 
      this.ownText = value; 
     } 
    } 

    public ParseTree Parent { get; private set; } 
    public string Rule { get; private set; } 
    public List<ParseTree> Children { get { return children; } } 

    public Boolean IsTerminal 
    { 
     get 
     { 
      return (children.Count == 0); 
     } 
    } 

} 
//Isn't this the silliest little thing you've ever seen? 
//Where is a pointer when you need one? 
public class C<T> 
{ 
    public T Value { get; set; } 
} 

,並獲取與諧音粘在一起:

public partial class TestParser 
    { 

     C<ParseTree> parseTreeContainer = new C<ParseTree>() { Value = new ParseTree("root", null) }; 

     public ParseTree Tree 
     { 
      get 
      { 
       return parseTreeContainer.Value; 
      } 
      set 
      { 
       parseTreeContainer.Value = value; 
      } 
     } 

     partial void CreateTreeAdaptor(ref ITreeAdaptor adaptor) 
     { 
      adaptor = new ParseAdaptor(this.parseTreeContainer); 
     } 

     partial void EnterRule(string ruleName, int ruleIndex) 
     { 
      ParseTree child = new ParseTree(ruleName, Tree); 
      ParseTree parent = Tree; 
      parent.Children.Add(child); 
      Tree = child; 
     } 

     partial void LeaveRule(string ruleName, int ruleIndex) 
     { 
      Tree = Tree.Parent; 
     } 

    } 
+0

感謝您發佈解決方案。你還能透露一下CommonTreeAdaptor的類定義嗎? – Annie

+0

它的ANTLR – Martijn

-2

你閱讀這篇文章:

http://www.antlr.org/wiki/pages/viewpage.action?pageId=1760

的例子是在Java中,但我懷疑是同一類在C#實現的目標太多。

+2

部分問題字面上寫着「我已經看過http://www.antlr.org/wiki/pages/viewpage.action?pageId=1760但是生成的解析器沒有一個構造函數一個ParseTreeBuilder 「 – Martijn

+0

這就是爲什麼有時候stackoverflow很愚蠢。 –

+0

你能詳細解釋一下嗎?我不認爲我在追隨。 – Martijn