El else colgante es un problema en la programación de generadores de analizadores sintácticos en el que una cláusula else opcional en una declaración if-then(-else) da como resultado que los condicionales anidados sean ambiguos. Formalmente, la gramática libre de contexto de referencia del lenguaje es ambigua , lo que significa que hay más de un árbol de análisis correcto .
En muchos lenguajes de programación se puede escribir código ejecutado condicionalmente en dos formas: la forma si-entonces y la forma si-entonces-else; la cláusula else es opcional:
si a entonces s si b entonces s1 si no s2
Esto da lugar a una ambigüedad en la interpretación cuando hay declaraciones anidadas, específicamente cuando aparece una forma si-entonces como s1
si-entonces-si no:
si a entonces si b entonces s si no s2
En este ejemplo, s
se ejecuta sin ambigüedades cuando a
es verdadero y b
es verdadero, pero se puede interpretar s2
como ejecutado cuando a
es falso (adjuntando así el else al primer if) o cuando a
es verdadero y b
es falso (adjuntando así el else al segundo if). ). En otras palabras, uno puede ver la afirmación anterior como cualquiera de las siguientes expresiones:
si a entonces ( si b entonces s) más s2 si a entonces ( si b entonces s más s2)
El problema de los demás pendientes data de ALGOL 60 , [1] y se ha resuelto de varias maneras en idiomas posteriores. En los analizadores LR , el else colgante es el ejemplo arquetípico de un conflicto de cambio-reducción .
Este es un problema que surge a menudo en la construcción de compiladores , especialmente en el análisis sin escáner . La convención cuando se trata del else colgante es adjuntar el else a la declaración if cercana, [2] permitiendo gramáticas inequívocas y libres de contexto, en particular. Los lenguajes de programación como Pascal, [3] C [4] y Java [5] siguen esta convención, por lo que no hay ambigüedad en la semántica del lenguaje , aunque el uso de un generador de analizador puede dar lugar a gramáticas ambiguas . En estos casos, la agrupación alternativa se logra mediante bloques explícitos, como begin...end
en Pascal [6] y {...}
en C.
Dependiendo del enfoque de construcción del compilador, se pueden tomar diferentes acciones correctivas para evitar ambigüedades:
El problema también se puede resolver haciendo explícito el vínculo entre un else y su if, dentro de la sintaxis. Esto suele ayudar a evitar errores humanos. [7]
Las posibles soluciones son:
if
cláusula sin cláusula alternativa como un error, distinguiendo efectivamente las expresiones condicionales (es decir , ) de las declaracionesif
condicionales (es decir , y , que no tienen cláusulas alternativas).when
unless
if e do s
para el caso de una alternativa y if e1 then e2 else e3
para el caso general. [10]A continuación se presentan ejemplos concretos.
En C , la gramática dice, en parte:
declaración =... | declaración de selección declaración-de-selección = ... | Declaración IF (expresión) | Declaración IF (expresión) Declaración ELSE
Así, sin más reglas, la declaración
si ( a ) si ( b ) s ; más s2 ;
podría analizarse ambiguamente como si fuera:
si ( a ) { si ( b ) s ; más s2 ; }
o:
si ( a ) { si ( b ) s ; } más s2 ;
En la práctica, en C se elige el primer árbol, asociando el else
con el más cercano if
.
El ejemplo anterior podría reescribirse de la siguiente manera para eliminar la ambigüedad:
declaración: declaración_abierta | declaración_cerrada ;open_statement: Declaración IF '(' expresión ')' | IF '(' expresión ')' declaración_cerrada ELSE declaración_abierta ;declaración_cerrada: declaración_no_si | IF '(' expresión ')' declaración_cerrada ELSE declaración_cerrada ;declaración_no_si: ... ;
Es posible que también sea necesario duplicar de esta manera otras reglas gramaticales relacionadas con declaraciones si pueden terminar directa o indirectamente con a statement
o selection-statement
no terminal.
Sin embargo, damos gramática que incluye declaraciones if y while.
declaración: declaración_abierta | declaración_cerrada ;open_statement: Declaración IF '(' expresión ')' | IF '(' expresión ')' declaración_cerrada ELSE declaración_abierta | MIENTRAS '(' expresión ')' declaración_abierta ;declaración_cerrada: declaración_simple | IF '(' expresión ')' declaración_cerrada ELSE declaración_cerrada | MIENTRAS '(' expresión ')' declaración_cerrada ;declaración_simple: ... ;
Finalmente, damos la gramática que prohíbe declaraciones IF ambiguas.
declaración: declaración_abierta | declaración_cerrada ;declaración_abierta: IF '(' expresión ')' declaración_cerrada | IF '(' expresión ')' declaración_abierta | IF '(' expresión ')' declaración_cerrada ELSE declaración_abierta | MIENTRAS '(' expresión ')' declaración_abierta ;declaración_cerrada: declaración_simple | IF '(' expresión ')' declaración_cerrada ELSE declaración_cerrada | MIENTRAS '(' expresión ')' declaración_cerrada ;declaración_simple: ... ;
Con esta gramática el enunciado if (a) if (b) c else d
sólo puede analizarse de una manera, porque la otra interpretación ( if (a) {if (b) c} else d
) se produce como
declaracióndeclaración_abiertaIF '(' expresión ')' declaración_cerrada ELSE declaración_abierta'si' '(' 'a' ')' declaración_cerrada 'de lo contrario' 'd'
y luego el análisis falla al intentar hacer coincidir closed_statement
"si (b) c". Un intento closed_statement
falla de la misma manera. El otro análisis, if (a) {if (b) c else d}
) tiene éxito:
declaracióndeclaración_abiertaIF '(' expresión ')' declaración_cerradaIF '(' a ')' (IF '(' expresión ')' declaración_cerrada ELSE declaración_cerrada)SI '(' a ')' (SI '(' b ')' c ELSE 'd')
{{cite book}}
: |website=
ignorado ( ayuda )