Python解析表达式并替换为另一个表达式

时间:2017-06-24 01:10:12

标签: python regex python-2.7 pyparsing

我正在使用pyparsing,并且为了解析一些文本,我创建了一个语法,然而,它按预期工作,对于像这样的表达式:

OR(OR(in1, in2), in3)

我想将嵌套表达式替换为“别名”,然后为这个别名创建一个表达式,简单来说就是:

# I have this expression ( OR(OR(in1, in2), in3) )
# Which I parsed to
parsed = ["OR", [["OR", ["in1", "in2"]], "in3"]]

# I want to have
exp1 = ["OR", ["in1", "in2"]]
exp2 = ["OR", ["exp1", "in3"]]

这是一个最小的例子,但是我可以有任何嵌套的“表达式”(只有两个参数)。有没有办法做到这一点?

1 个答案:

答案 0 :(得分:1)

这是一个解析器,可能与您编写的解析器类似:

import pyparsing as pp

LPAR, RPAR = map(pp.Suppress, "()")
OR = pp.Keyword("OR")
term = pp.pyparsing_common.identifier

or_expr = pp.Forward()
or_expr <<= pp.Group(OR + pp.Group(LPAR + pp.delimitedList(or_expr | term)) + RPAR)

当它解析你给出的字符串时,它提供相同的嵌套输出。

要创建“expN”表达式名称,可以使用解析操作在全局列表var中收集表达式和关联的表达式id:

# add parse action to convert OR's to exprs
exprs = []
def generate_expr_definition(tokens):
    expr_name = "exp{}".format(len(exprs)+1)
    exprs.append((expr_name, tokens.asList()[0]))
    return expr_name
or_expr.addParseAction(generate_expr_definition)

运行此解析器时,创建的结果不是重要部分。重要的是解析时构建的exprs列表:

or_expr.parseString(sample)

# generate assignments for each nested OR expr
for name, expr in exprs:
    print("{} = {}".format(name, expr))

这给出了:

exp1 = ['OR', ['in1', 'in2']]
exp2 = ['OR', ['exp1', 'in3']]

现在我看一下,然后问,“我怎么知道从输入解析的'exp1'与应该代表解析表达式的'exp1'之间的区别。如果是要解释为Python赋值,它应该真正读作:

exp2 = ['OR', [exp1, 'in3']]

变量名称周围没有引号。

为此,我们需要从解析操作返回一个对象,该操作将repr作为名称,而不包含周围的引号。像这样:

class ExprName:
    def __init__(self, name):
        self._name = name
    def __repr__(self):
        return self._name

将解析操作中的return语句更改为:

return ExprName(expr_name)

结果输出现在看起来像:

exp1 = ['OR', ['in1', 'in2']]
exp2 = ['OR', [exp1, 'in3']]

现在,您可以将生成的expN变量与已分析的输入区分开来。