pyparsing 如何将标识符传递给解析器

pyparsing how to pass identifiers to the parser

我正在尝试将有效标识符列表传递给解析器。也就是说:我有一个包含标识符的列表,解析器应该使用它们,我将它们作为参数传递给构造函数。

而不是 identifiers = Literal('identifier1') | Literal('identifier2') | Literal('identifier whatever') 我有一个标识符数组 identifiers = ['identifier1', 'identifier2', 'identifier whatever', ... 'identifier I can not what'] 我需要告诉 pyparsing 用作标识符。

这是我目前所做的:

def __init__(self, idents):
    if isinstance(idents, list) and idents:
        for identifier in idents:
           // and this is where I got stuck
           // I tried:
           // identifiers = Literal(identifier) but this keeps only the lastone

我怎样才能做到这一点?

将字符串列表转换为替代解析表达式列表的最简单方法是使用 oneOf:

import pyparsing as pp

color_expr = pp.oneOf(["red", "orange", "yellow", "green", "blue", "purple"])
# for convenience could also write as pp.oneOf("red orange yellow green blue purple")
# but since you are working with a list, I am show code using a list

parsed_colors = pp.OneOrMore(color_expr).parseString("blue orange yellow purple green green")

# use pprint() to list out results because I am lazy
parsed_colors.pprint()
sum(color_expr.searchString("blue 1000 purple, red red swan okra kale 5000 yellow")).pprint()

打印:

['blue', 'orange', 'yellow', 'purple', 'green', 'green']
['blue', 'purple', 'red', 'red', 'yellow']

所以oneOf(["A", "B", "C"])和easy-button版本oneOf("A B C")Literal("A") | Literal("B") | Literal("C")

相同

使用 oneOf 需要注意的一件事是它不强制执行单词边界

pp.OneOrMore(color_expr).parseString("redgreen reduce").pprint()

将打印:

['red', 'green', 'red']

尽管开头的'red'和'green'不是分开的词,结尾的'red'只是'reduce'的第一部分。这正是使用由 Literals.

构建的显式表达式所获得的行为

要加强单词边界,您必须使用关键字 class,现在您必须使用更多 Python 来构建它。

  1. 您将需要为您的备选方案建立一个 Or 或 MatchFirst 表达式。通常您使用“^”或“|”构建它们运营商,分别。但是要使用表达式列表创建其中一个,则可以调用构造函数形式 Or(expression_list)MatchFirst(expression_list).

  2. 如果你有一个字符串列表,你 可以 只创建 Or(list_of_identifiers),但这将默认将字符串转换为文字,并且我们已经看到你不想要那个。

  3. 相反,使用字符串通过 Python 列表理解或生成器表达式创建关键字表达式,并将其传递给 MatchFirst 构造函数(MatchFirst 比或者,关键字匹配可以安全地与 MatchFirst 的 short-circuiting 逻辑一起使用)。以下内容将全部相同,只是关键字序列的构建方式和传递给 MatchFirst 构造函数的方式略有不同:

    # list comprehension
    MatchFirst([Keyword(ident) for ident in list_of_identifiers])
    
    # generator expression
    MatchFirst(Keyword(ident) for ident in list_of_identifiers)
    
    # map built-in
    MatchFirst(map(Keyword, list_of_identifiers))
    

这里是配色示例,使用关键字重做。请注意大字中嵌入的颜色现在如何匹配:

colors = ["red", "orange", "yellow", "green", "blue", "purple"]
color_expr = pp.MatchFirst(pp.Keyword(color) for color in colors)
sum(color_expr.searchString("redgreen reduce skyblue boredom purple 100")).pprint()

打印:

['purple']