5

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}

これを修正するにはどうすればよいですか?

4

1 に答える 1

4

テストされていませんが、変更する必要があると思います:

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

に:

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

編集:わかりました、もう1つの変更。反復コードは、'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' 内の複数のグループにアクセスできprint tokenized['expr_list'][0].dump()ます。0 番目の項目 ( を使用) を見ると、次のようになります。

['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。実際、最も外側の文法式の Group を取得する場合は、'expr_list' も必要なく、 iterate するだけfor f in tokenized:です。

返された ParseResults の内容を引き出すには、dumpおそらくこのメソッドが最適なツールです。

于 2012-08-10T06:31:28.217 に答える