英文:
Pyparsing: How to collect all named results from groups?
问题
我正在使用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
在这里,变量被返回,但对于更复杂的表达式,这并不容易访问。是否有一种方法可以收集所有嵌套的变量?
有一个类似的问题在这里,但那里的解决方法会错误地将关键字标记为变量。
英文:
I'm using pyparsing and I need to be able to collect all of the variable names from an expression. It seems like this should be possible with setResultsName
, but for expressions with parens or that are otherwise grouped, the variable names are nested.
For example,
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())
This gives
[[['a', '+', 'b'], '+', 'c']]
[0]:
[['a', '+', 'b'], '+', 'c']
- var: [['c']]
[0]:
['c']
[0]:
['a', '+', 'b']
- var: [['a'], ['b']]
[0]:
['a']
[1]:
['b']
[1]:
+
[2]:
c
where the variables are returned, but not in an easily accessible format especially for more complex expressions. Is there a way to collect all of the nested variables?
There's a similar question here, but the workaround there would incorrectly label keywords as variables.
答案1
得分: 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'))
# 输出: ['a', 'b', 'c']
顺序不确定,但如果需要,您可以对列表进行排序。
英文:
As I understand it, you want the output to be the list of variables found throughout the tree as a single list.
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']
The order is not deterministic, but you can sort the list if needed.
答案2
得分: 0
你可以为变量添加一个解析操作,将其名称保存到一个变量列表中(确保在调用setResultsName之前插入此代码):
found_variables = []
def found_var(s, l, t):
found_variables.append(t[0])
variable.add_parse_action(found_var)
在第二次调用parse_string之前,务必清空列表。
英文:
You could add a parse action to variable to save its name off to a variable list (be sure to insert this code before calling setResultsName):
found_variables = []
def found_var(s, l, t):
found_variables.append(t[0])
variable.add_parse_action(found_var)
Be sure to clear the list before calling parse_string a second time.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论