我的PyParsing语法有以下测试代码:
from pyparsing import Word, nums, alphas, delimitedList, Group, oneOf
from pprint import pprint
field = Word(alphas)("field")
operator = oneOf("= +")("operator")
string_value = Word(alphas)("string")
int_value = Word(nums).setParseAction(lambda t: int(t[0]))("int")
value = (string_value | int_value )("value")
expression = Group(field + operator + value)("expression")
grammar = Group(delimitedList(expression, delim="&&"))("expr_list")
def test(s):
print "Parsing '{0}'".format(s)
tokenized = grammar.parseString(s)
for f in tokenized:
e = f.expression
pprint(dict(e.items()))
if __name__ == "__main__":
test("foo=1")
test("foo=1 && bar=2")
test("foobar=2 && snakes=4")
输出非常意外 - 似乎我只在tokenized
中获得 last 表达式:
Parsing 'foo=1'
{'field': 'foo', 'int': 1, 'operator': '=', 'value': 1}
Parsing 'foo=1 && bar=2'
{'field': 'bar', 'int': 2, 'operator': '=', 'value': 2}
Parsing 'foobar=2 && snakes=4'
{'field': 'snakes', 'int': 4, 'operator': '=', 'value': 4}
我该如何解决这个问题?
答案 0 :(得分:2)
未经测试,但我认为你只需要改变:
expression = (field + operator + value)("expression")
为:
expression = Group(field + operator + value)("expression")
编辑:好的,另外一个改变。您的迭代代码会查找名为“expression”的多个项目。 '&&' - 分隔列表中有多个名为'expression'的项目。更简单的是不通过它们的名称来引用它们,而是通过迭代'expr_list'中的分组表达式:
for f in tokenized['expr_list']:
field = f['field']
op = f['operator']
value = f['value']
print field, op, value
我通常在解析结果上使用dump
方法来查看数据的分组和命名方式。如果我打印出tokenized.dump()
,我会得到:
[[['foo', '=', 1], ['bar', '=', 2]]]
- expr_list: [['foo', '=', 1], ['bar', '=', 2]]
- expression: ['bar', '=', 2]
- field: bar
- int: 2
- operator: =
- value: 2
我可以看到我可以获得'expr_list'命名值。我还看到有一个子级别的“表达式”,但由于这些键在dict中默认是唯一的,因此只有最后解析的组的值。但我可以访问'expr_list'中的多个组 - 如果我查看第0个项目(使用print tokenized['expr_list'][0].dump()
),我得到:
['foo', '=', 1]
- field: foo
- int: 1
- operator: =
- value: 1
所以我可以使用:
遍历'expr_list'中的组for f in tokenized['expr_list']:
field = f['field']
op = f['operator']
value = f['value']
print field, op, value
我会得到:
foo = 1
bar = 2
没有必要在你的语法中的每个级别上放置结果名称 - 在这种情况下,我们通过迭代expr_list
得到了表达式,甚至没有使用{{ 1}}。事实上,如果你采用最外层语法表达式的组,你也不需要'expr_list',只需迭代expression
。
当试图梳理出返回的ParseResults的内容时,for f in tokenized:
方法可能是最好的工具。