Как разобрать и вернуть иерархию ключевых слов? - PullRequest
0 голосов
/ 12 декабря 2018

Ключевые слова для команды, которую я хочу проанализировать, имеют иерархию, например:

ключевые слова 'aaa' и 'bbb' будут принадлежать 'product1', а 'ccc' и 'ddd' будут принадлежатьдо 'product2'.В целом 'product1' и 'product2' принадлежат 'product'.

Когда пользователь вводит строку, такую ​​как 'ccc run X', я хочу, чтобы синтаксический анализатор выводил как часть дампа:

Product: product2 

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

Спасибо

1 Ответ

0 голосов
/ 12 декабря 2018

Я думаю, что действие разбора - лучшее место для добавления подобных предметов в токены.В теле действия синтаксического анализа, которое передает переданные токены, вы можете добавить новые именованные результаты, просто используя интерфейс dict на токенах, чтобы добавить его.

Я смоделировал этот простой анализатор для анализа вашей команды:

import pyparsing as pp

cmd_prefix = pp.oneOf("aaa bbb ccc ddd")
action_expr = pp.oneOf("run hold cancel submit pause resume")
cmd_expr = (cmd_prefix("prefix") 
            + action_expr("action") 
            + pp.empty() + pp.restOfLine("qualifiers"))

Запуск образца команды в качестве теста:

cmd_expr.runTests("""\
    aaa run X
    """)

Дает:

aaa run X
['aaa', 'run', 'X']
- action: 'run'
- prefix: 'aaa'
- qualifiers: 'X'

Мы можем добавить действие разбора в ваш cmd_expr, чтобы украсить результатыс дополнительными записями.Чтобы сохранить код и данные отдельно, вот диктовка, которая определяет несколько добавленных элементов на основе префикса:

prefix_items = {
    'aaa': {'Product': 'product1', 'Material':  'paper', },
    'bbb': {'Product': 'product1', 'Material':  'wool', },
    'ccc': {'Product': 'product2', 'Material':  'wood', },
    'ddd': {'Product': 'product2', 'Material':  'plastic', },
    }

И это действие синтаксического анализа добавит их к проанализированным результатам:

def add_prefix_items(tokens):
    # find dict of items to add
    adders = prefix_items.get(tokens.prefix, {})

    # for each key-value in dict, add to the parsed tokens
    for name, value in adders.items():
        tokens[name] = value

cmd_expr.addParseAction(add_prefix_items)

Вот еще несколько тестов и вывод:

cmd_expr.runTests("""\
    aaa run X
    ddd hold Z
    eee resume A
    """)

Дает:

aaa run X
['aaa', 'run', 'X']
- Material: 'paper'
- Product: 'product1'
- action: 'run'
- prefix: 'aaa'
- qualifiers: 'X'


ddd hold Z
['ddd', 'hold', 'Z']
- Material: 'plastic'
- Product: 'product2'
- action: 'hold'
- prefix: 'ddd'
- qualifiers: 'Z'

eee resume A
^
FAIL: Expected aaa | bbb | ccc | ddd (at char 0), (line:1, col:1)

Если этот список будет длинным, вам может понадобиться прочитать его из базы данных некоторыхДобрый.Вот небольшой пример базы данных в памяти (с использованием моей другой библиотеки с открытым исходным кодом, littletable):

import littletable as lt

# create simple in-memory database table, indexed by item
prefix_items = lt.Table().create_index('prefix').csv_import("""\
prefix,name,value
aaa,Product,product1
aaa,Material,paper
bbb,Product,product1
bbb,Material,wool
ccc,Product,product2
ccc,Material,wood
ddd,Product,product2
ddd,Material,plastic
""")

def add_prefix_items_from_table(t):
    # get all entries in the table with matching key
    # (in a SQL database, this would be some kind of SELECT query)
    adders = prefix_items.by.prefix[t.prefix]

    # for each matching record, add the item-value to the parsed tokens
    for rec in adders:
        t[rec.name] = rec.value

# clear previous parse action and add new one
cmd_expr.setParseAction()
cmd_expr.addParseAction(add_prefix_items_from_table)

Дает результаты, аналогичные показанным ранее.

...