2016-05-30 52 views
14

Dire che voglio analizzare un file in lingua X. Davvero, mi interessa solo una piccola parte delle informazioni all'interno. È abbastanza facile scrivere un parser in uno dei numerosi eDSL di Haskell a tale scopo (ad esempio Megaparsec).Esiste un modo stabilito per scrivere parser in grado di ricostruire il loro input esatto?

data Foo = Foo Int -- the information I'm after. 

parseFoo :: Parsec Text Foo 
parseFoo = ... 

Che prontamente dà origine a una funzione getFoo :: Text -> Maybe Foo.

Ma ora mi piace anche per modificare la fonte delle informazioni Foo, cioè fondamentalmente voglio implementare

changeFoo :: (Foo -> Foo) -> Text -> Text 

con le proprietà

changeFoo id ≡ id 
getFoo . changeFoo f ≡ fmap f . getFoo 

E 'possibile farlo con cambiare il risultato del parser in qualcosa come un obiettivo

parseFoo :: Parsec Text (Foo, Foo -> Text) 
parseFoo = ... 

ma ciò rende la definizione molto più ingombrante – Non riesco a ignorare più informazioni irrilevanti, ma è necessario memorizzare la corrispondenza di ogni string subparse e rimontarla manualmente.

Questo potrebbe essere un po 'automatizzato mantenendo la stringa-riassemblare in un livello StateT attorno alla monade del parser, ma non potrei semplicemente usare i parser primitivi esistenti.

Esiste una soluzione esistente per questo problema?

+0

Analisi librerie generalmente costruire un "Abstract Syntax Tree", che lascia fuori tutta la formattazione. Quello che stai cercando è un "Concrete Syntax Tree". Non conosco alcuna libreria che costruisca questo. – sapanoia

risposta

1

Una soluzione implementata in Haskell? Non ne conosco uno; possono esistere.

In generale, tuttavia, è possibile memorizzare un numero sufficiente di informazioni per rigenerare una versione legale del programma che assomiglia all'originale a un livello arbitrario, memorizzando le informazioni di "formattazione" con i token raccolti. Nel limite, le informazioni sul formato sono la stringa originale per il token; qualsiasi approssimazione di ciò darà risposte meno accurate.

Se si mantengono spazi bianchi come token espliciti nell'albero di analisi, nel limite è possibile anche rigenerarlo. Se ciò è utile probabilmente dipende dall'applicazione. In generale, penso che questo sia eccessivo.

dettagli su cosa/come catturare e come rigenerare possono essere trovati nel mio SO rispondere: Compiling an AST back to source code

1

Si tratta di un caso di "trasformazione bidirezionale"? Ad esempio, http://ceur-ws.org/Vol-1571/

In particolare, "Descrizione invertibile Sintassi: Unifying analisi e la stampa piuttosto" di Rendel e Osterman http://dblp.org/rec/conf/haskell/RendelO10, Haskell Symposium 2010 (cfr http://lambda-the-ultimate.org/node/4191)

+1

Sì, è un ottimo lavoro; ma è davvero il mio problema? Avevo l'impressione che questi parser invertibili garantissero principalmente l'analisi. stampa ≡ id'. Possono anche assicurare qualcosa su 'stampa. parse'? – leftaroundabout

+0

Se si stampa in modo soddisfacente, quindi 'stampa (parse s) === s' modulo spazio bianco?Dovrebbe essere ancora più semplice creare stampanti/parser di base per la stampa esatta. – d8d0d65b3f7cf42

+2

Bene, il fatto è che nella mia applicazione _most_ del file è "spazio bianco" (o meglio "commenti"), dal momento che non mi preoccupo di analizzare realmente la maggior parte del contenuto in dettaglio, solo poche variabili. – leftaroundabout