Esistono compilatori che tentano di correggere da soli errori di sintassi? [chiuso]

13

Ho sentito un po 'di tempo fa che c'era un compilatore che tentava di correggere gli errori di sintassi analizzando il contesto e deducendo ciò che era inteso.

Esiste davvero un compilatore di questo tipo? Ovviamente ha poco valore pratico, ma sarebbe molto interessante da giocare e da cui imparare.

    
posta Nathan Osman 27.12.2010 - 08:09
fonte

12 risposte

23

In un certo senso, l'atto di compilazione di è che deduce ciò che una determinata sintassi è pensata per fare, e quindi un errore di sintassi è quando il compilatore non è in grado di capirlo. È possibile aggiungere ulteriori "ipotesi" per fare in modo che il compilatore deduca ulteriori dettagli ed essere più flessibile con la sintassi, ma deve farlo deducendo da un insieme specifico di regole. E quelle regole diventano quindi parte della lingua e non sono più errori.

Quindi, no, non ci sono tali compilatori, davvero, perché la domanda non ha senso. Indovinare quali errori di sintassi si intende fare in base a qualche insieme di regole diventa solo una parte della sintassi.

In questo senso, c'è un buon esempio di un compilatore che fa questo: qualsiasi compilatore C. Spesso stampano solo un avvertimento su qualcosa che non è come dovrebbe essere, e quindi presumono che intendessi X, e vai avanti. In realtà, si tratta di un "indovinare" codice non chiaro (anche se per lo più non è sintassi di per sé), qualcosa che altrettanto avrebbe potuto arrestare la compilazione con un errore e quindi qualificarsi come errore.

    
risposta data 27.12.2010 - 12:19
fonte
23

Sembra davvero pericoloso. Se un compilatore cerca di dedurre il tuo intento, lo infonde sbagliato, corregge il codice e poi non ti dice (o ti dice in un avvertimento che tu, come tutti, ignori), allora stai per eseguire il codice che potrebbe seriamente qualche danno.

Un compilatore come questo probabilmente è qualcosa che NON è stato creato intenzionalmente.

    
risposta data 27.12.2010 - 08:30
fonte
9

L'IDE per un linguaggio di programmazione di solito in questi giorni ha un compilatore in esecuzione in background in qualche modo, in modo che possa fornire servizi di analisi come la colorazione della sintassi, IntelliSense, errori e così via. Ovviamente un tale compilatore deve essere in grado di dare un senso al codice profondamente spezzato; il più delle volte quando si modifica, il codice non è corretto. Ma dobbiamo ancora dare un senso.

Tuttavia, in genere la funzione di ripristino degli errori viene utilizzata solo durante la modifica; non ha molto senso consentirlo per la compilazione vera e propria negli scenari "mainline".

È interessante notare che abbiamo creato questa caratteristica nel compilatore JScript.NET; fondamentalmente è possibile mettere il compilatore in una modalità in cui consentiamo al compilatore di procedere anche se si verifica un errore, se l'IDE si sarebbe ripristinato da esso. È possibile digitare il codice Visual Basic , eseguire il compilatore JScript.NET su di esso e avere una ragionevole possibilità che un programma funzionante venga fuori dall'altra parte!

Questa è una demo divertente, ma risulta non essere una funzionalità molto buona per gli scenari "mainline" per molte ragioni. Una spiegazione completa sarebbe piuttosto lunga; la breve spiegazione è che rende programmi che funzionano imprevedibilmente e per caso e rende difficile l'esecuzione dello stesso codice attraverso più compilatori o più versioni dello stesso compilatore. Le grandi spese aggiunte dalla funzione non sono giustificate dai piccoli vantaggi.

Peter Torr, che ha ricoperto il ruolo nel passato, discute brevemente in questo blog pubblicato dal 2003 .

Anche se esporremo questa funzionalità tramite le API di hosting dello script del motore JScript .NET, non conosco nessun cliente reale che l'abbia mai utilizzata.

    
risposta data 27.12.2010 - 20:00
fonte
8

La prima cosa che mi viene in mente è l' inserimento automatico del punto e virgola di Javascript. Una caratteristica orribile e orribile che non avrebbe mai dovuto farsi strada nella lingua.

Questo non vuol dire che non avrebbe potuto fare un lavoro migliore. Se guardava in avanti alla seguente riga, allora potrebbe essere in grado di fare una supposizione migliore sull'intenzione del programmatore, ma alla fine della giornata, se ci sono molti modi validi che la sintassi potrebbe avere andato, quindi non c'è davvero alcun sostituto per il programmatore di essere esplicito.

    
risposta data 27.12.2010 - 08:47
fonte
7

Mi sembra che se un compilatore potesse correggere la sintassi errata, allora quella sintassi dovrebbe essere documentata nella lingua.

Il motivo per gli errori di sintassi è perché un parser non è in grado di creare l'albero di sintassi astratto dal programma. Questo accade quando un token è fuori luogo. Per indovinare dove dovrebbe essere quel token, se dovrebbe essere rimosso, o se qualche altro token dovrebbe essere aggiunto per correggere l'errore, è necessario un qualche tipo di computer che possa indovinare l'intento di un programmatore. Come potrebbe una macchina indovinare:

int x = 5 6;

Doveva essere:

int x = 5 + 6;

Potrebbe altrettanto facilmente essere uno dei seguenti: 56 , 5 - 6 , 5 & 6 . Non c'è modo per un compilatore di sapere.

Questa tecnologia non esiste ancora.

    
risposta data 27.12.2010 - 08:39
fonte
4

Anche se non è esattamente la stessa cosa, questo è il motivo per cui l'HTML è diventato il disastro. I browser hanno tollerato un brutto markup e la prossima cosa che sapevi, il browser A non poteva renderlo allo stesso modo del browser B (sì, ci sono altri motivi, ma questo era uno dei primi, esp circa 10 anni fa prima che alcune delle regole sciolte diventassero delle convenzioni ).

Come sostiene Eric Lippert, molte di queste cose sono gestite al meglio dall'IDE, non dal compilatore. Vediamo cosa stanno cercando di rovinarti i bit automatici.

La strategia che penso sia predominante ora è il raffinamento del linguaggio continuo invece di allentare il compilatore: se è veramente qualcosa che il compilatore può capire automaticamente, quindi introdurre un linguaggio ben definito attorno ad esso.

L'esempio immediato che mi viene in mente è l'auto-proprietà in C # (non l'unico linguaggio che ha qualcosa di simile): Dato che la maggior parte dei getter / setter in qualsiasi app sono in realtà solo wrapper attorno a un campo, basta consentire allo sviluppatore per indicare il loro intento e lasciare che il compilatore inietti il resto.

Quindi mi viene da pensare: la maggior parte dei linguaggi in stile C già fa questo in una certa misura. Per cose che possono essere capite automaticamente, basta rifinire la sintassi:

 if (true == x)
 {
    dothis();
 }
 else
 {
    dothat();
 }

Può essere ridotto a:

if (true == x)
    dothis();
else
    dothat();

Alla fine, penso che si tratti di questo: la tendenza è che non si rende il compilatore "più intelligente" o "più lento". È la lingua che viene resa più intelligente o più flessibile.

Inoltre, troppo "aiuto" può essere pericoloso, come il classico bug "se":

if (true == x)
    if (true == y)
       dothis();
else
    dothat();
    
risposta data 27.12.2010 - 20:46
fonte
1

Quando stavo codificando FORTRAN e PL / I tra la fine degli anni '80 e l'inizio degli anni '90 sui sistemi DEC e IBM minicomputer e mainframe, mi sembra di ricordare che i compilatori avrebbero regolarmente disconnesso messaggi come "blah blah error, assumendo blah blah e continua ... ". Allora, questa era un'eredità dei (anche prima, prima del mio tempo) giorni di elaborazione in batch e schede perforate quando c'era probabilmente un'enorme attesa tra l'invio del codice da eseguire e il recupero dei risultati. Quindi ha molto senso per i compilatori fare un tentativo di indovinare il programmatore e continuare piuttosto che abortire sul primo errore riscontrato. Intendiamoci, non ricordo che le "correzioni" siano particolarmente sofisticate. Quando alla fine mi sono trasferito su workstation Unix interattive (Sun, SGI, ecc.), Ho notato che la funzione sembrava essere completamente assente dai loro compilatori C.

    
risposta data 27.12.2010 - 17:48
fonte
0

L'obiettivo di un compilatore è di produrre eseguibili che si comportano come desiderato. Se un programmatore scrive qualcosa che non è valido, anche se il compilatore può con una probabilità del 90% indovinare cosa si intendeva, sarebbe in genere meglio richiedere al programmatore di correggere il programma per rendere chiara l'intenzione, piuttosto che far compilare il compilatore e produrre un eseguibile che avrebbe una probabilità significativa di nascondere un bug.

Naturalmente, le lingue dovrebbero essere generalmente progettate in modo che il codice che esprime chiaramente l'intenzione sia legale, e il codice che non esprime chiaramente l'intenzione dovrebbe essere vietato, ma ciò non significa che lo siano. Considera il seguente codice [Java o C #]

const double oneTenth = 0.1;
const float  oneTenthF = 0.1f;
...
float f1 = oneTenth;
double d1 = oneTenthF;

Avere un compilatore aggiungere un typecast implicito per l'assegnazione a f1 sarebbe utile, dal momento che c'è solo una cosa logica che il programmatore potrebbe volere che f1 contenga (il valore float più vicino a 1/10). Piuttosto che incoraggiare i compilatori ad accettare programmi impropri, tuttavia, sarebbe meglio per spec consentire conversioni implicite da doppio a virgola mobile in alcuni contesti. Per quanto riguarda il rovescio della medaglia, l'assegnazione a d1 può essere o non essere ciò che il programmatore intendeva davvero, ma non esiste una regola linguistica che lo vieti.

I peggiori tipi di regole linguistiche sono quelli in cui i compilatori trarranno inferenze nei casi in cui qualcosa non potrebbe legittimamente compilare diversamente, ma dove un programma potrebbe essere "accidentalmente" valido nel caso in cui l'inferenza fosse stata intesa. Molte situazioni che implicano la fine implicita rientrano in questa categoria. Se un programmatore che intende scrivere due istruzioni separate omette un terminatore di un'istruzione, un compilatore potrebbe in genere riuscire a dedurre il limite dell'istruzione, ma a volte potrebbe considerare come un'istruzione qualcosa che doveva essere elaborata come due.

    
risposta data 22.02.2014 - 17:35
fonte
0

Gli errori di sintassi sono particolarmente difficili da correggere. Prendiamo il caso di una destra mancante ) : Siamo in grado di riparare il codice inserendone uno, ma di solito ci sono molti posti in cui potremmo inserirne uno e ottenere un programma sintatticamente corretto.

Un punto molto più semplice sono gli identificatori errati (ma si noti che non si tratta di errori di sintassi). Si può calcolare la distanza di modifica tra l'identificatore irrisolvibile e tutti gli identificatori in ambito e, sostituendo la parola non risolvibile con quella che l'utente ha probabilmente inteso, si otterrebbe in molti casi un programma corretto. Tuttavia, risulta che è ancora meglio segnalare l'errore e lasciare che l'IDE suggerisca sostituzioni valide.

    
risposta data 23.02.2014 - 00:29
fonte
-1

Un compilatore di questo tipo sarebbe semplicemente un'implementazione rilassata e non standard di qualsiasi lingua venga compilata.

    
risposta data 27.12.2010 - 18:06
fonte
-2

È stato provato più volte, ma spesso non ha ottenuto l'effetto desiderato: pensa HAL 9000 o GlaDOS.

    
risposta data 28.12.2010 - 01:50
fonte
-3

In C, non puoi passare array per valore, eppure il compilatore ti permette di scrivere:

void foo(int array[10]);

che viene quindi automaticamente riscritto come:

void foo(int* array);

Quanto è stupido? Preferirei un errore grave qui invece di una riscrittura silenziosa, perché questa regola speciale ha portato molti programmatori a credere che gli array e i puntatori siano fondamentalmente la stessa cosa. Non lo sono.

    
risposta data 31.01.2011 - 20:13
fonte

Leggi altre domande sui tag