2009-11-24 27 views
6

Estoy tratando de usar Antlr para algunas funciones textuales similares a IDE, específicamente analizando un archivo para identificar los puntos para el plegado de código y para aplicar el resaltado de sintaxis.Entender árboles en ANTLR

Primera pregunta: ¿Antlr es adecuado para este requisito o es excesivo? Esto podría se puede lograr utilizando regex y/o un analizador de rollo manual ... pero parece que Antlr está ahí para hacer este trabajo por mí.

He echado un vistazo a través de ... y el excelente recurso tutorial here.

he logrado obtener una gramática de Java incorporado (mediante el standard grammar), y obtener todo lo analizado cuidadosamente en un árbol. Sin embargo, esperaba ver elementos anidados dentro del árbol. En realidad, todo es hijo del elemento superior.

Ej. Teniendo en cuenta:

package com.example 
public class Foo { 
    String myString = "Hello World" 
    // etc 
} 

me hubiera esperado en el nodo del Foo ser un hijo del nodo de la declaración del paquete. Del mismo modo, myString sería un hijo de Foo.

En su lugar, estoy descubriendo que Foo y myString (y todo lo demás) son hijos de package.

Este es el pasaje relevante hacer el análisis sintáctico:

public void init() throws Exception { 
    CharStream c = new ANTLRFileStream(
      "src/com/inversion/parser/antlr/Test.code"); 

    Lexer lexer = new JavaLexer(c); 
    CommonTokenStream tokens = new CommonTokenStream(lexer); 
    JavaParser parser = new JavaParser(tokens); 
    parser.setTreeAdaptor(adaptor); 

    compilationUnit_return result = parser.compilationUnit(); 
} 

static final TreeAdaptor adaptor = new CommonTreeAdaptor() { 
    public Object create(Token payload) { 
     if (payload != null) 
     { 
      System.out.println("Create " + JavaParser.tokenNames[payload.getType()] + ": L" + payload.getLine() + ":C" + payload.getCharPositionInLine() + " " + payload.getText()); 
     } 
     return new CommonTree(payload); 
    } 
}; 

Examinar result.getTree() devuelve una instancia de CommonTree, cuyos hijos son el resultado del análisis.

Valor esperado (quizás incorrectamente)

package com.example (4 tokens) 
    | 
    +-- public class Foo (3 tokens) 
     | 
     +--- String myString = "Hello World" (4 tokens) 
     +--- Comment "// etc" 

(o algo similar)

Valor real (Todos los valores son hijos del nodo raíz del result.getTree())

package 
com 
. 
example 
public 
class 
Foo 
String 
myString 
= 
"Hello World" 

¿Entiendo correctamente cómo funciona esto?

Soy un novato completo en Antlr hasta el momento, y estoy encontrando la curva de aprendizaje bastante empinada.

+0

¿Puedes mostrar el árbol tal como lo encuentras y el árbol como lo hubieras esperado? – Svante

+3

Por cierto, el análisis de idiomas no regulares NO se puede lograr con expresiones regulares. Cada vez que vea "árbol", "recursivo" o "anidado", piense "sin expresiones regulares". – Svante

+0

@Svante - Claro - He expandido el esperado vs real en la publicación. Espero que esto ayude. –

Respuesta

6

La gramática de Java-6 en la parte superior de la sección de intercambio de archivos en antlr.org no incluye la generación de árboles. Tendrás que hacer dos cosas.En primer lugar, dice antlr desea construir un AST:

options { 
    output=AST; 
} 

En segundo lugar, es necesario decir que lo que el árbol debe ser similar, ya sea usando los operadores de árboles o mediante el uso de las reglas de reescritura. Vea el documentation on tree construction. Por lo general, termino haciendo una combinación de ambos.

1

Para construir el árbol, debe establecer output = AST. (Árbol de sintaxis abstracto)

Por lo que yo sé, en una ANTLR solo 1 token puede ser la raíz de un árbol, por lo que no se puede obtener exactamente lo que estás buscando, pero puedes acercarte.

Salida: http://www.antlr.org/wiki/display/ANTLR3/Tree+construction