2017-06-24 28 views
1

我使用pyparsing,並解析一些文本替換,我創建了一個語法,它工作正常,但是,對於這樣一個表達:Python的解析表達式,並用另一種表達

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

這裏是一個解析器,可能是類似你寫的一個:

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」表達的名稱,你可以用一個解析動作收拾的表達,以及相關的表達ID,在全局列表VAR:

# 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瓦爾來自已解析的輸入。

+0

哇,它就像一個魅力,不知道pyparsing是如此強大,我正在考慮遍歷解析樹來獲取表達式,而這實際上是我想要的第一個地方,這是得到有序從底部到根的表達 – dpalma

+0

我還有一個問題,當我沒有嵌套表達時會發生什麼?因爲當我有一個簡單的表達式,如OR(in1,in2) – dpalma

+0

時,我不想替換名稱這是否會發生?我不認爲我的測試能夠做到這一點(在我的回答中查看發佈的輸出)。 – PaulMcG