2009-03-11 22 views
2

kullanarak yapma konusunda yardıma mı ihtiyacınız var? Python'u ayrıştırma için python çalışıyorum. Yinelemeli ayrıştırıcıyı yaparken takılıyorum. Yinelemeli ayrıştırıcıyı

bana sorunu ben elemanlarının Kartezyen ürünü yapmak istiyorum

açıklayalım. sözdizimi Daha açık bir şekilde

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

Böylece, genel bir şekilde, ilk grubu olması, n elemanları (a, b, c, d) olacaktır koymak

cross({elements },{element}) 

olup. İkinci grubun bir sonucu olacak, böylece nihai çıktı Kartezyen Ürün olacak. Bu

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

gibi N seviyesine gidebilir, çünkü

sözdizimi Bu c1 b, bir çapraz anlamına özyinelemeli yapılabilir etmektir. Lets bize sonucunu söyle Tekrar Bu (......

İstediğim şey setparseAction

kullanarak başlatıldığını edilecek nesne var çapraz (cross (çapraz n seviyesi haç kadar olabilir c2

ile y onu geçmeye Yani ben özyinelemeli ayrıştırıcı yapmak mümkün değilim bu konuda yardıma ihtiyaç sınıf 2

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

class object2(object): 
     This will hold cross elements 

sahip olacaktır.

cevap

6

Sen nasıl bu görmek için diğer dillerin tanımları bakmak gerekir genellikle ele alınır. Örneğin, çarpmanın nasıl tanımlandığına bakın.

O

{expression} * {expression} 

tekrarlama uğraşmak zor olduğu için değildir ve hiçbir zımni soldan sağa sipariş var. Ne öncelikleri ve operatörler etrafında soldan sağa sipariş koyar

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

gibi şeyler daha sık görmek bulunmaktadır. Bu gibi şeylerin genel olarak nasıl yapılandırıldığının örnekleri için http://www.cs.man.ac.uk/~pjj/bnf/c_syntax.bnf gibi bir şeye bakın.

+0

ben kullanılacak ifadeyi ihtiyacım yok. Python'da sadece pyparsing kullanarak yapmak için buna ihtiyacım var. Sözdizimi yazılır düzeltildi ve bu özyinelemeli çözümleyici kullanılarak yapılabilir olduğunu düşünüyorum. –

+0

@asb: Diğer insanlar bu tür şeyler için özyinelemeli ayrıştırıcılar kullanmıyorlar. Bu nedenle, kafa karıştırıcı özyinelemeyi ortadan kaldırmak için tanımı (sözdizimini değil, tanımlandığı şekilde değiştirirseniz) daha başarılı olabileceğinizi öneririm. –

3

@ S.Lott ile aynı fikirdeyseniz dilbilginizi tekrar gözden geçirmelisiniz.

özyineli tanımlamalar Forward() kullanılarak eklenebilir:

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})") 

Çıktı:

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

bu herhangi bir yardım, ama burada sen istediğini yapacağını nasıl olup olmadığını bilmiyorum lepl. Dilbilgisi doğru göründüğünden, pıhtılaşmayı tercüme etmenin kolay olacağını varsayardım.

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})') 

çıktısı:

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']