以任何顺序和数字处理一系列的pyparsing表达式

时间:2016-08-12 19:22:21

标签: python python-2.7 parsing pyparsing

使用pyparsing,我需要指定两个表达式可以以任何顺序出现,并且可以在两个大括号之间以任意数字出现。以下是我的代码。

import pyparsing as pp

def updateList(someList):
    def parseAction(str, loc, tokens):
        someList.append(tokens[0])
    return parseAction

msgNameList = []
ident = pp.Word(pp.alphanums + "_" + ".")
openBrace = pp.Suppress(pp.Literal("{"))
closeBrace = pp.Suppress(pp.Literal("}"))
fieldKw = pp.Keyword("field")
fieldExpr = fieldKw + ident + ident
msgKw = pp.Suppress(pp.Keyword("msg"))
msgName = ident.setParseAction(updateList(msgNameList))
msgExpr = pp.Forward()
msgBody = (openBrace + (pp.ZeroOrMore(fieldExpr) & pp.ZeroOrMore(msgExpr)) + closeBrace)
msgExpr << msgKw + msgName + pp.Optional(msgBody)

testStr1 = "msg msgNameA {msg msgNameAB {field type2 field2} field type1 field1}"
msgExpr.parseString(testStr1)
print msgNameList

msgNameList = []
testStr2 = "msg msgNameA {field type1 field1 msg msgNameAB {field type2 field2}}"
msgExpr.parseString(testStr2)
print msgNameList

产生这个输出:

['msgNameA', 'msgNameAB', 'type2', 'field2', 'type1', 'field1']
[]

请注意,我只在解析msgName表达式时添加到msgNameList。 (最终的表达式和解析函数会更复杂。)

对于两个测试字符串,我想要的输出是:

['msgNameA', 'msgNameAB']

我确信我的msgBody解析表达式不正确,但我无法弄清楚如何在pyparsing中表达我需要的东西。在大括号内,msgExpr或fieldExpr可以按任何顺序和任意数量出现(msgExpr ... fieldExpr ...或fieldExpr ... msgExpr ...)。一些例子:

  1. msgExpr msgExpr fieldExpr fieldExpr fieldExpr msgExpr
  2. fieldExpr msgExpr fieldExpr fieldExpr msgExpr fieldExpr
  3. msgExpr fieldExpr fieldExpr
  4. 我知道必须有办法做到这一点,但我错过了。

    提前致谢

1 个答案:

答案 0 :(得分:2)

(首先,将来,请准备MCVE您的问题。问题的要点是

  

使用pyparsing,我需要指定两个表达式可以以任何顺序出现,并且可以在两个大括号之间以任意数字出现。以下是我的代码。

所以请准备一个只包含足够细节的问题。)

假设我们从

开始
from pyparsing import *

foo = Literal('foo')
bar = Literal('bar')

然后指定“任何顺序和括号之间的任何数字”

openBrace = Suppress(Literal("{"))
closeBrace = Suppress(Literal("}"))

foo_or_bar = foo | bar
content = ZeroOrMore(foo_or_bar)
exp = openBrace + content + closeBrace

现在我们可以查看:

In [40]: exp.parseString('{foo}')
Out[40]: (['foo'], {})

In [41]: exp.parseString('{foobarfoo}')
Out[41]: (['foo', 'bar', 'foo'], {})