嵌套的括号解析案例,导致多个序列结果

时间:2013-10-14 08:18:08

标签: pyparsing

我想用这些条件解析带嵌套括号的字符串:

  • 元素由逗号,或栏|分隔。
  • 嵌套括号元素可以是单个alphanum或另一个嵌套括号。
  • 每个由条|文字连接的嵌套括号元素导致创建一个新序列,该序列组合了先前的序列元素和由嵌套括号外的逗号,连接的前向元素。

为了澄清,让我举一些输入字符串的例子以及它们应该返回的结果:

(a, b, c)应返回:a, b, c

(a, (b | c))应返回:a, ba, c

(a, b, (c | (d, e)), f)应返回:a, b, c, fa, b, d, e, f

(a, b, (c | (d, e) | f), g)应返回:a, b, c, ga, b, d, e, g以及a, b, f, g

(a, b, c, ((d, (e | f)) | (g, h)), i)应返回:a, b, c, d, e, ia, b, c, d, f, i以及a, b, c, g, h, i

((a | b), c)应返回:a, cb, c

1 个答案:

答案 0 :(得分:3)

(来自pyparsing wiki) 您可以使用infixNotation(以前称为operatorPrecedence)来解析字符串。假设','优先于'|',这看起来像:

variable = oneOf(list(alphas.lower()))
expr = infixNotation(variable, 
            [
            (',', 2, opAssoc.LEFT),
            ('|', 2, opAssoc.LEFT),
            ])

将测试用例转换为一个小测试框架,我们至少可以测试解析部分:

tests = [
    ("(a, b, c)", ["abc"]),
    ("(a, b | c)", ["ab", "c"]),
    ("((a, b) | c)", ["ab", "c"]),
    ("(a, (b | c))", ["ab", "ac"]),
    ("(a, b, (c | (d, e)), f)", ["abcf","abdef"]),
    ("(a, b, (c | (d, e) | f), g)", ["abcg", "abdeg", "abfg"]),
    ("(a, b, c, ((d, (e | f)) | (g, h)), i)",
      ["abcdei", "abcdfi", "abcghi"]),
    ("((a | b), c)", ["ac", "bc"]),
    ]

for test,expected in tests:
    # if your expected values *must* be lists and not strings, then
    # add this line
    # expected = [list(ex) for ex in expected]
    result = expr.parseString(test)
    print result[0].asList()

会给你这样的东西:

['a', ',', 'b', ',', 'c']
[['a', ',', 'b'], '|', 'c']
[['a', ',', 'b'], '|', 'c']
['a', ',', ['b', '|', 'c']]
['a', ',', 'b', ',', ['c', '|', ['d', ',', 'e']], ',', 'f']
['a', ',', 'b', ',', ['c', '|', ['d', ',', 'e'], '|', 'f'], ',', 'g']
['a', ',', 'b', ',', 'c', ',', [['d', ',', ['e', '|', 'f']], '|', ['g', ',', 'h']], ',', 'i']
[['a', '|', 'b'], ',', 'c']

这是一个简单的部分,解析字符串并在生成的结构中反映运算符优先级。现在,如果您按照正则表达式逆变器中的示例进行操作,则需要将对象附加到每个已解析的位,如下所示:

class ParsedItem(object):
    def __init__(self, tokens):
        self.tokens = tokens[0]
class Var(ParsedItem): 
    """ TBD """
class BinaryOpn(ParsedItem):
    def __init__(self, tokens):
        self.tokens = tokens[0][::2]
class Sequence(BinaryOpn):
    """ TBD """
class Alternation(BinaryOpn):
    """ TBD """

variable = oneOf(list(alphas.lower())).setParseAction(Var)
expr = infixNotation(variable, 
            [
            (',', 2, opAssoc.LEFT, Sequence),
            ('|', 2, opAssoc.LEFT, Alternation),
            ])

现在,您必须实施VarSequenceAlternation的正文。您不会直接从pyparsing获取值列表,而是返回其中一个对象类型。然后,不像我在上面的示例中那样调用asList(),而是调用类似generatemakeGenerator的内容来从该对象获取生成器。然后你将调用该生成器让对象为你生成所有不同的结果。

我把剩下的作为练习留给你。

- 保罗