Pyparsing getName () возвращает неправильное имя - PullRequest
2 голосов
/ 27 июня 2019

Я анализирую строки с dotted.strings и инфиксными математическими операторами.Кажется, что сам синтаксический анализ работает нормально, но имя, возвращаемое getName, не соответствует ожиданиям.

from pyparsing import (Word, alphas, opAssoc, infixNotation, 
                       Suppress, Group, delimitedList, oneOf)
LPAR, RPAR = map(Suppress, "()")

chars = Word(alphas + "_")
colstr = Group(delimitedList(chars, delim=".")).setResultsName("colstr*")
infix_expr = infixNotation(colstr, [
    ("-", 1, opAssoc.RIGHT),
    (oneOf("* /"), 2, opAssoc.LEFT),
    (oneOf("+ -"), 2, opAssoc.LEFT),
])("infix")

Теперь проверяем его ...

>>> infix_ex = infix_expr.parseString('a.b + x.y')
>>> print(infix_ex.dump())
[[['a', 'b'], '+', ['x', 'y']]]
- infix: [['a', 'b'], '+', ['x', 'y']]
  - colstr: [['a', 'b'], ['x', 'y']]
    [0]:
      ['a', 'b']
    [1]:
      ['x', 'y']

Вот чтоЯ ожидаю, но getName, кажется, возвращает имя с неправильного уровня дерева синтаксического анализа.

>>> infix_ex.getName()
'infix'
>>> infix_ex[0].getName()
'colstr'
>>> infix_ex[0].asList()
[['a', 'b'], '+', ['x', 'y']]

Как вы можете видеть, getName возвращает 'infix' для корневого уровня и 'colstr'для уровня инфикса дерева.

1 Ответ

0 голосов
/ 03 июля 2019

Это в значительной степени неизбежно, поскольку getName() - это метод, который определен в ParseResults, а не в сопоставленном токене (который может быть строкой и, следовательно, не поддерживает getName()).

Вот пример из ParseResults.getName строки документации:

    integer = Word(nums)
    ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d")
    house_number_expr = Suppress('#') + Word(nums, alphanums)
    user_data = (Group(house_number_expr)("house_number")
                | Group(ssn_expr)("ssn")
                | Group(integer)("age"))
    user_info = OneOrMore(user_data)

    result = user_info.parseString("22 111-22-3333 #221B")
    print(result.asList())
    for item in result:
        print(item.getName(), ':', item[0])

, которая печатает:

[['22'], ['111-22-3333'], ['221B']]
age : 22
ssn : 111-22-3333
house_number : 221B

Обратите внимание, что для использования getName() каждый из названных битов должен бытьGroup, и что имя идет в контейнере, а не в сопоставленном токене напрямую.

Вы можете определять имена результатов для элементов, которые не являются Group s, и получать к ним доступнапрямую, без необходимости получать [0] -й элемент, но вы не сможете вызвать getName() для них.

Если вы планируете использовать getName() для обхода структуры, возвращаемой при разборе, используя infixNotation, я рекомендую вам вместо этого определить свои собственные классы контейнеров для операнда и для каждого уровня приоритета в вашей грамматике инфиксной нотации.Посмотрите пример кода simple_bool.py, чтобы увидеть, как это делается.Таким образом, вы будете иметь более непосредственный контроль над объектами, передаваемыми вам от pyparsing, вместо того, чтобы пытаться работать через иерархию обозначений анализируемого инфикса (и, вероятно, пересматривать некоторые шаги анализа в процессе).

...