我想用这些条件解析带嵌套括号的字符串:
,
或栏|
分隔。|
文字连接的嵌套括号元素导致创建一个新序列,该序列组合了先前的序列元素和由嵌套括号外的逗号,
连接的前向元素。为了澄清,让我举一些输入字符串的例子以及它们应该返回的结果:
(a, b, c)
应返回:a, b, c
(a, (b | c))
应返回:a, b
和a, c
(a, b, (c | (d, e)), f)
应返回:a, b, c, f
和a, b, d, e, f
(a, b, (c | (d, e) | f), g)
应返回:a, b, c, g
和a, b, d, e, g
以及a, b, f, g
(a, b, c, ((d, (e | f)) | (g, h)), i)
应返回:a, b, c, d, e, i
和a, b, c, d, f, i
以及a, b, c, g, h, i
((a | b), c)
应返回:a, c
和b, c
答案 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),
])
现在,您必须实施Var
,Sequence
和Alternation
的正文。您不会直接从pyparsing获取值列表,而是返回其中一个对象类型。然后,不像我在上面的示例中那样调用asList()
,而是调用类似generate
或makeGenerator
的内容来从该对象获取生成器。然后你将调用该生成器让对象为你生成所有不同的结果。
我把剩下的作为练习留给你。
- 保罗