2015-02-10 16 views
1

我正在使用ANTLR4在C#中的代碼生成器上工作。它工作,但我正在做一些比TerminalNode更高的級別,我認爲應該在TerminalNode中處理。我想擴展或覆蓋解析樹中的TerminalNode對象

現在,我有一個標識符規則,例如,它可以具有GetText()值「myCollection.First.Name」並具有「myCollection」,「。」,「First」,「 。「,」Name「... [請注意,我的域語言不是C#或Java或C++ - 這是一種自定義語法。]

我當前執行映射從IdentifierContext到代碼將操作的域模型,在那裏我認爲這將是更容易實現和理解,如果該映射是在TerminalNode級別完成,像這樣:

"myCollection" --> An identifier for an object that lives in the top level scope. 
"." --> Descend into the scope of "myCollection". 
"First" --> an identifier for an object that lives in "myCollection"'s scope 
"." --> Descend into the scope of "First". 
"Name" --> an identifier for an object that lives in "First"'s scope 

我一直無法找到一種方法ŧ o這樣做,我不確定創建自定義Token和TokenFactory是否正確。似乎這將放入詞法分析器,應該在解析器中駐留什麼。

幫助?

P.S.我有「最終的Antlr4參考」,雖然看起來並不那麼遙遠,但如果答案在那裏,請給我一個指向它的指針?

回答

0

好吧,雖然這不是我所想的是最好的方式,由於所需的權宜之計,我已經通過如下創建自定義令牌和令牌工廠奉行這樣的:

在解析命名空間

,我創建了一個自定義的令牌:

public class VToken : CommonToken 
{ 

    public IModelTreeNode ModelTreeNode; 
    public bool IsRecognized; 
    public string[] Completions; 

    public VToken(int type, String text) : base(type, text) 
    { 
    } 

    public VToken(Tuple<ITokenSource, ICharStream> source, int type, 
     int channel, int start, int stop) : base(source, type, channel, start, stop) 
    { 
    } 

    public override string ToString() 
    { 
     return "VToken : " + Text; 
    } 
} 

然後我創建了一個自定義的令牌工廠(也是在解析命名空間)

public class VTokenFactory : ITokenFactory 
{ 
    public static readonly ITokenFactory Default = (ITokenFactory)new VTokenFactory(); 

    protected internal readonly bool copyText; 

    public VTokenFactory(bool copyText) 
    { 
     this.copyText = copyText; 
    } 

    public VTokenFactory() 
     : this(false) 
    { 
    } 

    public virtual VToken Create(Tuple<ITokenSource, ICharStream> source, int type, string text, int channel, int start, int stop, int line, int charPositionInLine) 
    { 
     VToken myToken = new VToken(source, type, channel, start, stop) 
     { 
      Line = line, 
      Column = charPositionInLine 
     }; 

     if (text != null)myToken.Text = text; 
     else if (this.copyText && source.Item2 != null) myToken.Text = source.Item2.GetText(Interval.Of(start, stop)); 
     return myToken; 
    } 

    IToken ITokenFactory.Create(Tuple<ITokenSource, ICharStream> source, int type, string text, int channel, int start, int stop, int line, int charPositionInLine) 
    { 
     return (IToken)this.Create(source, type, text, channel, start, stop, line, charPositionInLine); 
    } 

    public virtual VToken Create(int type, string text) 
    { 
     return new VToken(type, text); 
    } 

    IToken ITokenFactory.Create(int type, string text) 
    { 
     return (IToken)this.Create(type, text); 
    } 
} 

最後,改變解析器創建如下:

VLexer lexer = new VLexer(input); 
VTokenFactory factory = new VTokenFactory(); // <-- added 
lexer.TokenFactory = factory;    // <-- added 
CommonTokenStream tokens = new CommonTokenStream(lexer); 
VParser parser = new VParser(tokens); 

,當我處理規則,我通過訪問新的領域:

((VToken)context.children[0].Payload).Completions 
((VToken)context.children[0].Payload).IsRecognized 
((VToken)context.children[0].Payload).ModelTreeNode 
+0

注:本作品,但正如我所說的,感覺並不像它的建築的「正確」的地方把它。任何建議仍然是非常受歡迎的。 – 2015-02-11 23:29:41