Распечатать дерево результатов разбора - PullRequest
6 голосов
/ 23 марта 2012

Я использую pyparsing для разбора шестнадцатеричной строки и ищу автоматический способ печати дерева синтаксического анализатора.

Ближайший подход - это команда dump, но она выводит много дублирующейся информации.

Например:

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

Цель состоит в том, чтобы результат result.dump () был чем-то похожим на

 - 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

Симпатичный шрифт не обязателен, притворныйдревовидная структура.

Есть ли способ сделать этот отпечаток, или мне понадобится setParseAction для всех правил?

Ответы [ 2 ]

4 голосов
/ 23 марта 2012

Похоже, вам понадобится setParseAction для каждого из правил.

От анализа до иерархии объектов : "Прикрепите действия разбора к каждому выражению, но вот хитрость: используйтекласс вместо функции. Метод класса init будет вызван и вернет экземпляр этого класса. "

2 голосов
/ 30 марта 2012

Предпочитаю добавлять ответ вместо редактирования вопроса, к большому количеству кода.

Не идеально, уровни не подходят, и классы могут быть отброшены, если я смогу получить resultsName из printAction. Может, стоит создать новый вопрос: - /

Если кто-то использует это и улучшает, пожалуйста, скажите как:)

#!/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]
...