2012-03-23 11 views
6

Estoy usando pyparsing para analizar una cadena hexadecimal y estoy buscando una forma automática de imprimir el árbol de análisis sintáctico.Imprimir un árbol de pyparsing resultado

Un acercamiento cercano es el volcado de comando pero imprime mucha información duplicada.

Por ejemplo:

from pyparsing import * #Word, Optional, OneOrMore, Group, ParseException 

data = Forward() 

arrayExpr = Forward() 

def data_array(s,l,t): 
    n = int(t[0], 16) 
    arrayExpr << (n * data) 
    return t[0] 

array = Word(hexnums, exact=2).setParseAction(data_array) + arrayExpr 

data << (Literal('01') + array.setResultsName('array') 
    | Literal('03') + Word(hexnums, exact=2)('char') 
    | Literal('04') + Word(hexnums, exact=2)('boolean')) 

frame = (Word(hexnums, exact=2)('id') \ 
    + data('data'))('frame') 

result = frame.parseString("02010203010302"); 
print result.dump() 

El objetivo es que la consecuencia de result.dump() era algo similar a

- frame: ['02', '01', '03', '03', '01', '04', '02', '03', '02'] 
    - id: 02 
    - array: ['03', '03', '01', '04', '02', '03', '02'] 
    - char: 01 
    - boolean: 02 
    - char: 02 

La impresión bonita no es obligatorio, la pretendida es la estructura de árbol .

¿Hay alguna manera de hacer esta impresión o necesitaré un setParseAction para todas las reglas?

Respuesta

4

Parece que necesitará un setParseAction para cada una de las reglas.

De parsing to object hierarchy: "Adjuntar analizar las acciones a cada expresión, pero aquí está el truco: utilizar una clase en lugar de una función init método de la clase se llamará, y devolver una instancia de esa clase.".

+0

Gracias, he hecho algo así como el SimpleBool – Nine

+2

Excelente! Estoy pensando que su implementación parece un comienzo razonable. –

+1

exactamente lo que estaba buscando! sin el etiquetado es difícil dar sentido a los tipos en el árbol. – dashesy

2

Prefiero agregar una respuesta en lugar de editar la pregunta, con mucho código ...

No es perfecto, los niveles no son correctos y las clases podrían descartarse si pudiera obtener los resultsName de printAction. Tal vez debería crear una nueva pregunta: -/

Si alguien usarlo y mejorar ruega precisar :)

#!/usr/bin/python 

from pyparsing import * #Word, Optional, OneOrMore, Group, ParseException 

data = Forward() 

level = 0 
arrayExpr = Forward() 

def data_array(s,l,t): 
    n = int(t[0], 16) 
    arrayExpr << (n * data) 
    return t[0] 

class TreeChild(object): 
    def __init__(self,t): 
     self.args = t 
    def __str__(self): 
     ret = " %s: " % self.name 
     return ' ' * level + ret + self.args[0] + "\n" 

class TreeBranch(object): 
    def __init__(self,t): 
     self.args = t 
    def __str__(self): 
     global level 
     level = level + 1 
     childs = " ".join(map(str,self.args)) 
     level = level - 1 
     ret = " %s: " % self.name + '\n' 
     return ' ' * level + ret + childs + "\n" 

class Frame(TreeBranch): 
    name = 'frame' 

class Char(TreeChild): 
    name = 'char' 

class Boolean(TreeChild): 
    name = 'boolean' 

class Id(TreeChild): 
    name = 'id' 

class Array(TreeBranch): 
    name = 'array' 

array = Suppress(Word(hexnums, exact=2).setParseAction(data_array)) + arrayExpr 

data << (Suppress(Literal('01')) + array.setResultsName('array').setParseAction(Array) 
    | Suppress(Literal('03')) + Word(hexnums, exact=2)('char').setParseAction(Char) 
    | Suppress(Literal('04')) + Word(hexnums, exact=2)('boolean').setParseAction(Boolean)) 

frame = (Word(hexnums, exact=2)('id').setParseAction(Id) \ 
    + data('data'))('frame').setParseAction(Frame) 

result = frame.parseString("020103030104020302"); 
print result[0] 
Cuestiones relacionadas