2010-12-09 104 views
9

我有一个语法规则,ANTLR:获取令牌名称?

OR 
    : '|'; 

但是,当我打印使用AST,

public static void Preorder(ITree tree, int depth) 
{ 
    if (tree == null) 
    { 
     return; 
    } 

    for (int i = 0; i < depth; i++) 
    { 
     Console.Write(" "); 
    } 

    Console.WriteLine(tree); 

    for(int i=0; i<tree.ChildCount; ++i) 
     Preorder(tree.GetChild(i), depth + 1); 
} 

(感谢Bart)它显示实际|字符。有没有办法让我说“OR”呢?

回答

8

robert启发此答案。

if (ExpressionParser.tokenNames[tree.Type] == tree.Text) 
    Console.WriteLine(tree.Text); 
else 
    Console.WriteLine("{0} '{1}'", ExpressionParser.tokenNames[tree.Type], tree.Text); 
6

几周前我不得不这样做,但是使用了Python ANTLR。它对你没有多大帮助,但它可以帮助别人寻找答案。

使用Python ANTLR,令牌类型是整数。令牌文本包含在令牌对象中。下面是我所使用的溶液:

import antlrGeneratedLexer 

token_names = {} 
for name, value in antlrGeneratedLexer.__dict__.iteritems(): 
    if isinstance(value, int) and name == name.upper(): 
     token_names[value] = name 

有没有明显的逻辑到令牌的编号(至少与Python ANTLR),和令牌名称不存储为除模块__dict__字符串,所以这是只有获得他们的方式。

我想,在C#中的令牌类型是枚举,我相信枚举可以打印为字符串。但这只是一个猜测。

+0

宾果!`Console.WriteLine(ExpressionParser.tokenNames [tree.Type]);``int`存储在`tree.Type`中,“dict”存储在`___ Parser.tokenNames`中。 – mpen 2010-12-09 23:20:15

0

我是新来的ANTLR的,但它似乎ITree有可能与Parser(.NET中)没有直接的义务。取而代之的是一个派生的接口IParseTree,返回从Parser(在Antlr4),它包含一些额外的方法,包括控制装置:

string ToStringTree(Parser parser); 

它的整个节点树转换成文本表示。对于某些情况它很有用。

public static string GetNodeText(ITree t, Parser recog); 

这个方法并基本相同马克罗伯特建议,但更多:如果你喜欢看一些具体的节点只是名字没有它的孩子,然后在Trees类使用静态方法一般而灵活的方式。

1

男孩,我花了太多的时间把我的头撞在墙上试图弄清楚这一点。马克的回答给了我所需要的暗示,它看起来像下面将从TerminalNode在ANTLR的4.5获得令牌名称:

myLexer.getVocabulary.getSymbolicName(myTerminalNode.getSymbol.getType) 

,或者在C#:

myLexer.Vocabulary.GetSymbolicName(myTerminalNode.Symbol.Type) 

(貌似你实际上可以从解析器或词法分析器获取词汇表。)

那些词汇表方法似乎是在Antlr 4.5中获得令牌的首选方式,并且tokenNames似乎已被弃用。

对于我认为是非常基本的操作来说,它似乎不必要地复杂,所以也许有一种更简单的方法。