Sto cercando di analizzare un linguaggio molto semplice che consiste solo di numeri decimali o binari. Ad esempio, qui ci sono alcuni input validi:Perché sembra che l'operatore Parsec Choice dipenda dall'ordine dei parser?
#b1
#d1
#b0101
#d1234
Sto avendo un problema utilizzando del Parsec dell'operatore scelta: <|>
. Secondo il tutorial: Write yourself a Scheme in 48 hours:
[L'operatore di scelta] prova il primo parser, quindi se fallisce, prova il secondo. Se uno dei due riesce, restituisce il valore restituito da quel parser.
Ma nella mia esperienza, vedo che l'ordine dei parser ha fornito argomenti. Qui è il mio programma:
import System.Environment
import Text.ParserCombinators.Parsec
main :: IO()
main = do
(x:_) <- getArgs
putStrLn ("Hello, " ++ readExp x)
bin :: Parser String
bin = do string "#b"
x <- many(oneOf "01")
return x
dec :: Parser String
dec = do string "#d"
x <- many(oneOf "")
return x
-- Why does order matter here?
parseExp = (bin <|> dec)
readExp :: String -> String
readExp input = case parse parseExp "test" input of
Left error -> "Error: " ++ show error
Right val -> "Found val" ++ show val
Ecco come sto facendo funzionare il programma:
Installazione dipendenze
$ cabal sandbox init
$ cabal install parsec
Compilazione
$ cabal exec ghc Main
Run
$ ./Main "#d1"
Hello, Error: "test" (line 1, column 1):
unexpected "d"
expecting "#b"
$ ./Main "#b1"
Hello, Found val"1"
.210
Se cambio l'ordine dei parser come segue: vengono rilevati
parseExp = (dec <|> bin)
allora solo numeri binari e il programma non identifica il numeri decimali.
Con i test che ho eseguito, vedo che questo problema si verifica solo quando uno dei parser ha iniziato l'analisi di un input, ad es. se viene trovato un carattere hash #
, viene attivato il parser bin che termina con esito negativo in quanto il carattere successivo previsto è b
e non d
. Sembra che dovrebbe esserci una specie di backtracking che dovrebbe accadere, cosa di cui non sono a conoscenza.
Apprezzo l'aiuto!
Ma nel mio caso il primo parser non riesce. Viene attivato dal momento che il primo carattere corrisponde, ma fallisce in seguito in quanto non trova il prossimo personaggio previsto. Mi aspetto che il prossimo parser debba essere attivato ma ciò non accade come puoi vedere dall'output che ho incollato. – mandark
@mandark Questo dipende dal modo in cui funziona parsec. Io modifico – chi
Ancora più sorprendente, ho visto parser 'attoparsec' che possono avere successo o fallire a seconda dell'ordine degli argomenti a' <|> '. Dovrò fare la mia domanda al riguardo. – dfeuer