Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Print a tree of pyparsing result

I am using pyparsing to parse a hex string and I am searching for an automatic way of print the parser tree.

A near approach is command dump but it print a lot of duplicated info.

For example:

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()

The goal is that result of result.dump() was something similar to

 - 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

The pretty print isn't mandatory, the pretended is the tree structure.

Is there a way of make this print or I will need to had a setParseAction for all rules ?

like image 554
Nine Avatar asked Mar 23 '12 18:03

Nine


2 Answers

Looks like you'll need a setParseAction for each of the rules.

From parsing to object hierarchy: "Attach parse actions to each expression, but here is the trick: use a class instead of a function. The class's init method will get called, and return an instance of that class. "

like image 182
David Pointer Avatar answered Nov 04 '22 13:11

David Pointer


Prefer to add an answer instead of the edit the question, to much code ..

Isn't perfect, the levels don't get right and the classes could be discarded if I could get the resultsName from printAction. Maybe should create a new question :-/

If someone use it and improve please say how :)

#!/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]
like image 34
Nine Avatar answered Nov 04 '22 12:11

Nine