为什么不首先解析关键字并从自由文本匹配中省略?

Why are keywords not parsed first and omitted from free text matching?

我以为我理解了 pyparsing 的逻辑,但无法弄清楚为什么下面的例子失败了。

我正在尝试解析开放式文本评论,其中可以在评论的开头或结尾提及一个产品或一组产品。产品名称也可以从注释中省略。

输出应该是所提及产品的列表以及关于它们的描述。

下面是一些测试用例。解析将所有内容都标识为 'description' 而不是首先选择产品(这不是负片应该做的吗?)

我的理解有什么问题吗?

import pyparsing as pp

products_list = ['aaa', 'bbb', 'ccc']
products = pp.OneOrMore(' '.join(products_list))

word = ~products + pp.Word(pp.alphas)
description = pp.OneOrMore(word)

comment_expr = (pp.Optional(products("product1")) + description("description") + pp.Optional(products("product2")))

matches = comment_expr.scanString("""\
                                aaa is a good product
                                I prefer aaa
                                No comment
                                aaa bbb are both good products""")

for match in matches:
    print match

预期结果为:

product1: aaa, description: is a good product
product2: aaa, description: I prefer
description: No comment
product1: [aaa, bbb] description: are both good products

Pyparsing 的字符串和文字之间的快捷等价旨在提供便利,但有时会导致意外和不需要的情况。在这些行中:

products_list = ['aaa', 'bbb', 'ccc']
products = pp.OneOrMore(' '.join(products_list))

。 我很确定您希望产品与任何产品相匹配。但是相反,OneOrMore 将其作为参数传递:

' '.join(products_list)

这纯粹是一个字符串表达式,结果是 string "aaa bbb ccc"。将此传递给 OneOrMore,您是说产品是字符串 "aaa bbb ccc".

的一个或多个实例

要获得前瞻性,您需要将产品更改为:

products = pp.oneOf(products_list)

甚至更好:

products = pp.MatchFirst(pp.Keyword(p) for p in products_list)

那么你的负面前瞻效果会更好。