2012-08-10 58 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