Hace un tiempo escuché que solía haber un compilador que intentaba corregir los errores de sintaxis analizando el contexto e inferiendo lo que se pretendía.
¿Existe realmente ese compilador? Obviamente tiene poco valor práctico, pero sería muy interesante jugar y aprender de él.
Respuestas:
En cierto sentido, el acto de compilar es inferir lo que se supone que debe hacer cierta sintaxis y, por lo tanto, un error de sintaxis es cuando el compilador no puede resolverlo. Puede agregar más "adivinanzas" para que el compilador deduzca más cosas y sea más flexible con la sintaxis, pero debe inferir esto mediante un conjunto específico de reglas. Y esas reglas se convierten en parte del lenguaje y ya no son errores.
Entonces, no, no existen tales compiladores, realmente, porque la pregunta no tiene sentido. Adivinar qué errores de sintaxis deben hacer de acuerdo con un conjunto de reglas se convierte en parte de la sintaxis.
En ese sentido, hay un buen ejemplo de un compilador que hace esto: cualquier compilador de C. A menudo imprimen una advertencia de algo que no es como debería ser, y luego suponen que se refería a X, y continúan. De hecho, esto es "adivinar" un código poco claro (aunque en su mayoría no es sintaxis per se), algo que podría haber detenido la compilación con un error y, por lo tanto, calificarse como un error.
fuente
Suena muy peligroso Si un compilador intenta inferir su intención, lo infiere mal, corrige el código y luego no le dice (o le dice en alguna advertencia que usted, como todos, ignora), entonces está a punto de ejecutar un código que puede En serio hacer algo de daño.
Un compilador como este es probablemente algo que NO ha sido creado intencionalmente.
fuente
El IDE para un lenguaje de programación generalmente en estos días tiene un compilador ejecutándose en segundo plano de alguna manera, para que pueda proporcionar servicios de análisis como coloración de sintaxis, IntelliSense, errores, etc. Obviamente, un compilador de este tipo debe poder dar sentido a un código profundamente roto; la mayoría de las veces al editar, el código no es correcto. Pero todavía tenemos que darle sentido.
Sin embargo, generalmente la función de recuperación de errores solo se usa durante la edición; no tiene mucho sentido permitir eso para la compilación real en escenarios de "línea principal".
Curiosamente, creamos esa característica en el compilador JScript.NET; básicamente es posible poner el compilador en un modo en el que permitimos que el compilador continúe incluso si se encuentra un error, si el IDE se hubiera recuperado de él. ¡Puede escribir código de Visual Basic , ejecutar el compilador JScript.NET en él y tener una posibilidad razonable de que un programa de trabajo salga por el otro extremo!
Esta es una demostración divertida, pero resulta que no es una característica muy buena para escenarios de "línea principal" por muchas razones. Una explicación completa sería bastante larga; La breve explicación es que crea programas que funcionan de manera impredecible y accidental , y dificulta la ejecución del mismo código a través de múltiples compiladores o múltiples versiones del mismo compilador. Los grandes gastos que agrega la función no se justifican por los pequeños beneficios.
Peter Torr, quien publicó la característica en el pasado, lo analiza brevemente en esta publicación de blog de 2003 .
Aunque exponemos esta característica a través de las API de hospedaje de scripts del motor JNET .NET, no conozco ningún cliente real que la haya usado alguna vez.
fuente
Lo primero que me viene a la mente es la inserción automática de punto y coma de Javascript . Una característica horrible, horrible que nunca debería haber llegado al lenguaje.
Eso no quiere decir que no podría haber hecho un mejor trabajo. Si miraba hacia adelante en la siguiente línea, entonces podría ser capaz de adivinar mejor la intención del programador, pero al final del día, si hay varias formas válidas de que la sintaxis podría haber desaparecido, entonces realmente no hay sustituto para que el programador sea explícito.
fuente
Me parece que si un compilador puede corregir una sintaxis incorrecta, esa sintaxis debe documentarse en el idioma.
La razón de los errores de sintaxis es porque un analizador sintáctico no pudo crear el árbol de sintaxis abstracta fuera del programa. Esto sucede cuando una ficha está fuera de lugar. Para adivinar dónde debe estar ese token, si se debe eliminar o si se debe agregar algún otro token para corregir el error, necesitaría algún tipo de computadora que pueda adivinar la intención de un programador. ¿Cómo podría una máquina adivinar eso?
Se suponía que era:
Podría ser simplemente tan fácilmente cualquiera de los siguientes:
56
,5 - 6
,5 & 6
. No hay forma de que un compilador lo sepa.Esa tecnología aún no existe.
fuente
Aunque no es exactamente lo mismo, esta es la razón por la cual HTML se convirtió en el desastre que es. Los navegadores toleraron un marcado incorrecto y lo siguiente que sabía es que el navegador A no podía funcionar de la misma manera que el navegador B (sí, hay otras razones, pero esta fue una de las pocas, especialmente hace unos 10 años antes de que algunas de las reglas de flexibilidad se convirtieran en convenciones )
Como infiere Eric Lippert, muchas de estas cosas son mejor manejadas por el IDE, no por el compilador. Eso te permite ver lo que los bits automáticos intentan arruinarte.
La estrategia que creo que predomina ahora es el continuo refinamiento del lenguaje en lugar de aflojar el compilador: si realmente es algo que el compilador puede descubrir automáticamente, entonces introduzca una construcción de lenguaje bien definida a su alrededor.
El ejemplo inmediato que viene a la mente son las propiedades automáticas en C # (no es el único lenguaje que tiene algo similar): dado que la mayoría de los captadores / establecedores en cualquier aplicación son solo envoltorios alrededor de un campo, solo permita que el desarrollador indique su intento y dejar que el compilador inyecte el resto.
Lo que me lleva a pensar: la mayoría de los lenguajes de estilo C ya lo hacen hasta cierto punto. Para las cosas que se pueden resolver automáticamente, simplemente refine la sintaxis:
Se puede reducir a:
Al final, creo que todo se reduce a esto: la tendencia es que no hagas que el compilador sea "más inteligente" o "más flexible". Es el lenguaje que se hace más inteligente o más flexible.
Además, demasiada "ayuda" puede ser peligrosa, como el clásico error "if":
fuente
if (x && y) dothis(); else dothat();
Se vería un poco mejor.true
ofalse
.Cuando estaba codificando FORTRAN y PL / I a finales de los años 80 y principios de los 90 en sistemas de minicomputadora y mainframe de DEC e IBM, parece recordar que los compiladores desconectaban regularmente mensajes como "bla bla bla error; suponiendo que bla bla y continuando ... ". En aquel entonces, este era un legado de los días (incluso antes, antes de mi tiempo) de procesamiento por lotes y tarjetas perforadas, cuando probablemente hubo una enorme espera entre el envío de su código para ejecutar y obtener los resultados. Por lo tanto, tenía mucho sentido que los compiladores intentaran adivinar al programador y continuar en lugar de abortar el primer error encontrado. Eso sí, no recuerdo que las "correcciones" sean particularmente sofisticadas. Cuando finalmente me mudé a estaciones de trabajo interactivas de Unix (Sun, SGI, etc.),
fuente
El objetivo de un compilador es producir ejecutables que se comporten como se desee. Si un programador escribe algo que no es válido, incluso si el compilador puede adivinar con un 90% de probabilidad lo que se pretendía, generalmente sería mejor requerir que el programador arregle el programa para aclarar la intención, que hacer que el compilador continúe y produzca un ejecutable lo que tendría una posibilidad significativa de ocultar un error.
Por supuesto, los lenguajes generalmente deben diseñarse de modo que el código que expresa claramente la intención sea legal, y el código que no expresa claramente la intención debería estar prohibido, pero eso no significa que lo sean. Considere el siguiente código [Java o C #]
f1
Sería útil que un compilador agregue un tipo de letra implícito para la asignación , ya que solo hay una cosa lógica que el programador podría quererf1
contener (elfloat
valor más cercano a 1/10). Sin embargo, en lugar de alentar a los compiladores a aceptar programas inadecuados, sería mejor que la especificación permitiera conversiones implícitas de doble a flotante en algunos contextos. Por otro lado, la asignación ded1
puede o no ser lo que el programador realmente pretendía, pero no hay una regla de lenguaje que lo prohíba.Los peores tipos de reglas de lenguaje son aquellos en los que los compiladores harán inferencias en casos en los que algo no podría compilarse legítimamente de otra manera, pero donde un programa podría ser "accidentalmente" válido en un caso donde se pretendía hacer una inferencia. Muchas situaciones que involucran el final implícito de la declaración entran en esta categoría. Si un programador que tiene la intención de escribir dos declaraciones separadas omite un terminador de declaración, un compilador generalmente puede inferir el límite de la declaración, pero ocasionalmente puede considerar como una declaración algo que se suponía que debía procesarse como dos.
fuente
Los errores de sintaxis son especialmente difíciles de corregir. Tomemos el caso de un derecho perdido
)
: sabemos que podemos reparar el código insertando uno, pero generalmente hay muchos lugares donde podríamos insertar uno y obtener un programa sintácticamente correcto.Un punto mucho más fácil son los identificadores mal escritos (pero tenga en cuenta que esto no son errores de sintaxis). Se puede calcular la distancia de edición entre el identificador irresoluble y todos los identificadores en el alcance, y al reemplazar la palabra irresoluble por la que el usuario probablemente quiso decir, se obtendría un programa correcto en muchos casos. Sin embargo, resulta que todavía es mejor marcar el error y dejar que el IDE sugiera reemplazos válidos.
fuente
Tal compilador sería simplemente una implementación relajada y no estándar de cualquier idioma que esté compilando.
fuente
Se ha probado varias veces, pero a menudo no logró el efecto deseado: piense en HAL 9000 o GlaDOS.
fuente
En C, no puede pasar matrices por valor, sin embargo, el compilador le permite escribir:
que luego se reescribe en silencio como:
¿Qué tan estúpido es eso? Preferiría un error difícil aquí en lugar de una reescritura silenciosa, porque esta regla especial ha llevado a muchos programadores a creer que las matrices y los punteros son básicamente lo mismo. Ellos no son.
fuente