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

2. Les opérateurs contextuel

Une grammaire est très généralement exprimée sous la forme d'une grammaire « indépendante du contexte » ("context-free"). En pratique, la grammaire d'un langage n'a quasiment jamais cette propriété. Mais on en fait pourtant largement usage, pour la réalisation des outils qui travaillent sur une grammaire (analyseur syntaxique, compilateur, éditeur syntaxique, ...).

Des exemples d'opérateurs contextuels :

le cas de la fonction

Figure 1.a : grammaire des fonctions

Pour simplifier la présentation, on n'introduit pas la notion de liste. De ce fait :
- une fonction est définie avec un unique paramètre,
- le corps de la fonction est composé d'une unique instruction,
- etc.
La prise en compte des listes compliquerait l'exemple mais ne le contredirait pas.

opérateur fonction

Il est défini par :

(def fonction ()
   ((def return ...« phrase RETURN »...)
    (def call-rec ...« appel récursif »...))
   (... déclaration de la fonction...))

c'est-à-dire que 

opérateur call-rec

C'est l'appel d'une fonction, formellement paramétré par :

Figure 1.a : grammaire des fonctionsafficher >><< masquer ]

(def affect ()
   ((VAR) ":=" (EXP) ";"))

(def cond ()
   ("IF " (TEST) " THEN" "^M"
    "   " (ALORS) "^M"
    "ELSE" "^M"
    "   " (SINON) "^M"
    "END IF;" "^M"))

(def none ()
   ("NONE"))

(def fonction
   ((def return
       ((def VAR ()
           ((NOM ((bloc-fct))))))
       ((affect)))
    (def call-rec
       ((def BLOC-FCT
           ((bloc-fct))))
       ((call-fct))))
   ("FUNCTION " (NOM ((bloc-fct))) " (" (formel ((PARAM ((bloc-fct))))) ")"
       " RETURNS " (TYP ((bloc-fct))) ";" "^M"
    "BEGIN" "^M"
    "   " (INSTR ((bloc-fct))) "^M"
    "END;" "^M"))

(def call-fct ()
   ((NOM ((BLOC-FCT))) " (" (effect) ")"))

(def formel ()
   ((NOM) " : " (SNS) " " (TYP)))

(def effect ()
   ((EXP)))

Figure 1.b : la fonction compte

La définition d'une fonction introduit celle de « bloc de fonction » : c'est le bloc des déclarations de la fonction, qui définit :
- le nom de la fonction et le type de la valeur retournée,
- les paramètres formels (leur nom, leur type, leur sens),
- les déclarations locales.

Partant, on pourra ensuite utiliser ces déclarations "assez profondément" dans l'arbre syntaxique du corps de la fonction. La difficulté est alors de savoir nommer ces déclarations "globales" – "globales" vis-à-vis du corps de la fonction.

Pour particulariser les déclarations "globales" de la fonction, on structure la définition « textuelle » de la fonction en plaçant les paramètres de définition d'une fonction à l'intérieur d'un texte de nom bloc-fct :

(def fct-compte ()
   ((fonction)
    (def bloc-fct
       ((def NOM ...)
        (def TYP ...)
        (def PARAM ...)
        ...déclarations locales...
        (def INSTR ...))))
   ((fonction)))

On définit le texte fct-compte : la fonction compte :

Dans le cas de la fonction compte, on définit localement le texte param-arbre :

Figure 1.b : la fonction compteafficher >><< masquer ]

(def fct-compte ()
   ((fonction)
    (def bloc-fct
       ((def NOM () ("compte"))
        (def TYP () ("integer"))
        (def PARAM
           ((param-arbre)))
        (def param-arbre
           ((def NOM () ("a"))
            (def TYP () ("arbre"))
            (def SNS () ("IN"))))
        (def INSTR
           ((def TEST
               ((def BLOC-FCT
                   ((bloc-fct ((fct-feuille)))))
                (def EXP () ((NOM ((param-arbre ((bloc-fct)))))))))
               ((call-fct)))
            (def ALORS
               ((def EXP () ("1")))
               ((return)))
            (def SINON
               ((def plus-gche
                   ((def EXP
                      ((def BLOC-FCT
                          ((bloc-fct ((fct-fg)))))
                       (def EXP () ((NOM ((param-arbre ((bloc-fct)))))))))
                      ((call-fct))))
                   ((call-rec)))
                (def plus-dte
                   ((def EXP
                      ((def BLOC-FCT
                          ((bloc-fct ((fct-fd)))))
                       (def EXP () ((NOM ((param-arbre ((bloc-fct)))))))))
                      ((call-fct))))
                   ((call-rec)))
                (def EXP ()
                   ((plus-gche) " + " (plus-dte))))
               ((return))))
           ((cond))))))
   ((fonction)))

Un appel de fonction consiste alors en la fourniture d'un « bloc de fonction ». Par exemple :

(def TEST ()
   ((def BLOC-FCT
       ((bloc-fct ((fct-feuille)))))
    (def EXP ...))
   ((call-fct)))

on fournit le « bloc de fonction » de la fonction feuille.

Un appel récursif se ramène à fournir le « bloc de fonction » implicitement visible dans la déclaration de la fonction – le sien :

(def call-rec ()
   ((def BLOC-FCT
       ((bloc-fct))))
   ((call-fct)))

(le paramètre EXP est fourni par défaut : call-rec est lui-même paramétré par EXP).

Figure 1.c : les fonctions sur les arbres

On reconnaît dans la définition « textuelle » des fonctions sur les arbres le même schéma de construction du texte – renforcé ici par le fait que le paramètre formel est toujours un arbre entré (mode "IN") : mais ceci est en fait un "hasard".

Figure 1.c : les fonctions sur les arbresafficher >><< masquer ]

(def fct-feuille ()
   ((fonction)
    (def bloc-fct
       ((def NOM () ("feuille"))
        (def TYP () ("boolean"))
        (def PARAM
           ((param-arbre)))
        (def param-arbre
           ((def NOM () ("a"))
            (def TYP () ("arbre"))
            (def SNS () ("IN"))))
        (def INSTR
           ((none))))))
   ((fonction)))

(def fct-fg ()
   ((fonction)
    (def bloc-fct
       ((def NOM () ("fg"))
        (def TYP () ("arbre"))
        (def PARAM
           ((param-arbre)))
        (def param-arbre
           ((def NOM () ("a"))
            (def TYP () ("arbre"))
            (def SNS () ("IN"))))
        (def INSTR
           ((none))))))
   ((fonction)))

(def fct-fg ()
   ((fonction)
    (def bloc-fct
       ((def NOM () ("fd"))
        (def TYP () ("arbre"))
        (def PARAM
           ((param-arbre)))
        (def param-arbre
           ((def NOM () ("a"))
            (def TYP () ("arbre"))
            (def SNS () ("IN"))))
        (def INSTR
           ((none))))))
   ((fonction)))

3. les schémas contextuels

On reprend ici l'exemple du bloc de réservation, présenté auparavant (Chapitre 2.4, « Exemple de structuration des traitements »). Le bloc de réservation est un "opérateur" défini par l'utilisateur qui va connoter les phrases de « sortie brutale » : la « phrase EXIT » ou la « phrase RETURN » (on ne traite pas cette dernière).

le texte while

(def while ()
   ((def exit1 ()
       ("EXIT " (NOM((bloc-while))) ";" "^M")))
   ("while " (EXP-COND) " do /" (NOM((bloc-while))) "/" "^M"
    "   " (lst-init ((INSTR*))
             ((INSTR
                 ((def exit () ((exit1)))))))
    "END DO;" "^M"))

pour accéder au nom de la boucle on introduit un « bloc de boucle » bloc-while : les instructions sont décompilées en définissant le texte exit par sa forme simple exit1.

le texte reserve

(def reserve ()
   ((def exit2 ()
       ("free(" (NOM((bloc-reserve))) ");" "^M"
        (exit1))))
   ("reserve(" (NOM((bloc-reserve))) ");" "^M"
    "   " (lst-init ((INSTR*))
             ((INSTR
                 ((def exit () ((exit2)))))))
    "free(" (NOM((bloc-reserve))) ");" "^M"))

on introduit un « bloc de réservation » bloc-reserve pour nommer la ressource concernée. Les instructions sont alors décompilées en définissant le texte exit par sa forme complétée exit2.

Note : en toute rigueur il faudrait dans reserve introduire un test qui vérifie s'il y a lieu de définir un texte exit, c'est-à-dire qui puisse savoir si l'on est placé à l'intérieur d'une boucle (texte while).

le "corps" du bloc de réservation

(def INSTR ()
   ((def EXP-COND () ("R.c<R.P"))
    (def ALORS
       (lst-env
          ((def INSTR () ("incr(R.c);" "^M")))
          ((def INSTR () ((exit))))))
    (def SINON
       (lst-env)))
   ((cond))

on utilise l'"opérateur" exit, en "oubliant" qu'on est placé à l'intérieur d'un bloc de réservation, et qu'il faut donc libérer la ressource : c'est le texte exit qui se le rappellera.