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

时间:2019-06-13 20:57:19

标签: pyparsing

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

我有一个标识符数组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

我该如何实现?

1 个答案:

答案 0 :(得分:1)

将字符串列表转换为备用解析表达式列表的最简单方法是使用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"])和快捷按钮版本oneOf("A B C")Literal("A") | Literal("B") | Literal("C")相同

oneOf要注意的一件事是它不强制单词边界

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

将打印:

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

即使开头的“红色”和“绿色”不是分开的单词,而最后的“红色”只是“减少”的第一部分。这正是使用由Literal建立的显式表达式所得到的行为。

要强制使用单词边界,必须使用Keyword类,现在必须使用更多的Python来构建单词边界。

  1. 您将需要为替代项构建一个Or或MatchFirst表达式。通常,您使用'^'或'|'建立这些运算符。但是要使用表达式列表创建其中之一,则可以调用构造函数形式Or(expression_list)MatchFirst(expression_list)

  2. 如果您有字符串列表,您可以可以创建Or(list_of_identifiers),但这默认是将字符串转换为文字,我们已经看到您没有不想那样。

  3. 相反,使用字符串使用Python列表推导或生成器表达式创建关键字表达式,然后将其传递给MatchFirst构造函数(MatchFirst比Or更有效,关键字匹配将是安全的与MatchFirst的短路逻辑配合使用)。以下内容将全部相同,只是在如何构建关键字序列并将其传递给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']