2015-02-10 42 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