2009-03-11 9 views
2

私は解析のためのpythonのpyparsingしようとしています。再帰的なパーサを作成している間、私は立ち往生した。pyparsingを使用して再帰的なパーサーを作成するための助けが必要

は、私は要素の直積を作りたい問題

を説明しましょう。構文は、私はより具体的な方法

cross({a},{c1}) or cross({a,b},{c1}) or cross({a,b,c,d},{c1}) or 

だから一般的な形式は、最初のグループが持っているn個の要素(A、B、C、D)であろうです入れ

cross({elements },{element}) 

あります。第2のグループは、最終的な出力がデカルト積であるように1つの要素を有する。

構文は、これはC1にB、交差手段

cross(cross({a,b},{c1}),{c2}) 

ようにn個のレベルに行くことができるので、再帰なされるべきです。私たちに結果を言うことができます。我々は再び(クロス(十字(クロス......

何私がしたいことはsetparseAction

を使用して初期化するオブジェクトを持つことである。これは、n個のレベルのクロスまですることができC2

とYにそれを渡りますだから、私は再帰的なパーサを作ることができないのです。この上で助けを必要とし、クラス2

class object1(object): 
    This will be used by a,b,c,d 

class object2(object): 
     This will hold cross elements 

を持つことになります。

答えて

6

をあなたはどのようにこれを確認するために他の言語の定義をご覧ください通常処理されます。

たとえば、乗算がどのように定義されているかを見てください。

再帰に対処するのは難しいですし、何の暗黙の左から右への順序はありませんので、それは

{expression} * {expression} 

ではありません。あなたがより頻繁に見るものは、以下のようなものです:

{term} + {factor} 
{factor} * {unary-expression} 

これは、オペレータの周りに優先順位と左から右の順序を置くものです。

このようなものが一般的にどのように構成されているかの例については、http://www.cs.man.ac.uk/~pjj/bnf/c_syntax.bnfをご覧ください。

+0

私が使用する表現を必要といけません。私はこれをPythonで行うにはpyparsingのみを使用する必要があります。構文は固定されていると書かれていると私は再帰的なパーサーを使用して行うことができると思う。 –

+0

@asb:他の人はこの種のものに対して再帰的なパーサを使用しないので、混乱しない再帰を排除するために、(構文ではなく定義されている)定義を変更すればもっと成功するかもしれません。 –

3

私は@ S.Lottに同意します。文法を再考する必要があります。

再帰的定義はForward()を使用して導入することができます。

from pyparsing import (Literal, Word, OneOrMore, Forward, nums, alphas) 

def BNF(): 
    """ 
    element  :: id 
    elements  :: '{' element [ ',' element ]+ '}' 
        | 'cross' '(' elements ',' '{' element '}' ')' 
    """ 
    lcb, rcb, lb, rb, comma = [Literal(c).suppress() for c in '{}(),'] 
    element = Word(alphas, alphas+nums+"_") # id 
    elements = Forward() 
    elements << ((lcb + element + OneOrMore(comma + element) + rcb) 
       | (Literal('cross') + lb + elements + comma 
        + lcb + element + rcb + rb)) 
    return elements 

print BNF().parseString("cross(cross({a,b},{c1}),{c2})") 

出力:

['cross', 'cross', 'a', 'b', 'c1', 'c2'] 
3

これは任意のヘルプですが、ここではあなたがやりたいだろうかある場合、私は知りませんレップ文法は正しいと思われるので、私はそれをpyparsingに翻訳するのが簡単だろうと仮定します。

from lepl import * 

def compile_parser(): 

    class Cross(Node): pass 

    word = Token('[a-z0-9]+') 
    par, en, bra, ket = [~Token('\\'+c) for c in '(){}'] 
    comma = ~Token(',') 

    cross = Delayed() 
    vector = bra & word[1:,comma] & ket     > list 
    arg = vector | cross 
    cross += ~word('cross') & par & arg[2,comma] & en > Cross 

    parser = cross.string_parser() 
    return lambda expr: parser(expr)[0] 


if __name__ == '__main__': 

    parser = compile_parser() 
    print parser('cross({a},{c1})') 
    print parser('cross({a,b},{c1})') 
    print parser('cross({a,b,c,d},{c1})') 
    print parser('cross(cross({a,b},{c1}),{c2})') 

出力は次のようになります。

Cross 
+- [u'a'] 
`- [u'c1'] 

Cross 
+- [u'a', u'b'] 
`- [u'c1'] 

Cross 
+- [u'a', u'b', u'c', u'd'] 
`- [u'c1'] 

Cross 
+- Cross 
| +- [u'a', u'b'] 
| `- [u'c1'] 
`- [u'c2'] 
関連する問題