pyparsing SkipTo и ключ = значение ввода - PullRequest
0 голосов
/ 15 декабря 2018

Я пытаюсь определить синтаксический анализатор ввода, используя pyparsing.Мне удалось получить что-то вроде следующего разбора правильно:

key = value

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

import pyparsing as pp

_name = pp.Word(pp.alphas + '_', pp.alphanums + '_')
_key = _name + EQ
_value = pp.pyparsing_common.signed_integer

pp.dictOf(_key, _value)

Теперь я хотел бы добавить «необработанный» ввод данных:

$raw
H 0.0 0.0 0.0
F 1.0 1.0 1.0
$end

, где что-нибудь между $ и $end сожрановверх "в строку, ключ которой будет raw.Я попытался с:

import pyparsing as pp

SDATA = pp.Literal('$').suppress()
EDATA = pp.CaselessLiteral('$end').suppress()
data_t = pp.Combine(SDATA + pp.Word(pp.alphas + '_', pp.alphanums + '_')
                ) + pp.SkipTo(EDATA) + EDATA
data_t.setName('raw data')
data_t.setParseAction(lambda token: (token[0], token[1]))

, и это работает со строкой ввода '$raw\nH 0.0 0.0 0.0\nF 1.0 1.0 1.0\n$end' Однако я не могу объединить парсер key = value с data_t.Что-нибудь очевидное, что мне здесь не хватает?Или это просто невозможно объединить два?

ОБНОВЛЕНИЕ

Это тестовый вход:

$raw
H 0.0 0.0 0.0
F 1.0 1.0 1.0
$end

int = 42

и это путьЯ объединяю key = value и "необработанные" парсеры данных:

parser = pp.dictOf(_key, _value) ^ data_t

с синтаксическим анализом, затем вызывается как:

tokens = parser.parseString(keywords).asDict()

Это возвращает пустой dict.Перемещение int = 42 выше $raw ... $end возвращает только {'int': 42 }.

1 Ответ

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

Yowch!Это частично связано с ошибкой в ​​dictOf.Чтобы добиться прогресса в этом, я определил следующее:

kv_dict = pp.Dict(pp.OneOrMore(pp.Group(_key + _value)))

Затем я определил свой синтаксический анализатор как:

parser = pp.OneOrMore(pp.Group(data_t) | pp.Group(kv_dict))

Группировка важна, чтобы ключи в одном наборе не переходилина тех в другом.(Ошибка в dictOf не позволяет включать его в OneOrMore, так как dictOf допускает пустой dict, поэтому он завершается бесконечным циклом в конце строки вместо завершения.)

Наконец,Я использую dump(), чтобы увидеть результаты вместо asDict().asDict() будет отображать только проанализированные токены с именами, которые не являются вашими data_t.

print(parser.parseString(sample).dump())

Дает:

[[('raw', 'H 0.0 0.0 0.0\nF 1.0 1.0 1.0\n')], [['int', 42]]]
[0]:
  [('raw', 'H 0.0 0.0 0.0\nF 1.0 1.0 1.0\n')]
[1]:
  [['int', 42]]
  - int: 42

Если вы хотите добавить имена в data_t, изменитеопределение к этому, и отбросить действие разбора:

data_t = pp.Combine(SDATA + pp.Word(pp.alphas + '_', pp.alphanums + '_')
                )("name") + pp.SkipTo(EDATA)("body") + EDATA

Теперь я получаю:

[['raw', 'H 0.0 0.0 0.0\nF 1.0 1.0 1.0\n'], [['int', 42]]]
[0]:
  ['raw', 'H 0.0 0.0 0.0\nF 1.0 1.0 1.0\n']
  - body: 'H 0.0 0.0 0.0\nF 1.0 1.0 1.0\n'
  - name: 'raw'
[1]:
  [['int', 42]]
  - int: 42
...