我有一个语法规则,
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)它会显示实际的|
字符。有没有办法让它说“或”呢?
答案 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 建议的方法基本相同,但更通用,更灵活。