2008-11-02 33 views
6

sayı dizeleri ve değişken dizeleri arasında ayrım:Scala combinator ayrıştırıcılar - Ben numaraları ve bir maç açıklamada değişkeni temsil dizeleri temsil dizeleri arasında ayrım yapmak en iyi yolu hakkında merak, ben Cay Horstmann en combinator ayrıştırıcı egzersizleri yapıyorum

def factor: Parser[ExprTree] = (wholeNumber | "(" ~ expr ~ ")" | ident) ^^ { 
    case a: wholeNumber => Number(a.toInt) 
    case a: String => Variable(a) 
} 

İkinci satırda, "case a: wholeNumber" yasal değildir. Bir regexp hakkında düşündüm, ama "case" ile çalışmak için bir yol bulamadım.

cevap

6

Biraz ayırır ve vaka analizini |'a aktarırdım.

def factor: Parser[ExprTree] = (wholeNumber ^^ { Number(_.toInt) } 
           | "(" ~> expr <~ ")" 
           | ident ^^ { Variable(_) }) 

Eğer alt çizgi sözdizimi ile aşina değilseniz özür dilerim: Bu genel olarak, bağdaştırıcılarla ve gerçekten LL (*) ayrıştırma avantajlarından biridir. Temel olarak sadece "n th parametresini, kapanış fonksiyon değerine" geçmesi anlamına gelir. Böylece { Variable(_) }, { x => Variable(x) }'a eşdeğerdir.

Burada bir başka sözdizimi sihri örneği, ~ yerine ~> ve <~ işleçleridir. Bu işleçler, bu dönemin ayrıştırılmasının her iki parselin sözdizimi içermesi gerektiği anlamına gelir, ancak sonuç yalnızca expr sonucuyla belirlenmelidir. Böylece, "(" ~> expr <~ ")" tam olarak "(" ~ expr ~ ")" ile aynı şeyle eşleşir, ancak iç sonuç değerini expr'dan almak için fazladan durum analizi gerektirmez.

+0

Mükemmel! {Number (_. ToInt)} öğesini {x: String => Number (x)} olarak değiştirdim çünkü "error: genişletilmiş fonksiyon için parametre tipi eksik", sonra bir cazibe gibi çalıştı. Yine de bunu çözmek için bir vaka sınıfı yolu varsa merak ediyorum. –

+0

Aslında, durum sadece kısmi bir işlevi tanımlar. Girdi üzerinde desen eşleştirmesi yapmanıza izin verir, bu da gerçekten neden yararlıdır. Cevabımı kısmi işlevler (vaka) kullanarak kolayca yazabildim, sadece gerekli değildi. :-) (~> ve <~) –

+0

dışında olurdu. Eğer bütün terimle eşleşmeyi kastediyorsan, cevabın "hayır, bunu yapmanın bir yolu yok" olduğunu düşünüyorum. "AllNumber" yöntemi String'den farklı bir bileşen türüne sahip bir Parser döndürmedikçe, 'ident' veya '("~> expr <~")' den ayırt etmenin gerçekten hiçbir yolu yoktur. –