TD 7 plus

Exercice 3. Serrer les boulons

Il reste quelques boulons à serrer dans votre calculatrice pour qu'en plus de marcher, elle soit belle.

Exercice 3.1 Le problème de l'associativité

Comme évoqué à la fin de l'exercice 1, il y a un problème d'associativité dans la lecture des expressions. En effet, 1-2-3 est lu comme 1-(2-3) ce qui n'est pas l'interprétation naturelle. Pour cela, une solution simple consiste à utiliser des règles contenant des "suites de" définissables avec des expressions rationnelles :

    expression -> produit (+ produit | - produit)*
    produit -> facteur (* facteur | / facteur)*
Ce qui est en rouge correspond à la définition de l'expression rationnelle. Cela se lit ainsi : pour lire une expression, on lit d'abord un produit puis une suite (éventuellement vide) de "compléments d'expression" où chaque complément d'expression est soit - suivi d'un produit, soit + suivi d'un produit.

Exercice 3.2 Nombres négatifs

Autoriser les nombres négatifs, grâce à l'opérateur unaire changement de signe. Par exemple, autoriser les expressions : 1 + -2, - x, 1 / - 3.

Exercice 3.3 Calculatrice typée

Modifier le programme d'analyse lexicale pour pouvoir lire des réels positifs (comme 0.2 ou 1.23e-5). Séparer les nombres en deux classes les entiers et les flottants. (12 par exemple sera considéré comme entier alors que 12. sera considéré comme réel.) On rajoutera dans Terme un champ pour indiquer le type (entier ou flottant) du terme. Les calculs dépendront des types, par exemple, 1 / 2 ne donnera pas le même résultat que 1. / 2.. Les expressions ne comportent que des entiers, ou bien que des flottants. Mélanger les deux doit provoquer une erreur. Afficher en plus du résultat de chaque calcul, le type du résultat.

Exercice 4. Fonctions

Définir des fonctions (association d'un nom de variable et d'un terme) :

deffun f de x = x * x ;
  Fonction f (x) = (x * x)
eval  appel f en 2+1 ;
  Evaluation de f((2.0 + 1.0)) = 9.0

L'appel de fonction devient un nouveau type de terme. Il faudra donc rajouter une dérivation :

    expression -> appel NomFonction en expression

On remarquera qu'il faut définir un contexte local pour stocker la valeur associée au paramètre de la fonction avec un pointeur vers le contexte dans lequel l'appel a été fait. Évaluer l'appel appel f en 2+1 consiste à faire set x = 2+1 dans le contexte local puis à évaluer le terme associé à f dans ce contexte local. Le contexte de départ (le plus global) est la mémoire de la machine telle que définie précédemment. La valeur associée à une variable est d'abord cherchée dans le contexte local, si elle n'est pas trouvée, on remonte au contexte supérieur et ainsi de suite. On pourra ainsi avoir un appel dans un appel :

deffun f de x = x * x ;
  Fonction f (x) = (x * x)
deffun g de x = x + (appel f en x+1) ;
  Fonction g (x) =  x + f((x + 1.0))
eval appel g en 1 ;
  Evaluation de g (1.0) = 5.0

Exercice 5. Évaluation retardée

Stocker l'expression associée à une variable sans essayer de l'évaluer lors d'un set :

set y = 2 * x ;
  Stockage de y = (2.0 * x)
set x = 1 ; eval y ;
  Stockage de x = 1.0 
  Evaluation de y = 2.0 ;
set x = 2 ; eval y ;
  Stockage de x = 2.0 
  Evaluation de y = 4.0 ;
eval 1 + z ;
Exception in thread "main"java.lang.Error: Variable non affect'ee : z
        at ...

Pour faire un peu de haute voltige, on peut faire de même avec le passage d'argument lors d'un appel de fonction. Pour que cela marche, il faut lors d'un set associer le nom de la variable au terme à évaluer ainsi que le contexte dans lequel l'évaluer...


Last modified: Wed Feb 16 11:16:04 CET 2005