【问题标题】:Pyparsing: How to collect all named results from groups?Pyparsing:如何从组中收集所有命名结果?
【发布时间】:2023-01-31 09:22:20
【问题描述】:

我正在使用 pyparsing,我需要能够从表达式中收集所有变量名。看起来 setResultsName 应该可以做到这一点,但是对于带有括号或以其他方式分组的表达式,变量名是嵌套的。

例如,

ParserElement.enablePackrat()
LPAREN, RPAREN, COMMA = map(Suppress, "(),")
expr = Forward()

number = pyparsing_common.number
fn_call = Group(CaselessKeyword('safe_divide') + LPAREN + expr + COMMA + expr + RPAREN)
reserved_words = CaselessKeyword('safe_divide')
variable = ~reserved_words + pyparsing_common.identifier

operand = number | fn_call | variable.setResultsName('var', listAllMatches=True)

unary_op = oneOf("! -")
power_op = Literal("^")
multiplicative_op = oneOf("* / %")
additive_op = oneOf("+ -")
logical_op = oneOf("&& ||")

expr <<= infixNotation(
    operand,
    [
        (unary_op, 1, opAssoc.RIGHT),
        (power_op, 2, opAssoc.RIGHT),
        (multiplicative_op, 2, opAssoc.LEFT),
        (additive_op, 2, opAssoc.LEFT),
        (logical_op, 2, opAssoc.LEFT),
    ],
)

parsed = expr.parseString('(a + b) + c', parse_all=True)
print(parsed.dump())

这给

[[['a', '+', 'b'], '+', 'c']]
[0]:
  [['a', '+', 'b'], '+', 'c']
  - var: [['c']]
    [0]:
      ['c']
  [0]:
    ['a', '+', 'b']
    - var: [['a'], ['b']]
      [0]:
        ['a']
      [1]:
        ['b']
  [1]:
    +
  [2]:
    c

返回变量的地方,但不是以易于访问的格式,尤其是对于更复杂的表达式。有没有办法收集所有嵌套变量?

有一个类似的问题here,但那里的解决方法会错误地将关键字标记为变量。

【问题讨论】:

  • 你想要什么结果?特别是,如果一个变量出现了多次,它是否应该相应地在结果中重复?或者你只是想要使用的变量名称?

标签: python pyparsing


【解决方案1】:

据我了解,您希望输出是作为单个列表在整个树中找到的变量列表。

def gather_named_elements(tree, name):
    named = []
    for i in range(len(tree)):
        if isinstance(tree[i], ParseResults):
            named += tree[i][name].as_list()
            named += gather_named_elements(tree[i], name)
    return list(set([x[0] for x in named]))

print(gather_named_elements(parsed, 'var'))
# OUTPUT: ['a', 'b', 'c']

顺序不确定,但您可以根据需要对列表进行排序。

【讨论】:

    【解决方案2】:

    您可以向变量添加解析操作以将其名称保存到变量列表中(确保插入此代码调用 setResultsName):

    found_variables = []
    def found_var(s, l, t):
        found_variables.append(t[0])
    variable.add_parse_action(found_var)
    

    确保在第二次调用 parse_string 之前清除列表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-11
      • 2017-11-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多