2010-12-09 19 views
9

Tengo una regla gramatical,ANTLR: ¿Obtener nombre de token?

OR 
    : '|'; 

Pero cuando imprimo la AST usando,

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

(Gracias Bart) muestra el | carácter real. ¿Hay alguna manera de que pueda decir "O" en su lugar?

Respuesta

8

robert inspiró esta respuesta.

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

Tuve que hacer esto hace un par de semanas, pero con la ANTLR de Python. No te ayuda mucho, pero podría ayudar a alguien más a buscar una respuesta.

Con Python ANTLR, los tokens son enteros. El token de texto se incluye en el objeto token. Aquí está la solución utilicé:

import antlrGeneratedLexer 

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

No hay lógica aparente a la numeración de tokens (al menos, con Python antlr), y los nombres simbólicos no se almacenan como cadenas excepto en el módulo __dict__, así que este es el única forma de llegar a ellos.

Supongo que en C# los tipos de token están en una enumeración, y creo que las enumeraciones se pueden imprimir como cadenas. Pero eso es solo una suposición.

+0

Bingo!'Console.WriteLine (ExpressionParser.tokenNames [tree.Type]);' The 'int' se almacena en' tree.Type' y la "dict" se almacena en '___ Parser.tokenNames'. – mpen

0

Soy nuevo en Antlr, pero parece ITree no tiene la obligación directa que estar relacionado con Parser (en .NET). En su lugar hay una interfaz derivada IParseTree, regresar de Parser (en Antlr4), y contiene algunos métodos adicionales incluyendo override:

string ToStringTree(Parser parser); 

Convierte todo el subárbol nodo en representación de texto. Para algunos casos es útil. Si te gusta ver sólo el nombre de algún nodo concreto sin sus hijos, a continuación, utilizar el método estático en la clase Trees:

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

Este método básicamente el mismo que Marcos y Robert sugirió, pero en más manera general y flexible.

1

Chico, pasé demasiado tiempo golpeando mi cabeza contra la pared tratando de resolver esto. La respuesta de Mark me dio la pista que necesitaba, y parece que el siguiente obtendrá el nombre del token de una TerminalNode en Antlr 4.5:

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

o, en C#:

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

(parece que se en realidad puede obtener el vocabulario del analizador o el lector).

Esos métodos de vocabulario parecen ser la forma preferida de obtener los tokens en Antlr 4.5, y tokenNames parece estar en desuso.

Parece innecesariamente complicado para lo que creo que es una operación bastante básica, por lo que quizás haya una manera más fácil.