Dangling else

Un article de Wikipédia, l'encyclopédie libre.

En informatique, et notamment dans la conception et l'analyse des langages de programmation, le problème du dangling else (anglais que l'on pourrait traduire par le problème du « sinon pendant ») est un problème de programmation informatique qui résulte de l'ambiguïté de l'interprétation de la clause sinon dans l'imbrication de deux instructions conditionnelles de la forme si-alors-sinon. Formellement, la grammaire non contextuelle du langage est ambiguë, ce qui signifie qu'il peut y avoir plusieurs arbres d'analyse corrects pour une même instruction.

Le « dangling else »[modifier | modifier le code]

Dans de nombreux langages de programmation, on peut écrire une instruction conditionnelle sous deux formes : la forme si-alors  et la forme si-alors-sinon. En d'autres termes, la clause sinon est facultative, et les deux constructions suivantes sont valides :

if a then s
if b then s1 else s2

Cela donne lieu à une ambiguïté d'interprétation lorsqu'il y a des instructions imbriquées, plus précisément à chaque fois qu'un si-alors apparaît à la place du s1 dans une autre instruction si-alors-sinon, soit dans la situation que voici :

if a then if b then s else s2

Dans cet exemple, l'instruction exécutée est sans ambiguïté s lorsque a et b sont vrai ; mais on peut considérer que s2 doit être exécutée lorsque a est faux (et donc rattacher le else au premier if), ou lorsque a est vrai et b est faux (et donc rattacher le else au deuxième if). En d'autres termes, on peut voir l'instruction précédente comme l'une des expressions suivantes :

if a then (if b then s) else s2
      ou
if a then (if b then s else s2)

Un compilateur doit analyser correctement l'instruction, et choisir entre les deux interprétations selon le concepteur du langage de programmation. Le problème du dangling else date d'ALGOL 60[1], et a été résolu de diverses manières dans les langages qui ont suivi. Dans les analyseurs LR, le dangling else est l'exemple typique d'un conflit shift-reduce[2].

Exemples[modifier | modifier le code]

En langage C[modifier | modifier le code]

  if (a == 1)
    if (b == 1)
      a = 42;
  else
    b = 42;

Dans cet exemple, un programmeur pourrait s'attendre à ce que la variable b prenne la valeur 42 quand a ≠ 1. Le compilateur Compiler rattache le else au deuxième if et ne fait pas l'affection. Si l'on veut que b prenne la valeur 42 quand a≠ 1, l'instruction if interne doit être mise entre accolades :

  if (a == 1)
  {
    if(b == 1)
      a = 42;
  }
  else
    b = 42;

Autres langages[modifier | modifier le code]

Dans certains langages, le problème est résolu en associant obligatoirement une parenthèse fermante à chaque if. Par exemple, dans le langage de script Shell de Bourne, c'est un fi qui représente la parenthèse fermante ; le morceau de programme s'écrit alors :

if [ $a -eq 1 ] ; then
  if [ $b -eq 1 ] ; then
    a=42
  fi
else
  b=42
fi

D'autres langages de programmation, comme par exemple Python, résolvent le problème par indentation :

if a == 1:
    if b == 1:
        a = 42
else:
    b = 42

En Ada le problème n'apparaît pas à cause d'un parenthésage syntaxique inambigu, où chaque IF est fermé par un ENDIF :

IF a = 1 THEN
    IF b = 1 THEN
        a := 42;
    END IF;
ELSE
     b := 42;
END IF;

D'autres langages, comme Pascal, adoptent comme C le rattachement du else au dernier if.

Notes et références[modifier | modifier le code]

  1. P. W. Abrahams, « A final solution to the Dangling else of ALGOL 60 and related languages », Communications of the ACM, vol. 9, no 9,‎ , p. 679 (DOI 10.1145/365813.365821)
  2. Section 5.2 Shift/Reduce Conflicts sur le site du système GNU.