2012-06-19 7 views
7

Estoy trabajando en la compilación de un compilador y dentro de eso genero un árbol que representa el programa de origen que se transfiere. Quiero mostrar esta es una forma de árbol para que pueda mostrar la estructura del programa para cualquier persona interesada.Pretty Imprimiendo una estructura de datos de árbol en Ruby

Ahora sólo tienen la impresión de árbol en una sola línea como la siguiente:

ProgramNode -> 'Math' BlockNode -> DeclarationNode -> ConstantDeclarationNode -> const ConstantListNode -> [m := 7, ConstantANode -> [n := StringLiteralNode -> ""TEST"" ]] ; 

Lo que me gustaría es algo como esto:

ProgramNode 
    / \ 
'Math' BlockNode 
      | 
    DeclarationNode 
      | 
    ConstantDeclarationNode ------------------------------ 
     / \           | 
    const ConstantListNode        | 
      /| \  \        | 
      m := 7 ConstantANode     | 
          /| \     | 
          n := StringLiteralNode  | 
            / | \   | 
             " TEST "  ; 

realmente no he trabajado con árboles en Ruby, ¿cómo suelen representarse?

Cualquier ayuda sería apreciada.

+1

1 para el árbol ascii bastante :) –

+0

No sólo quiere los árboles generados en el ASCII? – Sean

+2

Imprime el árbol * de lado *, nodo raíz primero, con sangría sangrado. Vea las expresiones S de LISP para las formas canónicas de representar/imprimir árboles. Hecho bien esto te llevará de 1 a 2 horas. –

Respuesta

3

Este tipo de impresión bonita requiere bastante matemática. Además, no está claro lo que debería suceder si el árbol crece demasiado ancho para la ventana de la consola. No sé de ninguna biblioteca existente que haga esto. Yo personalmente uso awesome_print.

tree = {'ConstantDeclarationNode' => ['const', 
             'ConstantListNode' => ['m', ':=', '7']]} 

require 'awesome_print' 

ap tree 
# >> { 
# >>  "ConstantDeclarationNode" => [ 
# >>   [0] "const", 
# >>   [1] { 
# >>    "ConstantListNode" => [ 
# >>     [0] "m", 
# >>     [1] ":=", 
# >>     [2] "7" 
# >>    ] 
# >>   } 
# >>  ] 
# >> } 

Tiene un montón de opciones, ¡compruébalo!

+0

[¿Cómo lo hace 'git'?] (Http://www.kernel.org/pub/software /scm/git/docs/git-log.html) –

+0

Gracias, nunca he oído hablar de esto pero parece realmente prometedor. –

+0

¿Alguna idea sobre cómo podría pasar estos datos entre clases? Cada uno de los nodos en el árbol de arriba representa una clase en mi compilador, ¿debería devolver una matriz de cada uno de esos nodos y reunirlos en un hash de alguna manera? –

2

Debes consultar la gema Graph. Es increíble y notablemente sencillo trabajar con él. Puede elegir la dirección de su árbol y la forma de los nodos, así como los colores y mucho más. La descubrí por primera vez en Rubyconf el año pasado y quedé impresionado.

Es tan simple como:

digraph do 
    edge "Programnode", "Blocknode" 
    edge "Programnode", "Math" 
    edge "Blocknode", "DeclarationNode" 
end 

Obviamente que se desea introducir mediante programación los bordes :)

Aquí es una link to a pdf de la charla que dará más información sobre el mismo:

También hay un video de la charla en Confreaks si está interesado.

Saludos, Sean

+0

Gracias, definitivamente voy a mirar esto –

Cuestiones relacionadas