Пипарсинг ввода и конкретного вывода - PullRequest
0 голосов
/ 10 октября 2018

Я думаю, как разобрать следующий ввод:

comment ='  @Class wordinfo dict<<position:int>,wordinfo:str>\n ' + \
                           '@Class instances dict<<word:str>,instances:atomicint> '

Для конкретного вывода:

{'wordinfo': {'columns': [('wordinfo', 'text')],
              'primary_keys': [('position', 'int')],
              'type': 'StorageDict'},

 'instances': {'columns': [('instances', 'counter')],
               'primary_keys': [('word', 'text')],
               'type': 'StorageDict'}
}

Как мы видим выше, мне нужно взять ключсловарь в качестве первичного ключа, а затем я могу иметь одно или несколько значений в виде столбцов, сначала у меня всегда есть имя переменной, а затем тип переменной. Я спрашиваю себя, есть ли какой-то простой способ получить желаемый результат, так как яЯ не эксперт с pyparsing.Это осуществимо?Какие шаги мне нужно сделать?

1 Ответ

0 голосов
/ 10 октября 2018

Первый шаг - написать BNF.Вы уже начали думать об этом, когда вы написали: Мне нужно взять ключ словаря в качестве первичного ключа, а затем я могу иметь одно или несколько значений в качестве столбцов, сначала у меня всегда есть имя переменной, а затемтип переменной.

Преобразуйте это во что-то более формальное:

class_definition :: '@Class' identifier class_body
class_body :: class_dict  // can add other types here as necessary
class_dict :: 'dict' '<' '<' identifier ':' value_type '>' ','
                     column_decl [',' column_decl]... '>'
column_decl :: identifier ':' value_type
value_type :: 'int' | 'str' | 'atomicint'

Хммм, identifier : value_type в нескольких местах, назовем это var_decl и перепишем.Кроме того, я думаю, что вы можете иметь составные первичные ключи, определяя разделенный запятыми список внутри <> s, и мы используем этот вид списка в нескольких местах.Перезапись:

class_definition :: '@Class' identifier class_body
class_body :: class_dict  // can add other types here as necessary
class_dict :: 'dict' '<' '<' vars_decl '>' ',' vars_decl '>'
vars_decl :: var_decl [',' var_decl]...
var_decl :: identifier ':' value_type
value_type :: 'int' | 'str' | 'atomicint'

Затем работайте снизу вверх, чтобы определить их в терминах переноса:

import pyparsing as pp
S = pp.Suppress
identifier = pp.pyparsing_common.identifier
value_type = pp.oneOf("int str atomicint")
var_decl = pp.Group(identifier + S(":") + value_type)
vars_decl = pp.Group(pp.delimitedList(var_decl))
dict_decl = pp.Group(S("dict") + S("<") 
                     + S("<") + vars_decl + S(">") + S(",")
                     + vars_decl 
                     + S(">"))
class_decl = pp.Group('@Class' + identifier + dict_decl)

И, наконец, добавьте имена результатов, чтобы можно было выбирать разные фрагменты.после разбора легче:

import pyparsing as pp
S = pp.Suppress
identifier = pp.pyparsing_common.identifier
value_type = pp.oneOf("int str atomicint")
var_decl = pp.Group(identifier("name") + S(":") + value_type("type"))
vars_decl = pp.Group(pp.delimitedList(var_decl))
dict_decl = pp.Group(S("dict") + S("<") 
                     + S("<") + vars_decl("primary_key") + S(">") + S(",")
                     + vars_decl("columns") 
                     + S(">"))
class_decl = pp.Group('@Class'
                      + identifier("class_name")
                      + dict_decl("class_body"))

Затем проанализируйте ваш текст, используя:

class_definitions = pp.OneOrMore(class_decl).parseString(comment)

И распечатайте то, что вы получили:

print(class_definitions.dump())

Или даже лучше:

class_decl.runTests(comment)

Это совершенно не проверено, может быть, там нет единого мнения, но это общая идея.Но даже если вы в конечном итоге используете что-то кроме pyparsing, начните с BNF .Это действительно поможет прояснить ваше мышление и общую концепцию проблемы.

...