Анализ структуры объекта данных из текстовой строки

Я пробовал кое-что с модулем pyparsing, чтобы получить некоторое представление об общем анализе.
Мне дали вопрос для интервью (который был отправлен, поэтому я не думаю, что сейчас есть какие-либо этические проблемы), чтобы обработать структуру данных, подобную приведенной ниже, из текстового файла.

Collection Top_Level_Collection "Junk1"
{
  Column Date_time_column 1 {"01-21-2011"}
  Collection Pig_Entry "Sammy"
  {
    Column Animal_locations 35 {"Australia", "England", "U.S."}
    Data 4
    {
      4 0 72033 Teeth 2 {1 "2", 1 "3"};
      1 0 36331 Teeth 2 {2 "2", 3 "4"};
      2 3 52535 Teeth 2 {6 "4", 9 "3"};
      4 0 62838 Teeth 2 {3 "7", 7 "6"};
    }
  }
}

Я могу получить действительно хакерское решение с регулярным выражением и подсчетом столбцов, чтобы извлекать фрагменты данных и объединять их, но я хотел бы расширить свои знания в синтаксическом анализе, чтобы делать вещи более красноречиво.
Видно, что базовая структура сначала является «Основной абстрактный тип данных», затем следует необязательный «конкретный тип данных», затем либо «имя», либо «количество записей», при этом он может быть бесконечно вложенным.

Вот что я получил до сих пор, пытаясь разобрать словарь:

import numpy as np
import pyparsing as pp

test_str = '''
Collection Top_Level_Collection "Junk"
{
  Column Date_time_column 1 {"01-21-2011"}
  Collection Pig_Entry "Sammy"
  {
    Column Animal_locations 35 {"Australia", "England", "U.S."}
    Data 4
    {
      4 0 72033 Teeth 2 {1 "2", 1 "3"};
      1 0 36331 Teeth 2 {2 "2", 3 "4"};
      2 3 52535 Teeth 2 {6 "4", 9 "3"};
      4 0 62838 Teeth 2 {3 "7", 7 "6"};
    }
  }
}
'''
if __name__ == '__main__':
    expr = pp.Forward()

    object_type = pp.Word( pp.alphanums + '_')
    object_ident = pp.Word( pp.alphanums + '_')
    object_name_or_data_num = pp.Word( pp.alphanums + '_".')

    ident_group = pp.Group(object_type + pp.Optional(object_ident) + object_name_or_data_num)
    nestedItems = pp.nestedExpr("{", "}")

    expr << pp.Dict(ident_group + nestedItems)

    all_data_dict = (expr).parseString(test_str).asDict()

    print all_data_dict
    print all_data_dict.keys()

который возвращает:

{'Column': (['Date_time_column', '1', (['"01-21-2011"'], {}), 'Collection', 'Pig_Entry', '"Sammy"', (['Column', 'Animal_locations', '35', (['"Australia"', ',', '"England"', ',', '"U.S."'], {}), 'Data', '4', (['4', '0', '72033', 'Teeth', '2', (['1', '"2"', ',', '1', '"3"'], {}), ';', '1', '0', '36331', 'Teeth', '2', (['2', '"2"', ',', '3', '"4"'], {}), ';', '2', '3', '52535', 'Teeth', '2', (['6', '"4"', ',', '9', '"3"'], {}), ';', '4', '0', '62838', 'Teeth', '2', (['3', '"7"', ',', '7', '"6"'], {}), ';'], {})], {})], {}), 'Collection': (['Top_Level_Collection', '"Junk"'], {})}
['Column', 'Collection']

Однако я надеюсь, что он вернет что-то, что можно легко отправить в классы Python для создания объектов. Мое лучшее предположение для этого - поместить их во вложенный словарь, где ключ представляет собой кортеж из 2 или 3 типов объектов, а значение представляет собой словарь с каждым значением ключа под ним. т.е. Что-то похожее на это:

{ (Collection, Top_Level_Collection, "Junk1"):
    { (Column, Date_time_column): ["01-21-2011"], 
      (Collection, Pig_Entry, "Sammy"): 
        { (Column, Animal_locations): ["Australia", "England", "U.S."],
            (Data): [[ 4 0 72033 {(Teeth):[1 "2", 1 "3"]} ]
                    [ 1 0 36331 {(Teeth):[2 "2", 3 "4"]} ]
                    [ 2 3 52535 {(Teeth):[6 "4", 9 "3"]} ]
                    [ 4 0 62838 {(Teeth):[3 "7", 7 "6"]} ]]
        }
    }
}

person chase    schedule 04.07.2014    source источник
comment
В чем именно заключается ваш вопрос? Если у вас есть работающий код, который, по вашему мнению, можно улучшить, рассмотрите возможность codereview.stackexchange.com.   -  person jonrsharpe    schedule 04.07.2014
comment
Это не совсем работает, вывод, который я получаю, не вкладывает вещи должным образом   -  person chase    schedule 05.07.2014
comment
@jonrsharpe - он не знает основ написания синтаксического анализатора, проверка кода отправит его обратно.   -  person Leopold Asperger    schedule 05.07.2014
comment
@chase - см. мой ответ здесь   -  person Leopold Asperger    schedule 05.07.2014


Ответы (1)


Вам нужно будет создать классы для ваших данных, а затем использовать «setParseAction» для синтаксических анализаторов, чтобы вы могли создавать любые структуры данных, которые вы хотите. Для примера проверьте простой пример ниже:

#!/usr/bin/env python

from pyparsing import *

test_str="Alpha 1\nBeta 2\nCharlie 3"

aStmt = Word(alphas)("name") + Word(nums)("age")

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

def myParse(t):
    return Person(t.name, t.age)

aStmt.setParseAction(myParse)

for aline in test_str.split('\n'):
    print aline
    print aStmt.parseString(aline)
person leodotcloud    schedule 16.09.2014