2012-08-10 56 views
4

我有我的PyParsing语法下面的测试代码:如何循环ParseResults在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最后表达:

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} 

我该如何解决这个问题?

回答

2

未经检验的,但我认为你只需要改变:

expression = (field + operator + value)("expression") 

到:

expression = Group(field + operator + value)("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”命名的价值得到。我还看到有一个子级别的“表达式”,但由于这些键在默认情况下是唯一的,就像在字典中一样,所以最后解析的组只有一个值。但我可以访问“一个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得到表达式,甚至没有使用expression。事实上,如果你把最外面的语法表达组,你不需要'expr_list',只需迭代for f in tokenized:即可。

当试图弄清楚返回的ParseResults的内容时,dump方法可能是最好的工具。

+0

nope,没有工作:( - 编辑的问题也是。 – Kimvais 2012-08-10 06:34:03

+0

是的,我在猜测问题时太快 - 请看更多的编辑。 – PaulMcG 2012-08-10 06:55:16

+0

Thanks! - 现在我正面临一个带有通配符的新问题,但会打开一个新的问题,如果不能解决我自己!:) – Kimvais 2012-08-10 07:09:18