2013-02-06 22 views
7

Nel LLVM tutorials c'è un'istruzione su come scrivere un semplice compilatore JIT. Unfortunatelly, lexer e parser in questo tutorial sono scritti manualmente. Stavo pensando, tale soluzione è buona per scopi di apprendimento, ma non è adatta per la scrittura di compilatori complessi, pronti per la produzione. Sembra che GCC e pochi altri "grandi compilatori" siano scritti a mano. Ma penso che tutti questi generatori di parser danno una grande spinta quando si scrive il proprio compilatore (specialmente quando lo fai da solo, senza un gruppo di persone).LLVM JIT Parser scrittura con Bison/Antlr/Packrat/Elkhound/

È possibile utilizzare qualsiasi generatore di parser esistente come Bison/Antlr/Packrat/Elkhound ecc. Insieme a LLVM per creare il compilatore JIT? Voglio essere in grado di "alimentare" il parser costantemente (non una volta all'inizio) con le espressioni e compilarle in runtime.

In aggiunta Ho trovato un sacco di domande sul generatore di parser "migliore, moderno" (come questo: https://stackoverflow.com/questions/428892/what-parser-generator-do-you-recommend). Se è possibile utilizzare questi strumenti per creare il compilatore JIT LLVM, sarei grato per eventuali suggerimenti e raccomandazioni aggiuntivi, quale strumento sarebbe il migliore in termini di prestazioni e flessibilità in questo caso particolare.

+0

"Tale soluzione è utile per scopi di apprendimento ma non è adatta per la scrittura di compilatori complessi, pronti per la produzione" - Hm. Ho sempre pensato che GCC fosse un compilatore complesso e pronto per la produzione. Qualunque cosa ... –

+0

GCC stava usando il bisonte all'inizio, ma hai ragione - lo sto sistemando nella mia domanda. Ma davvero, mi piacerebbe usare un generatore per semplificare questo compito se è possibile. –

+5

Semmai, direi piuttosto è vero il contrario: yacc, Bison e altri sono adatti per scopi di apprendimento e simili, ma per un serio lavoro di produzione, un parser scritto a mano può essere l'unico modo per soddisfare i requisiti. –

risposta

9

Ci sono molti vantaggi nell'usare un generatore di parser come bisonte o antlr, in particolare mentre si sta sviluppando una lingua. Indubbiamente finirai per apportare modifiche alla grammatica mentre andrai, e vorrai finire con la documentazione della grammatica finale. Gli strumenti che producono automaticamente una grammatica dalla documentazione sono davvero utili. Possono anche aiutarti a darti fiducia che la grammatica della lingua sia (a) ciò che pensi sia e (b) non ambigua.

Se la tua lingua (a differenza di C++) è in realtà LALR (1), o anche meglio, LL (1), e stai utilizzando gli strumenti LLVM per costruire AST e IR, allora è improbabile che tu debba fare molto più che scrivere la grammatica e fornire alcune semplici azioni per costruire l'AST. Questo ti farà andare avanti per un po '.

La solita ragione per cui le persone scelgono di creare i propri parser, a parte i "programmatori reali non usano i parser dei parser generatori", è che non è facile fornire una buona diagnostica per gli errori di sintassi, in particolare con LR (1) analisi. Se questo è uno dei tuoi obiettivi, dovresti provare a rendere la grammatica LL (k) analizzabile (non è ancora facile fornire una buona diagnostica con LL (k), ma sembra essere un po 'più semplice) e usare un LL (k) quadro come Antlr.

C'è un'altra strategia, che consiste nel analizzare il testo del programma nel modo più semplice possibile utilizzando un parser LALR (1), che è più flessibile di LL (1), senza nemmeno tentare di fornire la diagnostica. Se l'analisi fallisce, è quindi possibile analizzarla di nuovo usando un parser più lento, possibilmente anche backtracking, che non sa come generare AST, ma tiene traccia della posizione della sorgente e tenta di recuperare dagli errori di sintassi. Recuperare da errori di sintassi senza invalidare l'AST è ancora più difficile che continuare a analizzare, quindi c'è molto da dire per non provare. Inoltre, tenere traccia della posizione della sorgente è molto lento e non è molto utile se non si deve produrre la diagnostica (a meno che non sia necessario per aggiungere annotazioni di debug), così è possibile velocizzare il parsing un po 'non preoccupandosi di localizzazione della posizione

Personalmente, sono prevenuto contro l'analisi del packrat, perché non è chiaro quale sia l'effettiva lingua analizzata da un PEG. Altre persone non si preoccupano così tanto di questo, e YMMV.

+1

Perché "non è chiaro" qual è la lingua attuale? PEG è ben definito, anche con tutti gli hacks fantastici che packrat consente di fare (parsing e così via). –

+1

@ SK-logic: ben definito non è lo stesso di chiaro. Un parser fatto a mano scritto in C++ è ben definito. Una macchina di Turing è ben definita. Sì, il PEG è ben definito. Ma per tutti loro, l'unico modo per vedere se una determinata stringa è nella lingua è eseguire il codice. (Di queste tre alternative, PEG è la meno peggio, ma preferisco ancora grammatiche libere da contesto, ma come ho detto altre persone come PEG e qualsiasi cosa funzioni per te è fantastica con me.) – rici

+0

Dalla mia esperienza pratica I PEG sono le grammatiche più chiare e facili da leggere. Posso tradurre una specifica del linguaggio direttamente in un PEG con pochissime modifiche. Ovviamente è possibile offuscarlo, ma non ho ancora visto una grammatica davvero pessima. Considerando che ci sono molte grammature illeggibili oltre ogni speranza Yacc. –