ANTLR:获取令牌名称?

时间:2010-12-09 22:43:55

标签: c# 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)它会显示实际的|字符。有没有办法让它说“或”呢?

4 个答案:

答案 0 :(得分:9)

robert启发了这个答案。

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

答案 1 :(得分:7)

几周前我不得不这样做,但使用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#中,令牌类型在枚举中,我相信枚举可以打印为字符串。但这只是猜测。

答案 2 :(得分:1)

男孩,我花了太多时间把头撞在墙上试图解决这个问题。 Mark的回答给了我需要的提示,看起来以下内容将从Antlr 4.5中的TerminalNode获取令牌名称:

ThreadLocal

或者,在C#中:

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

(看起来你实际上可以从解析器或词法分析器中获取词汇。)

这些词汇表方法似乎是Antlr 4.5中令牌的首选方法,而且tokenNames似乎已被弃用。

对于我认为非常基本的操作来说,这看起来似乎不必要地复杂化,所以也许更简单的方法。

答案 3 :(得分:0)

我是Antlr的新手,但似乎ITree没有直接义务与Parser(在.NET中)相关。而是从IParseTree(在Antlr4中)返回的派生接口Parser,它包含一些其他方法,包括覆盖:

string ToStringTree(Parser parser);

它将整个节点子树转换为文本表示。对于某些情况,它很有用。如果你只想看一些没有它的子节点的具体节点的名称,那么在类Trees中使用静态方法:

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

此方法与 Mark Robert 建议的方法基本相同,但更通用,更灵活。