Как лечить префиксные ключевые слова? - PullRequest
1 голос
/ 24 марта 2020

У меня следующая проблема с разбором. Моим ключевым словам может предшествовать подчеркивание для деактивации опции, block et c.

#coding: utf8
from pyparsing import Keyword, Combine, pyparsing_common, Literal, Suppress, Group, OneOrMore

test_string = r'''
keyword1list {
    keyword1 {
        option 213
    }

    _keyword1 {
        option 214
    }
}
'''

Это может произойти с любым ключевым словом, здесь keyword1list, keyword1 или option. Чего я хотел бы добиться - это оставить эти блоки во время синтаксического анализа или проанализировать их, но перехватить префикс деактивации.

В настоящее время я могу успешно проанализировать «активированный» test_string с помощью следующего кода, но это не удается по понятным причинам с ключевым словом с подчеркиванием.

lparent = Suppress(Literal('{'))
rparent = Suppress(Literal('}'))

kw1_block = Keyword('keyword1') + lparent
kw1_block = kw1_block + Keyword('option') + pyparsing_common.number.setResultsName('option')
kw1_block = Group(kw1_block + rparent).setResultsName('keyw1')

kw2_block = Keyword('keyword1list') + lparent
kw2_block = kw2_block+ OneOrMore(kw1_block) + rparent
kw2_block = Group(kw2_block).setResultsName('keyword1list', listAllMatches=True)
result = kw2_block.parseString(test_string)
print(result.dump())
tmp = kw2_block.runTests(test_string.replace('\n', '\\n'))
print tmp[0]

Мое текущее решение состоит в том, чтобы поместить все ключевые слова в список и настроить словарь, чтобы объединить их все с подчеркиванием и присвоить им флаг.

#coding: utf8
from pyparsing import Keyword, Combine, pyparsing_common, Literal, Suppress, Group, OneOrMore, ZeroOrMore

test_string = r'''
keyword1list {

    _keyword1 {
        option 1
    }
    keyword1 {
        option 2
    }
    _keyword1 {
        option 3
    }
    keyword1 {
        option 4
    }
    keyword1 {
        option 5
    }
}
'''


kwlist = ['keyword1', 'keyword1list', 'option']
keywords = {}
for k in kwlist:
    keywords[k] = Keyword('_' + k).setResultsName('deactivated') | Keyword(
        k).setResultsName('activated')

lparent = Suppress(Literal('{'))
rparent = Suppress(Literal('}'))

kw1_block = keywords['keyword1'] + lparent
kw1_block = kw1_block + keywords[
    'option'] + pyparsing_common.number.setResultsName('option') + rparent
kw1_block = Group(kw1_block).setResultsName('keyword1', listAllMatches=True)

kw2_block = keywords['keyword1list'] + lparent
kw2_block = kw2_block + ZeroOrMore(kw1_block) + rparent
kw2_block = Group(kw2_block).setResultsName('keyword1list')
result = kw2_block.parseString(test_string)
print(result.dump())
tmp = kw2_block.runTests(test_string.replace('\n', '\\n'))
print tmp[0]

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

Любая помощь очень ценится.

1 Ответ

1 голос
/ 25 марта 2020

Когда я вижу синтаксический анализатор, который предназначен для фильтрации выбранных блоков текста, мой первый подход обычно состоит в том, чтобы написать синтаксический анализатор, который будет соответствовать только выбранной части, а затем использовать transformString с подавленной формой этого синтаксического анализатора:

kwlist = ['keyword1', 'keyword1list', 'option']
to_suppress = MatchFirst(Keyword('_' + k) for k in kwlist)
kw_body = nestedExpr("{", "}") | Word(nums)

filter = (to_suppress + kw_body).suppress()
print(filter.transformString(test_string))

Запуск этого с вашей тестовой строкой дает:

keyword1list {


    keyword1 {
        option 2
    }

    keyword1 {
        option 4
    }
    keyword1 {
        option 5
    }
}
...