使用停止标记解析字符串

Parsing strings with stop tokens

假设一个解析器接受字母 abc 以及这三者的任意组合。我想用满足以下条件的子字符串调用一个函数:

  1. 子字符串以 a
  2. 开头
  3. 子串在遇到abc
  4. 之前终止
  5. 子字符串不以 abc
  6. 开头

例如我们有以下字符串:

bb cc ab bc cb bc abc bca bbb acc cbc ccc abc

我想用字符串 ab bc cbacc cbc ccc

调用函数

我尝试按如下方式实现:

import pyparsing as pp

x = pp.OneOrMore(pp.Word("abc") + ~pp.Literal("abc"))
x.addCondition(lambda tokens: tokens[0] != "abc")
x.addCondition(lambda tokens: tokens[0][0] == "a")
x.addParseAction(lambda tokens: print("x)", tokens))  # Print action for debugging

y = pp.Word("abc")
y.addParseAction(lambda tokens: print("y)", tokens))

text = pp.OneOrMore(x ^ y)
text.parseString("bb cc ab bc cb bc abc bca bbb acc cbc ccc abc")

但是由于某些原因,这个 停止 1 个字太快了,这是输出:

y) ['bb']
y) ['cc']
x) ['ab', 'bc', 'bc']
y) ['cb']
y) ['abc']
y) ['bca']
y) ['bbb']
x) ['acc', 'cbc']
y) ['ccc']
y) ['abc']

此外,如果 abc 停止标记是一个不同字符串的列表,所有字符串都将用作停止标记,我该如何解析它?

所以像这样:

stopStrings = ["abc", "bca"]
x = pp.OneOrMore(pp.Word("abc") + ~pp.OneOf(stopStrings))
...

希望这能说明问题,感谢您的帮助!

这可能接近您想要的。我不明白你的第三个条件。

  • token 的定义坚持认为它 不是 之一 stop_tokens 并且它是 Word 由任意集合 {a,b,c} 中的字母。
  • token 被识别时 setParseAction 发送一个请求,如果它的第一个字符是 'a'.
  • 则显示它
  • 整个 parser 只是任意数量的 token 后跟任意数量的 stop_token。每个 stop_token 在此上下文中被抑制。同时,如果识别出 stop_token,则会发出一条消息,指示已看到一个。

代码:

import pyparsing as pp

def report_a(s):
    try:
        if s[0][0]=='a':
            print (s[0], "begins with 'a'")
    except:
        pass

def report(s):
    print ('stop token encountered')

stop_tokens = pp.Or([pp.Literal('abc'), pp.Literal('bca')])
token = pp.NotAny(stop_tokens) + pp.Word('abc').setParseAction(lambda s: report_a(s))
parser = pp.ZeroOrMore(token) + pp.ZeroOrMore(stop_tokens).setParseAction(lambda s: report(s)).suppress()

text = 'bb cc ab bc cb bc abc bca bbb acc cbc ccc abc'

print (parser.parseString(text))

结果:

ab begins with 'a'
stop token encountered
['bb', 'cc', 'ab', 'bc', 'cb', 'bc']

我想我明白了。 Bill Bell 的回答帮助我获得了 1 个以上的终止字符串。

stop_strings = ["abc", "acb"]
stop_tokens = pp.Or([pp.Literal(sub) for sub in stop_strings])

x = pp.OneOrMore(~stop_tokens + pp.Word("abc")) + pp.Optional(stop_tokens.suppress())
x.addCondition(lambda tokens: tokens[0][0] == "a")
x.addParseAction(lambda tokens: print("x)", tokens))  # Print action for debugging

y = pp.Word("abc")
y.addParseAction(lambda tokens: print("y)", tokens))

text = pp.OneOrMore(x ^ y)
text.parseString("bb cc acb ab cb abc bca bbb acc cbc ccc")

输出:

y) ['bb']
y) ['cc']
y) ['acb']
x) ['ab', 'cb']
y) ['bca']
y) ['bbb']
x) ['acc', 'cbc', 'ccc']