Le lingue moderne usano ancora generatori di parser?


38

Stavo facendo ricerche sulla suite di compilatori gcc su wikipedia qui , quando è venuto fuori questo:

GCC iniziò usando i parser LALR generati con Bison, ma gradualmente passò ai parser scritti in discesa ricorsiva scritti a mano; per C ++ nel 2004, e per C e Objective-C nel 2006. Attualmente tutti i front-end usano parser scritti a mano ricorsivi-discendenti

Quindi con quest'ultima frase (e per quanto mi fidi di Wikipedia) posso sicuramente dire che "C (gcc), C ++ (g ++), Objective-C, Objective-C ++, Fortran (gfortran), Java (gcj), Ada (GNAT), Go (gccgo), Pascal (gpc), ... Mercury, Modula-2, Modula-3, PL / I, D (gdc) e VHDL (ghdl) "sono tutti front-end che no utilizzare più un generatore di parser. Cioè, usano tutti parser scritti a mano.

La mia domanda allora è: questa pratica è onnipresente? In particolare, sto cercando risposte esatte a "l'implementazione standard / ufficiale di x ha un parser scritto a mano" per x in [Python, Swift, Ruby, Java, Scala, ML, Haskell]? (In realtà, anche le informazioni su altre lingue sono benvenute qui.) Sono sicuro di poterlo trovare da solo dopo molte ricerche. Ma sono anche sicuro che questo sia facilmente rispondibile dalla comunità. Grazie!


3
Punto dati: CPython ha un generatore di parser LALR (pgen) preparato in casa. Non so il resto.

8
Punto dati: Ghc (haskell) usa un generatore di parser LALR (felice), così come OCaml.
Twan van Laarhoven,

1
Dovrebbe essere "Esegui compilatori moderni ad alte prestazioni ..." o simili, perché il linguaggio è la specifica non l'implementazione, mentre è il compilatore che utilizza o non utilizza un parser generato dalla macchina.
dmckee,

@dmckee, sì, hai ragione. Tuttavia, la denominazione inizia a diventare lunga e meno al punto. Sentiti libero di modificarlo se sei più creativo di me!
Eatonphil,

Per quanto riguarda ML: MLton utilizza un generatore di parser specifico per ML, sono sicuro al 90% che lo fa anche SML / NJ, anche se ne ho meno familiarità. Potresti o meno voler considerare questo "scritto a mano".
Patrick Collins,

Risposte:


34

AFAIK, GCC utilizzano in particolare parser scritti a mano per migliorare la diagnostica degli errori sintattici (ovvero fornire messaggi umani significativi sugli errori di sintassi).

La teoria di analisi (e i generatori di analisi che discendono da essa) riguarda principalmente il riconoscimento e l'analisi di una frase di input corretta . Ma ci aspettiamo dai compilatori che forniscano un messaggio di errore significativo (e che siano in grado di analizzare in modo significativo il resto dell'input dopo l'errore sintattico), per un input errato.

Inoltre, i vecchi linguaggi legacy -come C11 o C ++ 11- (che sono concettualmente vecchi, anche se la loro ultima revisione ha solo tre anni) non sono affatto senza contesto. Gestire la sensibilità del contesto in grammatiche per generatori di parser (cioè bisonti o anche menhir ) è noiosamente difficile.


2
Concur. Recuperare bene dagli errori di analisi (quando non si vuole smettere di analizzare al primo errore, come il vecchio Borland Pascal) e creare messaggi di errore di buona qualità (inclusi suggerimenti e suggerimenti per la risoluzione, come vogliono gli umani) sono entrambi intrinsecamente contesto - compiti euristici e sensibili. Possono essere fatti in cima all'output del generatore di parser di riserva, in qualche modo, ma è uno slog.
Jonathan Eunice,

2
Dealing with that context sensitiveness in grammars for parser generators is boringly difficult. È anche più o meno impossibile in quanto questi strumenti generano parser senza contesto. Il posto corretto per verificare se sono presenti tutti i vincoli sensibili al contesto è dopo aver generato l'albero di analisi se si utilizzano strumenti come questo.
dtech,

7

Generatori di parser e motori di analisi sono abbastanza generici. Il vantaggio della generalità è che costruire rapidamente un parser accurato e renderlo funzionale è semplice, nello schema generale delle cose.

Lo stesso motore parser soffre sul fronte delle prestazioni a causa della sua generalità. Qualsiasi codice scritto a mano sarà sempre significativamente più veloce rispetto ai motori di analisi basati su tabella.

La seconda area in cui i generatori / motori di parser hanno difficoltà è che tutti i linguaggi di programmazione reali sono sensibili al contesto, spesso in modi abbastanza sottili. I linguaggi LR sono privi di contesto, il che significa che ci sono molte sottigliezze sul posizionamento e sull'ambiente che sono impossibili da trasmettere correttamente nella sintassi. I grammatici attribuiti tentano di indirizzare le regole del linguaggio di base come "dichiarare prima dell'uso", ecc. Cablare questa sensibilità al contesto nel codice scritto a mano è semplice.


15
Citazione per la dichiarazione di prestazione per favore? Essere guidati da tabelle può essere una significativa ottimizzazione delle prestazioni e i generatori hanno accesso ad algoritmi che sono molto efficienti ma praticamente mai implementati a mano (proprio perché sono un pasticcio impenetrabile di tabelle e numeri magici).

2
E riguardo alla seconda area: molti dei principali linguaggi di programmazione reali non sono sensibili al contesto in alcun senso applicabile (dovresti fare riferimento all'insieme di tutti i programmi validi dopo il controllo del tipo e simili, che non è mai ciò che un scritto a mano o il parser generato tenta di analizzare). È vero che i parser scritti a mano sono più flessibili, e questo è utile per alcune lingue, ma principalmente nel regno del recupero e della segnalazione degli errori, dell'incremento, ecc. - I generatori di parser sono raramente evitati a causa del potere di riconoscimento (sia che voler scrivere una tale grammatica è una storia diversa). -1

Se si utilizzano le informazioni sulla tabella dei simboli durante l'analisi, è possibile anche chiamarle sensibili al contesto. Le grammatiche attribuite non sono assolutamente prive di contesto, anche se non credo che siano completamente sensibili al contesto. I tuoi altri punti sul recupero degli errori e sulla segnalazione sono ben presi.
BobDalgleish,

1
C e C ++ necessitano delle informazioni sulla tabella dei simboli durante l'analisi (o accettano un albero di analisi molto meno specifico in cui non viene fatta alcuna distinzione, ad esempio, tra espressioni di espressione e dichiarazioni di variabili). Ma non stavo pensando a quelli. Lingue come Java, Lisps, JavaScript, Ruby, Python, Go, Rust, Scala, Swift, Haskell (e probabilmente molti altri, forse anche C # e ML?) Non hanno bisogno di tali informazioni per costruire il tipo di AST che avresti voglio comunque. Molti di loro in realtà hanno grammatiche LL (1) o addirittura grammatiche LALR.

1
citazione per tutte le lingue reali sono sensibili al contesto, per favore?
ps
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.