2016-03-20 23 views
2

: Ben gibi girişli testparser test ettiğinizdeparsekten garip hatalar üretmek

import Text.Parsec 

ispositive a = if (a<0) then Nothing else (Just a) 

f a b = a+b 

parserfrommaybe :: String -> (Maybe c) -> Parsec a b c 
parserfrommaybe msg Nothing = fail msg 
parserfrommaybe _ (Just res) = return res  

(<!>) :: Parsec a b (Maybe c) -> String -> Parsec a b c 
(<!>) p1 msg = p1 >>= (parserfrommaybe msg)  

integermaybeparser = (ispositive <$> integer) <!> "negative numbers are not allowed" 
testparser = f <$> (integermaybeparser <* whiteSpace) <*> integermaybeparser 

bu "-1 3" o verir:

Left (line 1, column 4): 
unexpected "3" 
negative numbers are not allowed 

Ben sütun 1 hata vermek ve "beklenmedik 3" cümlesi olmadan hata iletisini vermek bekleniyor ama parsec ayrıştırma devam görünüyor.

Bu neden oldu? ve parsec'in beklediğim hata mesajını nasıl vermesi gerekir?

cevap

1

Çözümü bulduğumun nedeni, ilk ayrıştırıcının çalıştırılması ve başarısız olduğunda bile girdi tüketmesidir. lookAhead p1 döner Just res o zaman olmadan tekrar başarılı olup olamayacaklarını sonra *> ilk argüman şimdi, çünkü lookAhead girişini tüketmeden başarısız olur

(<!>) :: (Monad m,Stream a m t) => ParsecT a b m (Maybe c) -> String -> ParsecT a b m c 
(<!>) p1 msg = ((lookAhead p1) >>= (parserfrommaybe msg)) *> (p1 >>= (parserfrommaybe msg)) 

lookAhead p1 eğer getiri Nothing:

çözüm böyle lookAhead kullanmaktı Girdi tüketen ve sonuç *> ikinci argümanından elde edilebilir.

ghc'yi tatmin etmek içintip notunu (Monad m) => String -> (Maybe c) -> ParsecT a b m c olarak değiştirmek zorunda kaldım.

+0

Sadece dikkat çekmek için, bu korkunç derecede verimsiz olacak - 'p1' hemen hemen her zaman iki kez ayrıştırılıyor. Sorun daha basittir - negatif bir tam sayı geçerli değilse, neden negatif sembolü ayrıştırıyoruz? Negatif tamsayı hatalarını özel olarak bildirmek isterseniz (bu nedenle negatif işareti ayrıştırmanız gerekir), 'parserFail'i kullanmalısınız (ve' ispositive değil <$> .. '-' 'Nothing' size bir hata vermez Burada düşünün) negatif bir tam sayıyla karşılaştığınızda - bu, negatif tamsayıdan hemen sonra gerçek ayrıştırıcı hatasına neden olur. 'Bir ayrıştırıcının başarısız olmasına neden olamaz. – user2407038