afficher >><< masquer ]
SAMPI - Editeur structuré
1. Le Problème et la Proposition
2. Le Langage Primitif de Représentation Textuelle
2.1. Présentation de la Syntaxe Concrète
2.2. Notations
2.3. Exemple de structuration des données
2.4. Exemple de structuration des traitements
2.5. Exemple de structurations connexes
3. Le Langage Complété pour la Structuration des Textes
3.1. Présentation de la Syntaxe Complétée
3.2. Etude quantitative de l'évolution des programmes
3.3. L'édition syntaxique
3.3.1. Définition d'un langage
3.3.2. Information de contexte
3.3.22.1. La décompilation contextuelle
3.3.22.2. Les opérateurs contextuel
3.3.3. Exécution
3.3.4. Définition de propriétés
3.4. étude de cas : le langage LTR3 et l'atelier ENTREPRISE
4. L'Enrichissement du Langage par de Nouveaux Concepts
4.1. Présentation de la Syntaxe Abstraite
4.2. Les difficultés
4.3. Compléter la Syntaxe
5. La Formalisation des Solutions Techniques
5.1. L'évaluation fonctionnelle
5.2. La structuration par les objets
5.3. Modèle sémantique comparé de l'évaluateur
5.4. Comparaison critique
5.5. Construction de la Syntaxe Abstraite
6. Les Comparaisons avec d'autres Approches
7. Les Perspectives
8. Les Editeurs
8.0. brisé sur la barrière de la complexité (une fois de plus)
8.1. L'éditeur ligne : Manuel de l'utilisateur
8.2. L'éditeur page : Guide de l'utilisateur
9. Les Aspects d'Implantation
9.1. Contexte d'évaluation
9.2. La Syntaxe Abstraite : Manuel du concepteur
9.3. L'éditeur page : Guide de l'implanteur
Références
Rubrique Perl-Javascript

Information de contexte

On présente plusieurs exemples d'"opérateurs" dont le comportement est lié au contexte dans lequel on les utilise – il s'agit soit d'opérateurs du langage sont de textes qu'on aura identifiés comme représentant des concepts significatifs du langage.

1. La décompilation contextuelle

2. Les opérateurs contextuel

1. La décompilation contextuelle

Les opérateurs du langage sont définis comme des textes placés dans l'« environnement global » ; la prise en compte d'information de contexte se traduit donc simplement par la redéfinition de l'opérateur concerné dans un environnement local.

1.1. le « else pendant »

L'exemple classique d'un opérateur dont le schéma de décompilation dépend du contexte est celui du « else pendant » de Pascal. On définit ici les opérateurs de phrase conditionnelle suivants :

opérateur cond1

(def cond1 ()
   ("if " (TEST) " then" "^M"
    "   " (ALORS) "^M"
    (lsp
       (if (egal (use SINON) "")
           (rep "else")
           (rep "else" "^M"
                "   " (SINON))))))

On affiche systématiquement le mot-clé "else", qu'il y ait ou non une « partie SINON ».

opérateur cond2

(def cond2 ()
   ("if " (TEST) " then" "^M"
    (lsp
       (if (egal (use SINON) "")
           (rep "   " (ALORS))
           (rep "   " (ALORS
                         ((def cond () ((cond1))))) "^M"
                "else" "^M"
                "   " (SINON))))))

Dans cond2 :

opérateur cond

(def cond ()
   ((cond2)))

L'opérateur cond est l'opérateur utilisé dans l'arbre syntaxique du programme :

Par exemple :

On n'affiche aucun "else" :

forme « textuelle »forme « visuelle »
(def UTIL1
   ((def TEST () ("x=y"))
    (def ALORS
       ((def TEST () ("y=z"))
        (def ALORS () ("x:=y"))
        (def SINON () ()))
       ((cond)))
    (def SINON () ()))
   ((cond)))
if x=y then
   if y=z then
      x:=y

Sur la « branche ALORS », l'existence d'une « partie SINON » force l'affichage du "else" (la règle de syntaxe de Pascal rapporte la « partie SINON » introduite par "else" à la phrase conditionnelle la plus proche pour laquelle ne se rapporte encore aucune « partie SINON ») :

(def UTIL2
   ((def TEST () ("x=y"))
    (def ALORS
       ((def TEST () ("y=z"))
        (def ALORS () ("x:=y"))
        (def SINON () ()))
       ((cond)))
    (def SINON () ("y:=x")))
   ((cond)))
if x=y then
   if y=z then
      x:=y
   else
else
   y:=x

Dans la « partie SINON de la partie ALORS » il n'y a pas nécessité d'affichage du "else" :

(def UTIL3
   ((def TEST () ("x=y"))
    (def ALORS
       ((def TEST () ("y=z"))
        (def ALORS () ("x:=y"))
        (def SINON
           ((def TEST () ("x=z"))
            (def ALORS () ("write('Erreur')"))
            (def SINON () ()))))
       ((cond)))
    (def SINON () ()))
   ((cond)))
if x=y then
   if y=z then
      x:=y
   else
      if x=z then
         write('Erreur')

Dans cette même partie on affiche le "else" : cette propriété est "héritée" sur la « branche SINON » du deuxième niveau de la « branche ALORS » du premier niveau :

(def UTIL3
   ((def TEST () ("x=y"))
    (def ALORS
       ((def TEST () ("y=z"))
        (def ALORS () ("x:=y"))
        (def SINON
           ((def TEST () ("x=z"))
            (def ALORS () ("write('Erreur')"))
            (def SINON () ()))))
       ((cond)))
    (def SINON () ("y:=x")))
   ((cond)))
if x=y then
   if y=z then
      x:=y
   else
      if x=z then
         write('Erreur')
      else
else
   y:=x

Il ne faut cependant pas oublier de redéfinir l'opérateur cond par sa forme initiale (sur cond2) dans une sous-branche où l'ambiguïté disparaît. Par exemple, l'opérateur repeat :

(def repeat ()
   ("repeat" "^M"
    "   " (INSTR
             ((def cond () ((cond2))))) "^M"
    "until " (EXP-COND)))

Le parenthésage implicite défini par l'opérateur repeat fait "oublier" le contexte d'apparition de cet opérateur.

1.2. groupement d'instructions

On peut aussi avoir des ambiguïtés d'affichage introduites à la définition d'"opérateurs" propres à l'utilisateur. Par exemple, on définit l'"opérateur" :

(def lecture ()
   ("carcou := carlu;" "^M"
    "read(carlu);"))

qui est utilisé dans le programme comme une instruction indivisible.

Selon la position de l'"opérateur" dans le programme, l'affichage sera différent. Par exemple :

[1] begin
       ...
       carcou := carlu;
       read(carlu);
       Traitement(carcou);
       ...
    end;

[2] while condition do
     begin
       carcou := carlu;
       read(carlu);
     end;

dans le cas [1], les deux instructions sont affichées "en ligne" ; dans le cas [2] on les encadre par les parenthèses begin-end.

On peut systématiquement se placer dans le cas [2], mais ceci risque d'entraver une bonne lisibilité du programme. Pour conserver les deux formes possibles d'affichage on introduit alors un opérateur de groupement d'instructions qui se chargera de la prise en compte du contexte d'utilisation de l'opérateur.

(def list-instr1 ()
   ("begin" "^M"
    "   " (lst-init ((INSTR*))
             ((INSTR) ";" "^M"))
    "end;" "^M"))

(def list-instr2 ()
   ((lst-init ((INSTR*))
       ((INSTR) ";" "^M"))))

(def list-instr ()
   ((lst-instr2)))

L'"opérateur" liste-instr est défini par défaut sur liste-instr2 : on n'affiche pas les parenthèses begin-end. Certains opérateurs redéfinissent alors liste-instr. Par exemple :

(def while ()
   ("while " (EXP-COND) " do" "^M"
    "   " (INSTR
             ((def liste-instr () ((liste-instr1)))))))

L'"opérateur" lecture est défini sur liste-instr : il laisse à ce dernier le soin de décider l'affichage ou non des parenthèses begin-end.

(def lecture ()
   ((def INSTR*
       (lst-env
          ((def INSTR () ("carcou := carlu")))
           (def INSTR () ("read(carlu)"))))))
   ((liste-instr)))