PyParsing使用大括号和特定标头解析嵌套循环

时间:2014-05-15 10:16:48

标签: python nested-loops pyparsing braces

我发现了几个关于pyparsing的话题。他们在解析嵌套循环时遇到了几乎相同的问题,但即便如此,我找不到我的错误的解决方案。

我有以下格式:

key value;
header_name "optional_metadata"
{
     key value;
     sub_header_name
     {
        key value;
     };
};
key value;
  • Key是alphanum
  • 值可以是Int,String的类型,带有alphanum +“@ ._”
  • 键/值可能在括号块之后
  • 键/值可能位于第一个大括号块之前的文件中
  • 大括号块之前或之后的键/值是选项
  • 标题可能有一个名称
  • 闭合支撑后面是分号

我使用了以下解析器:

VALID_KEY_CHARACTERS = alphanums
VALID_VALUE_CHARACTERS = srange("[a-zA-Z0-9_\"\'\-\.@]")

lbr = Literal( '{' ).suppress()
rbr = Literal( '}' ).suppress() + Literal(";").suppress()

expr = Forward()
atom = Word(VALID_KEY_CHARACTERS) + Optional(Word(VALID_VALUE_CHARACTERS))
pair = atom | lbr + OneOrMore( expr ) + rbr
expr << Group( atom + pair )

当我使用它时,我只获得了“header_name”和“header_metadata”,我修改了它,并且我只获得了一个大括号内的键/值,触发了python异常以显示解析错误(它需要'}'到达sub_header_name时。

任何人都可以帮助我理解为什么? 谢谢。

1 个答案:

答案 0 :(得分:1)

我认为主要的问题是你的语法没有完全描述输入,导致几个不匹配。我看到的两个主要问题是您忘记了每个密钥对值必须以分号结尾,并且没有指定在结束大括号之后可以出现密钥对值。它看起来也像以下几行:

pair = atom | lbr + OneOrMore( expr ) + rbr
expr << Group( atom + pair )

...将要求每组花括号至少包含两个键对值或一个键对值和一组花括号。我相信一旦遇到这些行,这会导致错误:

{
    key value;
};

...在你的意见中,虽然我不完全确定。

无论如何,在玩完你的语法之后,我最终得到了这个:

from pyparsing import *

data = """key1 value1; 
header_name "optional_metadata"
{
     key2 value2;
     sub_header_name
     {
        key value;
     };
};
key3 value3;"""

# I'm reusing the key characters for the header names, which can contain a semicolon
VALID_KEY_CHARACTERS = srange("[a-zA-Z0-9_]")
VALID_VALUE_CHARACTERS = srange("[a-zA-Z0-9_\"\'\-\.@]")

semicolon = Literal(';').suppress()
lbr = Literal('{').suppress()
rbr = Literal('}').suppress()

key = Word(VALID_KEY_CHARACTERS)
value = Word(VALID_VALUE_CHARACTERS)

key_pair = Group(key + value + semicolon)("key_pair")
metadata = Group(key + Optional(value))("metadata")

header = key_pair + Optional(metadata)

expr = Forward()
contents = Group(lbr + expr + rbr + semicolon)("contents")
expr << header + Optional(contents) + Optional(key_pair)

print expr.parseString(data).asXML()

这导致以下输出:

<key_pair>
  <key_pair>
    <ITEM>key1</ITEM>
    <ITEM>value1</ITEM>
  </key_pair>
  <metadata>
    <ITEM>header_name</ITEM>
    <ITEM>&quot;optional_metadata&quot;</ITEM>
  </metadata>
  <contents>
    <key_pair>
      <ITEM>key2</ITEM>
      <ITEM>value2</ITEM>
    </key_pair>
    <metadata>
      <ITEM>sub_header_name</ITEM>
    </metadata>
    <contents>
      <key_pair>
        <ITEM>key</ITEM>
        <ITEM>value</ITEM>
      </key_pair>
    </contents>
  </contents>
  <key_pair>
    <ITEM>key3</ITEM>
    <ITEM>value3</ITEM>
  </key_pair>
</key_pair>

我不完全确定这是否正是你想要完成的,希望它应该足够接近你可以调整它以适合你的特定任务。