【问题标题】:pyparsing: grammar for list of Dictionaries (erlang)pyparsing:字典列表的语法(erlang)
【发布时间】:2014-03-29 18:09:12
【问题描述】:

我正在尝试构建一个语法来解析 Erlang 标记的元组列表,并将其映射到 pyparsing 中的 Dict。当我有一个字典列表时,我遇到了问题。如果 Dict 只有一个元素,则语法有效,但是当我添加第二个元素时,现在无法解析它。

当前(简化的语法代码(我删除了在这种情况下不需要的语言部分):

#!/usr/bin/env python2.7

from pyparsing import *

# Erlang config file definition:
erlangAtom = Word( alphas + '_')
erlangString = dblQuotedString.setParseAction( removeQuotes )

erlangValue = Forward()
erlangList = Forward()

erlangElements = delimitedList( erlangValue )
erlangCSList = Suppress('[') + erlangElements + Suppress(']')
erlangList <<= Group( erlangCSList )
erlangTaggedTuple = Group( Suppress('{') + erlangAtom + Suppress(',') +
                           erlangValue + Suppress('}') )
erlangDict = Dict( Suppress('[') + delimitedList( erlangTaggedTuple ) + 
                   Suppress(']') )

erlangValue <<= ( erlangAtom | erlangString |
                  erlangTaggedTuple |
                  erlangDict | erlangList )

if __name__ == "__main__":
    working = """
[{foo,"bar"}, {baz, "bar2"}]
"""

    broken = """
[
    [{foo,"bar"}, {baz, "bar2"}],
    [{foo,"bob"}, {baz, "fez"}]
]
"""
    w = erlangValue.parseString(working)
    print w.dump()

    b = erlangValue.parseString(broken)
    print "b[0]:", b[0].dump()
    print "b[1]:", b[1].dump()

这给出了:

[['foo', 'bar'], ['baz', 'bar2']]
- baz: bar2
- foo: bar

b[0]: [['foo', 'bar'], ['baz', 'bar2'], ['foo', 'bob'], ['baz', 'fez']]
- baz: fez
- foo: bob

b[1]:
Traceback (most recent call last):
  File "./erl_testcase.py", line 39, in <module>
    print "b[1]:", b[1].dump()
  File "/Library/Python/2.7/site-packages/pyparsing.py", line 317, in __getitem__
    return self.__toklist[i]
IndexError: list index out of range

working 有效,但 broken 不会解析为两个列表。

有什么想法吗?

编辑:调整测试用例以更明确地说明预期输出。

【问题讨论】:

  • 你能添加实际打印输出的代码吗?
  • 我有 - 见示例底部 (print erlangValue.parseString(working).dump())

标签: python parsing erlang pyparsing


【解决方案1】:

好的,所以我以前从未使用过 pyparsing,如果我的解决方案没有意义,请见谅。我们开始:

据我了解,您需要的是三个主要结构。您犯的最常见错误是将 delimitedLists 分组。他们已经分组,所以你有一个双重分组的问题。这是我的定义:

对于 {a,"b"}:

erlangTaggedTuple = Dict(Group(Suppress('{') + erlangAtom + Suppress(',') + erlangValue + Suppress('}') ))

对于 [{a,"b"}, {c,"d"}]:

erlangDict = Suppress('[') + delimitedList( erlangTaggedTuple ) + Suppress(']')

剩下的:

erlangList <<= Suppress('[') + delimitedList( Group(erlangDict|erlangList) ) + Suppress(']')

所以我对您的代码的修复是:

#!/usr/bin/env python2.7

from pyparsing import *

# Erlang config file definition:
erlangAtom = Word( alphas + '_')
erlangString = dblQuotedString.setParseAction( removeQuotes )

erlangValue = Forward()
erlangList = Forward()

erlangTaggedTuple = Dict(Group(Suppress('{') + erlangAtom + Suppress(',') +
                           erlangValue + Suppress('}') ))
erlangDict = Suppress('[') + delimitedList( erlangTaggedTuple ) + Suppress(']') 
erlangList <<= Suppress('[') + delimitedList( Group(erlangDict|erlangList) ) + Suppress(']')

erlangValue <<= ( erlangAtom | erlangString |
                  erlangTaggedTuple |
                  erlangDict| erlangList )

if __name__ == "__main__":
    working = """
[{foo,"bar"}, {baz, "bar2"}]
"""

    broken = """
[
    [{foo,"bar"}, {baz, "bar2"}],
    [{foo,"bob"}, {baz, "fez"}]
]
"""
    w = erlangValue.parseString(working)
    print w.dump()

    b = erlangValue.parseString(broken)
    print "b[0]:", b[0].dump()
    print "b[1]:", b[1].dump()

它给出了输出:

[['foo', 'bar'], ['baz', 'bar2']]
- baz: bar2
- foo: bar
b[0]: [['foo', 'bar'], ['baz', 'bar2']]
- baz: bar2
- foo: bar
b[1]: [['foo', 'bob'], ['baz', 'fez']]
- baz: fez
- foo: bob

希望对您有所帮助,干杯!

【讨论】:

  • 太好了 - 谢谢!小测试用例看起来一切都很好;希望我能弄清楚如何将其扩展到完整的语法。赏金当之无愧:)
  • 很高兴能帮上忙 :)
【解决方案2】:

我不明白为什么它不起作用,因为您的代码看起来很像 JSON example,它可以很好地处理嵌套列表。

但问题似乎发生在这一行

erlangElements = delimitedList( erlangValue )

如果erlangValues 是列表,则它们会被附加而不是 cons'd。你可以解决这个问题

erlangElements = delimitedList( Group(erlangValue) )

它会在最顶层元素周围添加一层额外的列表,但会阻止您的子列表合并。

【讨论】:

  • 所以如果我这样做,那么 pyparsing 会分组(而不是合并列表),但字典仍然没有被解析:` [[[['foo', 'bar'], [ 'baz', 'bar2']], [['foo', 'bob'], ['baz', 'fez']]]]`
  • 它为我解析。不过,你没有一本字典。您会得到一个列表,其中包含两个字典的列表。所以result[0][0]result[0][1] 是你的两个字典。 (你期待别的吗?)
  • 这可能对我有用(必须仔细检查更大的语法),但它添加额外级别的列表意味着 Erlang 数据结构不能干净地映射到 Python,这是有问题的。问题是我不明白为什么当前代码不能正常工作 - 它在 erlangList 的定义中已经有一个 Group() ...
  • 所以我回到了 JSON 示例,但它遇到了完全相同的问题 - 请参阅 stackoverflow.com/questions/22081239/… 所以要么我们完全遗漏了一些东西,要么这是 pyparsing 中的基本内容......
猜你喜欢
  • 2020-07-10
  • 2010-10-06
  • 2012-11-15
  • 2011-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-17
  • 1970-01-01
相关资源
最近更新 更多