3

解析のためにpython pyparsingを試しています。再帰パーサーの作成中に行き詰まりました。

問題を説明しましょう

要素のデカルト積を作りたいです。構文は次のとおりです。

cross({elements },{element})

より具体的に言います

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

したがって、一般的な形式は、最初のグループには n 個の要素 (a、b、c、d) があります。2 番目のグループには 1 つの要素が含まれるため、最終的な出力はデカルト積になります。

次のように n レベルに進むことができるため、構文を再帰的にする必要があります。

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

これは、a,b を c1 と交差させることを意味します。結果を y としましょう。y と c2 を再び交差させます。

これは n レベルまで可能です cross(cross(cross(cross......

私が欲しいのは、 setparseAction を使用してオブジェクトを初期化することです

だから私は2クラスを持っています

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

class object2(object):
       This will hold cross elements

これについて助けが必要です。再帰パーサーを作成できません。

4

3 に答える 3

4

文法を再考する必要がある@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']
于 2009-03-11T14:24:58.477 に答える
3

これが役立つかどうかはわかりませんが、lepl で必要なことを行う方法は次のとおりです。文法は正しいように見えるので、pyparse に変換するのは簡単だと思います。

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']
于 2009-11-04T12:08:47.280 に答える