2010-06-07 12 views
7

Sto convertendo un codice Haskell funzionante che utilizza Parsec per utilizzare invece Attoparsec nella speranza di ottenere prestazioni migliori. Ho apportato le modifiche e tutto viene compilato, ma il mio parser non funziona correttamente.Problema con input incompleto quando si utilizza Attoparsec

Sto analizzando un file che comprende vari tipi di record, uno per riga. Ognuna delle mie singole funzioni per analizzare un record o un commento funziona correttamente, ma quando provo a scrivere una funzione per compilare una sequenza di record, il parser restituisce sempre un risultato parziale perché si aspetta un input maggiore.

Queste sono le due varianti principali che ho provato. Entrambi hanno lo stesso problema.

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

Per questo secondo ho modificato i parser di record/commenti per consumare i caratteri di fine riga.

items :: Parser [Item] 
items = manyTill (comment <|> recordType1 <|> recordType2) endOfInput 

C'è qualcosa di sbagliato nel mio approccio? C'è un altro modo per ottenere ciò che sto tentando?

risposta

2

ho incontrato questo problema prima e la mia comprensione è che è causato dal modo in cui <|> opere nella definizione di sepBy:

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

Ciò sposterà solo per pure [] volta (s *> scan) ha fallito , che non accadrà solo perché sei alla fine dell'input.

La mia soluzione è stata solo per chiamare feed con una empty ByteString sul Result restituito da parse. Questo potrebbe essere una specie di hack, ma sembra anche di essere come attoparsec-iteratee affronta la questione:

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

Per quanto posso dire questo è l'unico motivo che attoparsec-iteratee opere qui e pianura vecchio parse non lo fa .

+0

Grazie, questo ha risolto il mio problema. –

0

Si danno poche informazioni e questo è il motivo per cui penso che sia difficile dare un buon aiuto. Tuttavia ci sono un paio di commenti che vorrei dare:

  • Forse il parser non si rende conto che l'input è terminato e dipende da come ottenere un EOL o ottenere un altro record. Quindi chiede un risultato parziale. Prova a darle l'equivalente di EOL nella speranza che lo costringa.
  • Non riesco a ricordare il codice, ma l'utilizzo dell'istanza Alternativa potrebbe essere dannoso per l'analisi delle prestazioni. Se questo è il caso, potresti voler scrivere sul commento e su recordTypes.
  • Uso i cereali per parecchie analisi binarie e anche estremamente veloce. attoparsec sembra comunque meglio come parser di testo. Dovresti assolutamente considerare l'opzione.
  • Un'altra opzione è utilizzare l'IO basato su iteratee nel più lungo tempo. John Lato ha fatto un eccellente articolo su iteratees nell'ultimo lettore di monade (n. 16 credo). La condizione di fine linea sono le iterate da segnalare. Attenzione però che i tipi di iteratee sono piuttosto scoraggianti e prendetevi del tempo per abituarvi.
+0

Grazie per i suggerimenti. Ho provato a ridurre il parser alla versione minima che presenta il problema, come la rimozione delle alternative e la semplice sequenza di commenti. In GHCi la funzione di commento funziona come mi aspetto, ma la funzione degli elementi è problematica. Mi stavo chiedendo se c'era qualcosa di fondamentalmente sbagliato nel mio approccio. Sono felice di condividere qualsiasi informazione aggiuntiva che potrebbe essere utile. Ho provato a darle un extra EOL ma non ha fatto differenza. Ho visto iteratees menzionati in alcuni punti ma non li ho mai visti prima, quindi stavo cercando di evitarli per il momento. –

5

Se si scrive un parser attoparsec che consuma il maggior numero possibile di input prima di fallire, è necessario indicare la continuazione del risultato parziale quando si è raggiunta la fine dell'input.

+5

Quindi 'feed' è in realtà il modo corretto di affrontare questa situazione? Potrebbe essere una buona idea renderlo un po 'più chiaro nella documentazione, lo so che mi ha confuso quando l'ho incontrato per la prima volta. –

Problemi correlati