2016-03-20 5 views
2

Wenn ich diesen Code haben:Parsec seltsame Fehler erzeugen, wenn sie vielleicht als ParseError zu behandeln versuchen

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 

wenn ich testparser mit Eingang testen, wie diese "-1 3" gibt es:

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

Ich erwartete, dass es Fehler in Spalte 1 gibt und die Fehlermeldung ohne den Satz "Unerwartetes 3" gibt, aber es scheint, Parsec fortgesetzt Parsing.

Warum ist das passiert? und wie parsec die Fehlermeldung geben, die ich erwarte?

Antwort

1

Ich habe die Lösung gefunden, die Ursache davon ist, dass der erste Parser ausgeführt wird und Eingaben verbraucht, selbst wenn es scheitert.

wurde die Lösung lookAhead wie folgt zu verwenden:

(<!>) :: (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)) 

wenn lookAhead p1 kehrt Nothing dann das erste Argument von *> ohne Eingabe aufwendig wegen lookAhead würde scheitern, wenn jetzt lookAhead p1 kehrt Just res dann würde es wieder gelingen, ohne aufwändige Eingabe, und das Ergebnis würde aus dem zweiten Argument von *> erhalten werden.

natürlich musste ich parserfrommaybe Typ Annotation zu (Monad m) => String -> (Maybe c) -> ParsecT a b m c ändern, um ghc zu befriedigen.

+0

Nur um darauf hinzuweisen, wird dies furchtbar ineffizient sein - 'p1' wird fast immer zweimal geparst. Das Problem ist einfacher - wenn eine negative Ganzzahl nicht gültig ist, warum dann das negative Symbol überhaupt analysieren? Und wenn Sie negative Ganzzahlenfehler speziell melden möchten (Sie müssen also das negative Zeichen analysieren), sollten Sie 'parserFail' verwenden (und nicht' ispositiv <$> ..' - das 'Nothing' stellt keinen Fehler in der Art dar, wie Sie es tun denke hier), wenn du auf eine negative ganze Zahl stößt - dies wird einen tatsächlichen Parserfehler verursachen, direkt nach der negativen ganzen Zahl. '' kann nicht dazu führen, dass ein Parser fehlschlägt. – user2407038

Verwandte Themen