2013-01-11 13 views
13

Ich bin ein wenig verwirrt durch dieses Verhalten von attoparsec.Warum sehe ich Teilergebnisse mit attoparsec, wenn ich Fehler erwarte?

$ ghci 
> :m Data.Attoparsec.Text 
> :m + Data.Text 
> parse (string (pack "module")) (pack "mox") 
Partial _ 
> parse (string (pack "module")) (pack "moxxxx") 
Fail "moxxxx" [] "Failed reading: takeWith" 
> 

Warum brauche ich zusätzliche Zeichen vorhanden, um den Fehler auszulösen?

Sollte es nicht scheitern, sobald das erste "x" gefunden wird?

+0

Für zukünftige Referenz, öffnete ich ein Ticket und der Attarsec-Maintainer behoben diesen Fehler: https://github.com/bos/attoparsec/issues/97 –

Antwort

13

Es ist ein Implementierungsdetail, ein string Parser wird nicht beendet, bevor es weiß, ob genug Eingaben übrig sind, damit es möglicherweise erfolgreich ist. Es ist eine Konsequenz des Alles-oder-Nichts-Verhaltens dieser Parser (was meiner Meinung nach im Allgemeinen für die Leistung gut ist).

string :: Text -> Parser Text 
string s = takeWith (T.length s) (==s) 

string s versucht length s Einheiten Text, zu nehmen und sie dann mit s vergleichen.

takeWith :: Int -> (Text -> Bool) -> Parser Text 
takeWith n p = do 
    s <- ensure n 
    let h = unsafeTake n s 
     t = unsafeDrop n s 
    if p h 
    then put t >> return h 
    else fail "takeWith" 

takeWith n p zuerst versucht, um sicherzustellen, dass n Einheiten Text zur Verfügung stehen, und

ensure :: Int -> Parser Text 
ensure !n = T.Parser $ \i0 a0 m0 kf ks -> 
    if lengthAtLeast (unI i0) n 
    then ks i0 a0 m0 (unI i0) 
    else runParser (demandInput >> go n) i0 a0 m0 kf ks 
    where 
    go n' = T.Parser $ \i0 a0 m0 kf ks -> 
     if lengthAtLeast (unI i0) n' 
     then ks i0 a0 m0 (unI i0) 
     else runParser (demandInput >> go n') i0 a0 m0 kf ks 

ensure n schafft eine Fortsetzung für mehr Haferschleim Eingang zu fragen (a Partial Ergebnis), wenn es nicht findet genug Eingabe sofort.

Sie einen Fehler mit

Prelude Data.Attoparsec.Text Data.Text> parseOnly (string (pack "module")) (pack "mox") 
Left "not enough input" 

sagen, den Parser vorne bekommen können, dass es nicht mehr Eingang (dann die demandInput von ensure macht es gescheitert) erhalten wird, oder später

Prelude Data.Attoparsec.Text Data.Text> parse (string (pack "module")) (pack "mox") 
Partial _ 
Prelude Data.Attoparsec.Text Data.Text> feed it (pack "") 
Fail "mox" ["demandInput"] "not enough input" 

durch das Erzählen der Partial Ergebnis, dass das war, fütterte es eine leere Text.

+0

Danke - das macht Sinn nach Ihrer Erklärung. – timbod

Verwandte Themen