2010-06-07 11 views
7

kullanırken eksik girdiyle ilgili sorun Parsec kullanan bazı çalışan Haskell kodlarını dönüştürerek daha iyi performans elde etme umuduyla Attoparsec'i kullanıyorum. Değişiklikleri yaptım ve her şey derleniyor ama benim çözümleyici düzgün çalışmıyor.Attoparsec

Her satırda bir tane olmak üzere çeşitli kayıt türlerinden oluşan bir dosyayı ayrıştırma yapıyorum. Bir kaydı veya yorumu ayrıştırmak için her bir bireysel işlevim doğru çalışır, ancak bir kayıt dizisini derlemek için bir işlev yazmaya çalıştığımda, ayrıştırıcı her zaman daha fazla girdi beklediği için kısmi bir sonuç döndürür.

Bunlar, denediğim iki ana varyasyon. Her ikisinin de aynı sorunu var.

items :: Parser [Item] 
items = sepBy (comment <|> recordType1 <|> recordType2) endOfLine 

Bu ikincisi için satır sonu karakterlerini tüketmek için kayıt/yorum ayrıştırıcılarını değiştirdim.

Yaklaşımımla ilgili bir sorun var mı? Denediğim şeyi başarmanın başka bir yolu var mı?

cevap

2

Bunu daha önce sorunla karşılaştık ve benim anlayış sepBy tanımında <|> eserler biçimi nedeniyle ortaya oluyor ki: (s *> scan) başarısız bir kez

sepBy1 :: Alternative f => f a -> f s -> f [a] 
sepBy1 p s = scan 
    where scan = liftA2 (:) p ((s *> scan) <|> pure []) 

Bu yalnızca pure [] hareket edecek Sadece girişin sonunda olduğun için olmayacak.

Benim çözümüm sadece parse tarafından döndürülen Result bir empty bytestring ile feed aramaya olmuştur. Bu hack tür olabilir, ama aynı zamanda gibi görünüyor nasıl konuyla attoparsec-iteratee fırsatlar:

f k (EOF Nothing) = finalChunk $ feed (k S.empty) S.empty 

Bildiğim kadarıyla şunu söyleyebilirim eski parse değil attoparsec-iteratee eserler burada olduğunu ve düz tek nedeni .

+0

Teşekkürler, bu benim sorunumu çözdü. –

0

Size oldukça az bilgi veriyorsunuz, bu yüzden size iyi bir yardım vermenin zor olduğunu düşünüyorum.

  • Belki ayrıştırıcı giriş yapıldığını fark etmez ve bir EOL alma veya başka bir rekora alma ya dayanıyor: Ancak orada isterim yorumların bir çift vermek için vardır. Bu nedenle kısmi bir sonuç ister. Onu zorlarsa umut EOL eşdeğerini beslemeye çalışın.
  • Kodu hatırlayamıyorum, ancak Alternatif örneğini kullanmak, performansı ayrıştırma açısından zararlı olabilir. Bu durumda, yorum ve recordTypes üzerinde isteyebilirsiniz.
  • Çok sayıda ikili ayırma için tahıl kullanırım ve bu da son derece hızlıdır. Attoparsec olsa da bir metin ayrıştırıcı olarak daha iyi görünüyor. Bu seçeneği kesinlikle düşünmelisiniz.
  • Başka bir seçenek, daha uzun vadede yinelemeli IO kullanmaktır. John Lato, son monad okuyucusunda iterate'ler hakkında mükemmel bir makale yaptı (inanıyorum # 16). Hat sonu durumu, sinyal verilecek iteratlardır. Yinelenen türlerin oldukça ürkütücü olmasına ve alışmak için biraz zaman almasına dikkat edin.
+0

Öneriler için teşekkürler. Ayrıştırıcıyı, alternatifleri kaldırmak ve yalnızca bir dizi yorum yapmak gibi sorunu gösteren en küçük sürüme indirmeyi denedim. GHCi'de yorum işlevi beklediğim gibi çalışır, ancak öğeler işlevi sorunludur. Yaklaşımım ile temelde yanlış bir şey olup olmadığını merak ediyordum. Faydalı olabilecek ekstra bilgileri paylaştığımız için mutluyum. Ekstra bir EOL beslemeye çalıştım ama hiçbir fark yaratmadı. Birkaç yerde bahsettiğim yinelemeleri gördüm ama onlarla daha önce karşılaşmadım, bu yüzden an için bunlardan kaçınmaya çalışıyordum. –

5

Hata vermeden önce olabildiğince fazla girdi alan bir attoparsec çözümleyici yazarsanız, girişinizin sonuna ulaştığınızda kısmi sonuç devam ettiğini bildirmeniz gerekir.

+5

Yani 'besleme' aslında bu durumla başa çıkmak için doğru yoldur? Bunu dokümantasyonda biraz daha açık hale getirmek iyi bir fikir olabilir - ilk karşılaştığımda beni şaşırttı biliyorum. –