it-swarm.it

Quali sono i principali vantaggi e svantaggi dell'analisi LL e LR?

Quando costruisco un parser in un linguaggio di programmazione cosa guadagno e cosa ho perso scegliendo l'uno o l'altro?

29
Maniero

Contrarrò l'analisi di LL e LR per una serie di criteri:

Complessità

LL vince qui, a mani basse. Puoi facilmente scrivere a mano un parser LL. In effetti, questo è comunemente fatto: il compilatore Microsoft C # è un parser di discesa ricorsivo scritto a mano (fonte qui , cerca un commento fatto da Patrick Kristiansen - anche il post sul blog è molto interessante).

L'analisi LR utilizza un metodo piuttosto intuitivo per analizzare un testo. Funziona, ma mi ci è voluto del tempo per capire come funziona esattamente. Scrivere un simile parser a mano è quindi difficile: si implementerebbe più o meno un generatore di parser LR.

Generalità

LR vince qui: tutte le lingue LL sono lingue LR, ma ci sono più lingue LR che lingue LL (una lingua è una lingua LL se può essere analizzata con un parser LL e una lingua è una lingua LR se può essere analizzata con un parser LR).

LL ha alcuni fastidi che ti ti darà fastidio durante l'implementazione di qualsiasi linguaggio di programmazione. Vedi qui per una panoramica.

Esistono lingue non ambigue che non sono lingue LR, ma sono piuttosto rare. Non incontri quasi mai queste lingue. Tuttavia, LALR ha alcuni problemi.

LALR è più o meno un hack per i parser LR per rendere le tabelle più piccole. Le tabelle per un parser LR possono in genere diventare enormi. I parser LALR danno la possibilità di analizzare tutte le lingue LR in cambio di tabelle più piccole. La maggior parte dei parser LR in realtà usa LALR (non segretamente, ma di solito puoi trovare esattamente ciò che implementa).

LALR può lamentarsi dei conflitti di riduzione-riduzione e riduzione-riduzione. Ciò è causato dall'hack della tabella: "piega" voci simili insieme, il che funziona perché la maggior parte delle voci sono vuote, ma quando non sono vuote genera un conflitto. Questi tipi di errori non sono naturali, difficili da capire e le correzioni sono di solito abbastanza strane.

Errori del compilatore e recupero degli errori

LL vince qui. In un'analisi LL, di solito è abbastanza facile emettere utili errori del compilatore, in particolare nei parser scritti a mano. Sai cosa ti aspetti dopo, quindi se non si presenta, di solito sai cosa è andato storto e quale sarebbe l'errore più sensato.

Inoltre, nell'analisi LL, il recupero degli errori è molto più semplice. Se un input non analizza correttamente, puoi provare a saltare un po 'avanti e capire se il resto dell'input analizza correttamente. Se ad esempio alcune istruzioni di programmazione non sono corrette, è possibile saltare avanti e analizzare l'affermazione successiva, in modo da poter rilevare più di un errore.

Usando un parser LR questo è molto più difficile. Puoi provare ad aumentare la tua grammatica in modo che accetti input errati e stampi errori nelle aree in cui le cose sono andate male, ma di solito è piuttosto difficile da fare. Aumenta anche la possibilità di finire con una grammatica non LR (o non LALR).

Velocità

La velocità non è in realtà un problema con il modo in cui si analizza l'input (LL o LR), ma piuttosto la qualità del codice risultante e l'uso delle tabelle (è possibile utilizzare le tabelle sia per LL che per LR). LL e LR sono quindi comparabili a questo proposito.

Link

Qui è un collegamento a un sito che contrappone anche LL e LR. Cerca la sezione vicino al fondo.

Qui puoi trovare una conversazione sulle differenze. Non è una cattiva idea guardare criticamente le opinioni espresse lì, tuttavia, c'è un po 'di guerra santa in corso lì.

Per maggiori informazioni, qui e qui sono due dei miei post sui parser, anche se non riguardano strettamente il contrasto tra LL e LR.

44
Alex ten Brink