Domanda

Esiste un parser che genera un albero AST / parse in fase di esecuzione? Un po 'come una libreria che accetterebbe una stringa di grammatica EBNF o qualcosa di analogo e sputerebbe fuori una struttura di dati?

  • Sono a conoscenza di antlr, jlex e dei loro simili. Generano il codice sorgente che potrebbe farlo. (ad esempio saltare il passaggio di compilazione)
  • Sono a conoscenza di Boost :: Spirit, che usa un po 'di magia nera con sintassi C ++ per generare tali cose al momento dell'esecuzione (decisamente molto più vicino a quello che voglio, ma sono un vago quando si tratta di C ++. E è ancora alquanto limitante, perché la tua grammatica è hardcoded)
  • Non sono a conoscenza di nulla in Python o Ruby, anche se un compilatore del compilatore potrebbe benissimo essere efficace in un tale linguaggio ...

Ora sono a conoscenza dei combinatori di parser. (grazie Jonas) E alcune biblioteche (grazie eliben)

per inciso, ho anche notato Parsing Expression Grammars ultimamente, che suona bene erano qualcuno per implementarlo (dicono che Perl 6 lo avrà, ma Perl sfugge alla mia comprensione)

È stato utile?

Soluzione

Dai un'occhiata a combinatori di parser che penso possano aiutarti. È possibile creare parser in fase di esecuzione usando questa tecnica. Un noto combinatore di parser è Parsec che utilizza Haskell come lingua host. Dalla documentazione parsec :

  

I parser combinatori sono scritti e utilizzati nello stesso linguaggio di programmazione del resto del programma. Non vi è alcun divario tra il formalismo grammaticale (Yacc) e l'attuale linguaggio di programmazione utilizzato (C)

     

I parser sono valori di prima classe all'interno della lingua. Possono essere inseriti in elenchi, passati come parametri e restituiti come valori. È facile estendere l'insieme disponibile di parser con parser su misura specifici per un determinato problema

Se stai utilizzando .NET dai un'occhiata alla libreria combinatore parser per F # .

Altri suggerimenti

Se Java è meglio per te, esiste una porta della libreria Haskell Parsec - JParsec . Molto potente, sebbene la documentazione non sia eccezionale.

Puoi costringerlo a fare un lex diretto quindi analizzare la fase, ma puoi fare alcune cose interessanti con il lessing dinamico e le grammatiche dinamiche.

Roba da capogiro.

Poiché è tutto in Java (il tuo Parser è un POJO), puoi fare il refactoring e fare TDD, e tutto ciò che sei abituato a fare in Java. Questo è un grande vantaggio di un approccio più tradizionale ANTLR / JavaCC / JJTree.

Lambda the Ultimate ha discusso di un parser che consente estensioni di sintassi .

  

Sto progettando di scrivere un compilatore che consenta di estendere la sintassi (una sorta di metaprogrammazione in fase di compilazione). Non voglio avere un sistema molto potente, quindi ho pensato di avere solo:

{syntax: while (condition) do code}
while (condition, code) => // actual execution
     

e sostituisci ogni modello che corrisponde alla sintassi con una chiamata alla funzione.   Tuttavia, non so da dove cominciare per far funzionare il lexer e il parser, perché i soliti strumenti come Flex / Bison o ANTLR (vorrei scrivere il compilatore in C #) non sembrano permettere questo.

     

Potresti fornirmi qualche direzione su dove andare dopo? Ho anche letto che Scheme o Haskell potrebbero essere lingue migliori per raggiungere questo obiettivo. E, naturalmente, sono aperto a qualsiasi suggerimento sull'idea reale di implementarli.

Sì, certo!

In tutti i linguaggi dinamici, questo è molto semplice da ottenere, poiché il codice può essere facilmente generato e valutato in fase di esecuzione. Consiglierò due alternative:

  • In Perl, usa Parse :: RecDescent. Prende la sua grammatica da una stringa e puoi sicuramente chiedergli di generare un nuovo parser da una nuova stringa in fase di esecuzione.
  • In Python, considera PLY. Puoi facilmente generare le funzioni con docstrings in fase di esecuzione ed eseguire PLY su di esso.

Consiglio personalmente l'opzione Python, anche se potrebbe non essere rilevante se conosci Perl ma non Python.

Per completezza, devo notare che puoi farlo con Lex & amp; Anche Yacc, ma è peloso. Dovrai generare un file Lex / Yacc dalla tua grammatica in fase di runtime, compilarlo in C, compilarlo in una lib condivisa e caricarlo in fase di runtime. Sembra fantascienza, ma alcuni strumenti lo fanno per esigenze complesse di efficienza e dinamicità.

Buona fortuna.

JFlex , l'estensione JLex Java, ti consente di eseguire la compilazione del tempo di esecuzione, ma è roba piuttosto pelosa.

Che cosa hai intenzione di analizzare? In C o C ++ non avrai un parser in runtime, quindi non è disponibile senza una libreria aggiuntiva. Per molti linguaggi di programmazione questo è vero però.

Per impostazione predefinita, tutti i parser sono "dinamici" quando vengono implementati. Anche in C.

Se la lingua che stai per analizzare è la tua: scrivere parser è una cosa da imparare da sola. Anche con i generatori di parser è un'opera in sé. Dopo averlo imparato, però, diventerà piuttosto semplice. Trucchi speciali come la sintassi rientrata saranno comunque difficili, e avrai bisogno di test validi e approfonditi per vedere che il parser fa quello che vuoi. Ho scritto un parser così lo so.

[Dropincc.java] http://pfmiles.github.com/blog/dropincc-dot-java-the-ultimate-tool-to-create-dsls-in-java/ " Dropincc.java è un parser dinamico generatore in java puro " ;.

Ciò ti consente di definire le regole grammaticali nel linguaggio di programmazione Java e non è necessario apprendere ulteriori notazioni. Nessun altro strumento da riga di comando deve essere utilizzato. Potresti definire, compilare ed "valutare" il tuo linguaggio appena definito in puro java.

Controlla il link qui per ottenere maggiori informazioni.

[Home page dei progetti] https://github.com/pfmiles/dropincc.java

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top