Existe-t-il des compilateurs qui tentent de corriger eux-mêmes les erreurs de syntaxe? [fermé]


15

J'ai entendu tout à l'heure qu'il y avait un compilateur qui tentait de corriger les erreurs de syntaxe en analysant le contexte et en déduisant ce qui était prévu.

Un tel compilateur existe-t-il vraiment? Évidemment, il a peu de valeur pratique, mais il serait très intéressant de jouer avec et d'apprendre.


3
IntelliSense appartient-il à cette catégorie? De nombreux compilateurs ont des erreurs similaires à [point-virgule] attendues.
Robert Harvey

1
@Robert: Non, mais c'est un bon point.
Nathan Osman

1
Un de mes amis a fait un peu de piratage sur le préprocesseur C, par exemple «inlcude -> include», et un peu de travail pour essayer de comprendre où les conditions ouvertes auraient dû être fermées. C'était la thèse de son maître, qu'il a rapidement abandonnée pour quelque chose de plus facile. Pourtant, une question assez intéressante!
Tim Post

3
Le compilateur AC # échoue avec des messages d'erreur TRÈS utiles. Cela combiné à une bonne documentation disponible en ligne pour chaque code d'erreur fonctionne plutôt bien. C'est une mauvaise idée de corriger automatiquement la syntaxe, bien que les interprètes HTML (par exemple les navigateurs) le fassent souvent de toute façon.
Job

1
Le compilateur auquel vous faites référence était le PL / I d'origine. Il a supposé que tout ce que le programmeur avait écrit devait signifier quelque chose, et a essayé de deviner ce que cela pouvait être. D'après mon expérience, cela a très mal deviné!
david.pfx

Réponses:


28

Dans un certain sens, l'acte de compilation est infère ce que certains syntaxe est censé faire, et donc une erreur de syntaxe est lorsque le compilateur ne parvient pas à comprendre. Vous pouvez ajouter plus de "devinettes" pour que le compilateur infère d'autres choses et soit plus flexible avec la syntaxe, mais il doit le faire en déduisant par un ensemble spécifique de règles. Et ces règles deviennent alors une partie du langage, et ne sont plus des erreurs.

Donc, non, il n'y a pas vraiment de tels compilateurs, car la question n'a pas de sens. Deviner quelles erreurs de syntaxe sont censées faire selon un ensemble de règles devient simplement une partie de la syntaxe.

En ce sens, il existe un bon exemple de compilateur qui fait ceci: n'importe quel compilateur C. Souvent, ils imprimeront simplement un avertissement de quelque chose qui ne devrait pas être, puis supposeront que vous vouliez dire X, et continuer. Il s'agit en fait de «deviner» du code peu clair (bien que ce ne soit pas la syntaxe en soi), quelque chose qui aurait tout aussi bien pu arrêter la compilation avec une erreur, et donc être considéré comme une erreur.


4
C'est la bonne réponse. Une fois qu'un compilateur peut récupérer d'une erreur, ce n'est plus vraiment une erreur. Perl est (en?) Célèbre pour ce comportement "Faites ce que je veux dire", choisissant ce que le programmeur est le plus susceptible d'avoir voulu dire étant donné la source ambiguë.
Jon Purdy

Perl sacrifie la verbosité pour la taille du code source.
Nathan Osman

@George Edison: C'est soit une tautologie, soit une contradiction.
Jon Purdy

Ou un aperçu profond. :)
Lennart Regebro

23

Cela semble vraiment dangereux. Si un compilateur tente de déduire votre intention, la déduit incorrectement, corrige le code, puis ne vous le dit pas (ou vous indique dans un avertissement que vous, comme tout le monde, l'ignorez), alors vous êtes sur le point d'exécuter du code qui peut faire sérieusement des dégâts.

Un compilateur comme celui-ci est probablement quelque chose qui n'a PAS été créé intentionnellement.


5
Je le sais. Un tel compilateur n'aurait aucune utilité pour la compilation, mais le concept est assez intéressant et a un potentiel d'apprentissage.
Nathan Osman

2
presque tous les derniers IDE fournissent des suggestions pour la syntaxe et c'est vraiment utile. et pour le reste de la partie d'accord avec nganju
Jigar Joshi

Je n'utiliserais pas un tel compilateur. Il relève de la «magie noire».
Michael K

Hmmm où évalueriez-vous l'inférence de type de Scala sur cette échelle? Après l'avoir essayé, il dirait que c'est une contribution majeure à la concision du code. D'un autre côté, cela m'a parfois tiré dans le pied (par exemple parce que je pensais que je faisais affaire avec des listes mais en réalité je faisais toujours affaire avec des ensembles).
2010

Nous avons des trucs comme l'autoscope dans OMP, donc une petite partie est faisable. Bien sûr, le code sur lequel je travaille a désactivé l'autoscopie car nous ne lui faisons pas confiance. Je pouvais voir un compilateur interactif qui demandait "vous vouliez dire XXX?". C'est aussi loin que je serais prêt à aller. Et même cela est probablement trop dangereux.
Omega Centauri

12

L'IDE pour un langage de programmation a généralement de nos jours un compilateur qui s'exécute en arrière-plan, de sorte qu'il peut fournir des services d'analyse comme la coloration de la syntaxe, IntelliSense, les erreurs, etc. De toute évidence, un tel compilateur doit être capable de donner un sens à du code profondément cassé; la plupart du temps lors de l'édition, le code n'est pas correct. Mais nous devons encore lui donner un sens.

Cependant, la fonction de récupération d'erreur n'est généralement utilisée que lors de l'édition; cela n'a pas beaucoup de sens de permettre cela pour une compilation réelle dans des scénarios "principaux".

Fait intéressant, nous avons intégré cette fonctionnalité dans le compilateur JScript.NET; Fondamentalement, il est possible de mettre le compilateur dans un mode où nous permettons au compilateur de continuer même si une erreur est rencontrée, si l'EDI en aurait récupéré. Vous pouvez taper du code Visual Basic , exécuter le compilateur JScript.NET dessus et avoir une chance raisonnable qu'un programme de travail sorte à l'autre bout!

Il s'agit d'une démonstration amusante, mais elle s'avère ne pas être une très bonne fonctionnalité pour les scénarios "principaux" pour de nombreuses raisons. Une explication complète serait assez longue; la brève explication est que cela rend les programmes qui fonctionnent de manière imprévisible et accidentelle , et il est difficile d'exécuter le même code via plusieurs compilateurs ou plusieurs versions du même compilateur. Les dépenses importantes que la fonctionnalité ajoute ne sont pas justifiées par les petits avantages.

Peter Torr, qui a proposé la fonctionnalité dans la journée, en parle brièvement dans ce blog de 2003 .

Bien que nous exposions cette fonctionnalité via les API d'hébergement de scripts du moteur JScript .NET, je ne connais aucun vrai client qui l'ait jamais utilisée.


J'aimerais que mon employeur ait les ressources pour expérimenter comme ça; nous n'effectuons même pas de tests unitaires la nuit car il y a tellement de fonctionnalités à ajouter et de bugs à corriger :(
Job

1
C'est le genre de réponse que j'espérais ... comme je l'ai mentionné précédemment - une telle fonctionnalité a évidemment peu d'utilité pratique, mais fournirait un excellent moyen d'apprendre certaines techniques qui pourraient être appliquées à d'autres choses. (Analyse de la langue, etc.)
Nathan Osman

1
@Job: La sagesse générale est que si vous n'exécutez pas régulièrement les tests unitaires, vous aurez beaucoup plus de bugs à corriger .
Eric Lippert

Je sais déjà ce que je dois faire à propos de mon travail au lieu de pleurnicher ici. Dans certains éditeurs de logiciels, les dirigeants ne comprennent pas vraiment la différence entre un prototype et un produit fini. Après tout, au niveau des pixels, il n'y a souvent pas beaucoup de différence. Il n'est pas judicieux de ne pas commencer avec un prototype, afin de ne pas perdre de temps. Mais la réponse épouvantable "semble bonne, combien de jours pour mettre cela en production?". Ce sont les mêmes personnes qui se méfieraient si les ingénieurs leur disaient qu'ils devaient passer du temps sur l'infrastructure ou la refactorisation. J'entends même que Spolsky ne l'aime pas.
Job

10

La première chose qui me vient à l'esprit est l' insertion automatique des points-virgules de Javascript . Une caractéristique horrible et horrible qui n'aurait jamais dû faire son chemin dans la langue.

Cela ne veut pas dire qu'il n'aurait pas pu faire mieux. S'il regardait la ligne suivante, il pourrait peut-être mieux deviner l'intention du programmeur, mais à la fin de la journée, s'il y a plusieurs façons valides que la syntaxe aurait pu disparaître, alors il n'y a vraiment pas de substitut pour le programmeur étant explicite.


1
Je suis tout à fait d'accord avec la fonction d'insertion de points-virgules JavaScript - complètement inutile.
Nathan Osman

7

Il me semble que si un compilateur peut corriger une syntaxe incorrecte, cette syntaxe doit être documentée dans le langage.

La raison des erreurs de syntaxe est qu'un analyseur n'a pas pu créer l'arbre de syntaxe abstrait à partir du programme. Cela se produit lorsqu'un jeton n'est pas à sa place. Afin de deviner où ce jeton doit être, s'il doit être supprimé ou si un autre jeton doit être ajouté pour corriger l'erreur, vous aurez besoin d'une sorte d'ordinateur qui peut deviner l'intention d'un programmeur. Comment une machine pourrait-elle deviner que:

int x = 5 6;

Devait être:

int x = 5 + 6;

Il pourrait tout aussi bien être un des éléments suivants: 56, 5 - 6, 5 & 6. Il n'y a aucun moyen pour un compilateur de savoir.

Cette technologie n'existe pas encore.


1
Une telle technologie ne peut pas exister. La lecture de l'esprit n'est pas autorisée; toutes les instructions doivent provenir sans ambiguïté du code.
Job

C'est vrai, mais ce que je voulais vraiment dire, c'est "Y a-t-il des compilateurs qui tentent de corriger la syntaxe invalide en faisant des suppositions en fonction du contexte." Le fait que le compilateur corrige une syntaxe non valide ne rend pas la syntaxe valide. De plus, je me rends compte qu'un tel outil serait inutile pour le développement de code.
Nathan Osman

6

Bien que ce ne soit pas tout à fait la même chose, c'est en quelque sorte la raison pour laquelle le HTML est devenu la catastrophe. Les navigateurs ont toléré un mauvais balisage et la prochaine chose que vous saviez, le navigateur A ne pouvait pas être rendu de la même manière que le navigateur B (oui, il y a d'autres raisons, mais c'était l'une des rares, en particulier il y a environ 10 ans avant que certaines règles de relâchement ne deviennent conventionnelles. ).

Comme le déduit Eric Lippert, beaucoup de ces choses sont mieux gérées par l'IDE, pas par le compilateur. Cela vous permet de voir ce que les bits automatiques tentent de visser pour vous.

La stratégie que je pense qui prédomine maintenant est le raffinement continu du langage au lieu de relâcher le compilateur: si c'est vraiment quelque chose que le compilateur peut comprendre automatiquement, alors introduisez une construction de langage bien définie autour de lui.

L'exemple immédiat qui me vient à l'esprit est les propriétés automatiques en C # (pas le seul langage qui a quelque chose de similaire): étant donné que la majorité des getters / setters dans n'importe quelle application ne sont en fait que des wrappers autour d'un champ, permettez simplement au développeur d'indiquer leur intention et laissez le compilateur injecter le reste.

Ce qui me fait alors réfléchir: la plupart des langages de style C le font déjà dans une certaine mesure. Pour les choses qui peuvent être déterminées automatiquement, affinez simplement la syntaxe:

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

Peut être réduit à:

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

En fin de compte, je pense que cela se résume à ceci: La tendance est que vous ne rendez pas le compilateur "plus intelligent" ou "plus lâche". C'est le langage qui est rendu plus intelligent ou plus lâche.

De plus, trop «d'aide» peut être dangereux, comme le bug classique «if»:

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

Il convient de noter que XHTML a fourni une solution au désordre créé par les mauvaises spécifications de HTML.
Nathan Osman

2
if (x && y) dothis(); else dothat();aurait l'air un peu mieux.
Job

1
Un chat meurt chaque fois que quelqu'un compare avec trueou false.
JensG

2

Lorsque je codais FORTRAN et PL / I à la fin des années 80 et au début des années 90 sur les systèmes de mini-ordinateur et d'ordinateur central DEC et IBM, je me souviens que les compilateurs se déconnectaient régulièrement des messages comme "erreur bla bla; en supposant bla bla et continuant .. . ". À l'époque, c'était un héritage des jours (encore plus tôt, avant mon époque) de traitement par lots et de cartes perforées où il y avait probablement une énorme attente entre la soumission de votre code à exécuter et l'obtention des résultats. Il était donc très logique pour les compilateurs de tenter de deviner le programmeur et de continuer plutôt que d'annuler la première erreur rencontrée. Attention, je ne me souviens pas que les "corrections" aient été particulièrement sophistiquées. Lorsque je suis finalement passé aux postes de travail interactifs Unix (Sun, SGI, etc.),


2
Ces compilateurs continueraient, mais ils continueraient UNIQUEMENT dans le but d'essayer de trouver d'autres erreurs, de sorte que vous pourriez (potentiellement) corriger plusieurs choses avant de soumettre à nouveau. Les PC modernes sont suffisamment rapides pour qu'il soit tout à fait possible pour un compilateur "interactif" de s'arrêter à la première erreur de syntaxe et de vous déposer dans un éditeur. (Et, en fait, le Turbo Pascal d'origine, au début des années 1980, fonctionnait exactement de cette façon. C'était agréable.)
John R. Strohm

1
Oui, je me souviens que le compilateur d'optimisation IBM PL / I fournirait occasionnellement des instructions BEGIN et END manquantes, ISTR fournirait également des points-virgules manquants.
TMN

1

Le but d'un compilateur est de produire des exécutables qui se comportent comme souhaité. Si un programmeur écrit quelque chose qui n'est pas valide, même si le compilateur peut deviner à 90% ce qui était prévu, il serait généralement préférable d'exiger du programmeur qu'il corrige le programme pour que l'intention soit claire, plutôt que de demander au compilateur d'aller de l'avant et de produire un exécutable. ce qui aurait une chance importante de cacher un bug.

Bien sûr, les langues devraient généralement être conçues de manière à ce que le code qui exprime clairement l'intention soit légal, et le code qui n'exprime pas clairement l'intention devrait être interdit, mais cela ne signifie pas qu'elles le sont. Considérez le code suivant [Java ou C #]

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

Avoir un compilateur ajouter un transtypage implicite pour l'affectation f1serait utile, car il n'y a qu'une seule chose logique que le programmeur pourrait vouloir f1contenir (la floatvaleur la plus proche de 1/10). Plutôt que d'encourager les compilateurs à accepter des programmes inappropriés, il serait préférable que la spécification autorise des conversions implicites de double à flottant dans certains contextes. D'un autre côté, l'affectation à d1mai ou peut ne pas être ce que le programmeur avait vraiment l'intention, mais aucune règle de langage ne l'interdit.

Les pires sortes de règles de langage sont celles où les compilateurs feront des inférences dans les cas où quelque chose ne pourrait pas légitimement compiler autrement, mais où un programme pourrait "accidentellement" être valide dans le cas où l'inférence était intentionnelle. De nombreuses situations impliquant une fin de déclaration implicite entrent dans cette catégorie. Si un programmeur qui a l'intention d'écrire deux instructions distinctes omet un terminateur d'instruction, un compilateur peut généralement réussir à déduire la frontière de l'instruction, mais peut parfois considérer comme une instruction quelque chose qui était censé être traité comme deux.


0

Les erreurs de syntaxe sont particulièrement difficiles à corriger. Prenons le cas d'un droit manquant ): nous savons que nous pouvons réparer le code en en insérant un, mais il existe généralement de nombreux endroits où nous pourrions en insérer un et obtenir un programme syntaxiquement correct.

Les identificateurs mal orthographiés sont beaucoup plus faciles (mais notez qu'il ne s'agit pas d'erreurs de syntaxe). On peut calculer la distance d'édition entre l'identifiant insoluble et tous les identifiants dans la portée, et en remplaçant le mot insoluble par celui que l'utilisateur voulait probablement dire, on trouverait un programme correct dans de nombreux cas. Cependant, il s'avère qu'il est toujours préférable de signaler l'erreur et de laisser l'IDE suggérer des remplacements valides.


-1

Un tel compilateur serait simplement une implémentation détendue et non standard du langage qu'il compile.


-2

Il a été essayé plusieurs fois, mais souvent, il n'a pas obtenu l'effet souhaité: pensez à HAL 9000 ou GlaDOS.


-3

En C, vous ne pouvez pas passer de tableaux par valeur, mais le compilateur vous permet d'écrire:

void foo(int array[10]);

qui est ensuite réécrit en silence:

void foo(int* array);

C'est stupide? Je préférerais une erreur grave ici au lieu d'une réécriture silencieuse, car cette règle spéciale a conduit de nombreux programmeurs à croire que les tableaux et les pointeurs sont essentiellement la même chose. Ils ne sont pas.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.