2010-12-09 9 views
9

ich eine Grammatikregel habe,ANTLR: Tokenname erhalten?

OR 
    : '|'; 

Aber wenn ich den AST drucken,

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); 
} 

(Dank Bart) es zeigt den aktuellen | Charakter. Gibt es eine Möglichkeit, dass ich stattdessen "OR" sagen kann?

Antwort

8

robert inspiriert diese Antwort.

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

Ich musste dies vor ein paar Wochen tun, aber mit dem Python ANTLR. Es hilft dir nicht viel, aber es könnte jemandem helfen, der nach einer Antwort sucht.

Bei Python ANTLR sind Token-Typen Ganzzahlen. Der Token-Text ist im Token-Objekt enthalten. Hier ist die Lösung, die ich verwenden:

import antlrGeneratedLexer 

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

Es gibt keine offensichtliche Logik die Nummerierung von Tokens (zumindest mit Python ANTLR) und die Token-Namen werden nicht als Strings außer in dem Modul __dict__ gespeichert, so ist dies die nur eine Möglichkeit, zu ihnen zu gelangen.

Ich würde vermuten, dass in C# Token-Typen in einer Aufzählung sind, und ich glaube, Enumerationen können als Zeichenfolgen gedruckt werden. Aber das ist nur eine Vermutung.

+0

Bingo!'Console.WriteLine (ExpressionParser.tokenNames [tree.Type]);' Der 'int' wird in' tree.Type' gespeichert und das "dict" wird in '___ Parser.tokenNames' gespeichert. – mpen

0

Ich bin neu in Antlr, aber es scheint ITree keine direkte Verpflichtung hat (in .NET) zu Parser zusammenzuhängen. Stattdessen gibt es eine abgeleitete Schnittstelle IParseTree von Parser (in Antlr4) zurückgeführt, und es enthält einige zusätzliche Methoden, einschließlich Überschreibung:

string ToStringTree(Parser parser); 

Er wandelt den gesamten Knoten Teilbaum in Textdarstellung. In manchen Fällen ist es nützlich. Wenn Sie nur den Namen eines konkreten Knoten sehen möchten, ohne es Kinder ist, dann statische Methode in der Klasse verwenden Trees:

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

Diese Methode ist im Grunde das gleiche wie Mark und Robert vorgeschlagen, aber in mehr allgemeine und flexible Art und Weise.

1

Junge, ich habe viel zu viel Zeit damit verbracht, meinen Kopf gegen eine Wand zu schlagen, um das herauszufinden. Mark Antwort gab mir den Hinweis, den ich brauchte, und es sieht aus wie die Folgenden wird der Token-Namen von einem TerminalNode in Antlr 4,5 erhalten:

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

oder in C#:

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

(Sieht aus wie Sie kann das Vokabular entweder vom Parser oder vom Lexer bekommen.)

Diese Vokabularmethoden scheinen der bevorzugte Weg zu sein, um die Token in Antlr 4.5 zu erhalten, und tokenNames scheint veraltet zu sein.

Es scheint unnötig kompliziert für das, was ich denke, ist eine ziemlich grundlegende Operation, also vielleicht gibt es einen einfacheren Weg.