Abstraction Concrète : Application Ada2Caml


Présentation de l'application

L'application étudiée ici, Ada2Caml traite de la conversion automatique d'un langage informatique vers un autre. L’objectif visé est essentiellement didactique, et l'exemple, conçu à partir de sous ensembles des 2 langages, ne fait qu’effleurer la complexité des structures de Caml et Ada. Dans ce cadre, il sera très facile de tester les exemples proposés, à chaque étape. Cela permet de suivre les différentes phases de l’analyse du premier langage puis de la synthèse des phrases du second.

Ada2Caml est un traducteur d'une restriction du langage Ada vers des structures Caml équivalentes. L'application est découpée en trois parties :
Syntaxe concrète Chaîne de caractères : programme Ada
Analyse lexicale
adalex
Syntaxe intermédiaire Séquence ordonnée de lexèmes Ada
Analyse syntaxique
adaspec + adainst
Syntaxe abstraite Structure arborescente
Synthèse
adacaml
Syntaxe concrète Chaîne de caractères : programme Caml

Analyse lexicale

Fonctions du module
Module adalex
Exemples d'analyse lexicale

L'analyse lexicale consiste à décomposer le texte du programme présenté comme une chaîne de caractères en une liste de lexèmes. Le programme sera chargé d'éliminer les commentaires et de distinguer les mots réservés ou clés, les nombres, les symboles utilisés comme opérateurs ou séparateurs, les identificateurs, les chaînes de caractères, les booléens et les valeurs du type caractère.

Les fonctions du module

Exemples d'analyse lexicale de fonctions et procédures en ADA

La phrase à décomposer en lexèmes est une définition de fonction Ada (en italique), elle est passée en argument, comme une chaîne de caractères, à la fonction Caml analex :
#let f = analex "
function carre(x:integer)return integer is
begin
  return x*x;
end carre;
" ;;
En résultat, la fonction analex retourne la liste de lexèmes suivante :

f : lexeme list = [
Cle "function"; Nom "carre"; Sym "("; Nom "x"; Sym ":"; Nom "integer"; Sym ")"; Cle "return"; Nom "integer"; Cle "is"; Cle "begin"; Cle "return"; Nom "x"; Sym "*"; Nom "x"; Sym ";"; Cle "end"; Nom "carre"; Sym ";"]
Autre exemple, la phrase à traiter est la définition de procédure Ada :

#let p = analex "
with text.io;
use text.io;
procedure principale is  -- debut du programme
  a:constant integer := 5;
  b:integer := 10;
  begin
    put(a+b);
    put(a-b);
end principale ;
" ;;
En résultat, la fonction analex retourne la liste de lexèmes suivante :

p : lexeme list =
[Cle "with"; Nom "text"; Sym "."; Nom "io"; Sym ";"; Nom "use"; Nom "text"; Sym "."; Nom "io"; Sym ";"; Cle "procedure"; Nom "principale"; Cle "is"; Nom "a"; Sym ":"; Cle "constant"; Nom "integer"; Sym ":="; Ent 5; Sym ";"; Nom "b"; Sym ":"; Nom "integer"; Sym ":="; Ent 10; Sym ";"; Cle "begin"; Nom "put"; Sym "("; Nom "a"; Sym "+"; Nom "b"; Sym ")"; Sym ";"; Nom "put"; Sym "("; Nom "a"; Sym "-"; Nom "b"; Sym ")"; Sym ";"; Cle "end"; Nom "principale"; Sym ";"]

Analyse syntaxique

Fonctions du module adaspec
Fonctions du module adainst
Module adaspec
Module adainst
Exemples d'analyse syntaxique

Pour l'analyse syntaxique, on trouvera pratique d'utiliser les descriptions en notation B.N.F. ou les diagrammes syntaxiques selon les goûts. On se réfèrera à la grammaire du langage Ada, telle qu'elle est décrite par de nombreux manuels, par exemple « Programmer en Ada » de J. Barnes, ou « Ingénierie du logiciel avec Ada » de G. Booch. Dans le premier module d'analyse syntaxique, adaspec, le problème consiste à reconnaître la structure des spécifications de procédures ou de fonctions et quatre types d’identificateurs, les identificateurs de procédures, de fonctions, de types et d’étiquettes (label).

Le deuxième module d'analyse syntaxique, adainst, a pour objet de reconnaître la structure des définitions d’implémentation de procédures ou de fonctions, les différentes formes d’instructions et les expressions du langage Ada. Au terme de l’analyse syntaxique, la séquence ordonnée de lexèmes du langage Ada est transformée en une structure arborescente, la syntaxe abstraite.

Les fonctions du module adaspec

Les fonctions du module adainst

Exemples d'analyse syntaxique

Exemples d'analyse syntaxique de spécifications ADA
Exemples d'analyse syntaxique d'expressions ADA
Exemples d'analyse syntaxique d'instructions ADA

Exemples d'analyse syntaxique de spécifications ADA

La phrase à analyser est une spécification de fonction Ada (en caractères gras), elle est passée en argument, comme un flot de lexèmes, à la fonction Caml decl_sousprog, après un premier traitement d’analyse lexicale :
#decl_sousprog(stream_of_list (analex "
function f1(x:float;y:float)return float;
" ) );;
Résultat de l’évaluation,
- : type_specification =
 SpecFun
  (Fun "f1",
   ([[Var "x"], IN, Type "float", Nil_exp;
     [Var "y"], IN, Type "float", Nil_exp],
    Type "float"))

Exemples d'analyse syntaxique d'expressions ADA

La phrase à analyser est une expression Ada d’affectation (en caractères gras) :
#condition(stream_of_list (analex "
(x <= 5)
" ) );;

- : type_expression = InfEq (Var "x", Entier 5)

Exemples d'analyse syntaxique d'instructions ADA

La phrase à analyser est une instruction simple Ada d’affectation (en caractères gras) :
#instruction_simple(stream_of_list (analex "
alpha := x+2*sin(a-5) ;
"));;
Résultat de l’évaluation,
- : type_instruction_type =
 Affect
  (Var "alpha",
   Add (Var "x", 
        Mul (Entier 2, 
             App (Fun "sin", [Sub (Var "a", Entier 5)]))))
Nouveaux exemples avec des instructions composées.
  • Cas de l’instruction alternative :
    #instruction_composee(stream_of_list (analex "
    if x>10 
       then put(x);
       else exit;
    end if;
    " ) );;
    
    Résultat de l’évaluation,
    - : type_instruction_type =
     If [Sup (Var "x", Entier 10), 
        [Instr ([], Appel (Proc "put", [Var "x"]))];
       Booleen true, [Instr ([], Exit)]]
    
  • Cas de boucle
    #instruction_loop(stream_of_list (analex "
    while x <= 5 loop
       x:=x+1;
    end loop;
    " ) );;
    
    - : type_instruction_type =
     Loop
      (While (InfEq (Var "x", Entier 5)),
       [Instr ([], Affect (Var "x", Add (Var "x", Entier 1)))])
    
  • Cas de séquence d’instructions
    #sequence_instr(stream_of_list (analex "
    x:=x+1;
    put(x);
    return x;
    " ) );;
    
    - : type_instruction list = [
    Instr ([], Affect (Var "x", Add (Var "x", Entier 1))); 
    Instr ([], Appel (Proc "put", [Var "x"])); 
    Instr ([], Return (Var "x"))]
    

    Synthèse

    Fonctions du module
    Module adacaml
    Exemples de conversion Ada -> Caml

    Pour le dernier module, il s’agit de traiter le problème inverse des modules précédents, et de reconstituer une phrase du langage cible, Caml, à partir de la forme équivalente en syntaxe abstraite. Cette fois, l’opération est réalisée en une seule étape, en passant directement de la structure arborescente à la chaîne de caractère finale en syntaxe concrète Caml.

    Les fonctions du module

    Exemples de conversion de fonctions et procédures ADA en Caml

    Le premier exemple est une spécification Ada de fonction,
    #ada_to_caml "
    function essai(x,y,z:integer)return integer;
    ";;
    
    ce qui correspond à une déclaration de typage d’expression en Caml, d’où le résultat suivant :
    - : string = 
               "value essai : int -> int -> int -> int;;"
    
    Autre exemple de conversion spécification Ada -> typage Caml :
    #ada_to_caml "
    function identique(x:integer)return integer is
    a:character;
    begin
      return x;
    end identique;
    " ;;
    
    - : string = "let identique = function x -> x;;"
    
    Exemple de conversion de définition de fonction Ada en Caml :
    #ada_to_caml "
    function essai(x,y,z:integer)return integer is
    u,v,w:constant integer:=7;
    a:integer:= (x + y)*abs(z);
    begin
      return (w+a*u)*(z-a*w);
    end essai;
    " ;;
    
    - : string = "let essai = function x -> function y -> function z -> let u = 7 and v = 7 and w = 7 and a = ref ((x + y) * (abs z )) in ((w + (!a * u)) * (z - (!a * w)));;"

    Après mise en page du résultat de la conversion, on a la fonction Caml :

    let essai = 
       function x -> function y -> function z -> 
         let u = 7 and v = 7 and w = 7 
         and  a = ref ((x + y) * (abs z )) 
         in ((w + (!a * u)) * (z - (!a * w)));;
    

    Mise en œuvre de l'application

  • Générateur de l'application

    La procédure de génération de l’application a été conçue pour fonctionner avec les chemins d’accès aux fichiers, mis en place par défaut, lors de l’installation initiale. Le lecteur devra adapter ces chemins en fonction des modifications qu’il aura pu apporter à l’installation initiale. Ici, le répertoire racine de l’installation est considéré comme étant le répertoire maître lors de la génération de l’application.

    Exécution de l'application

    Depuis le système interactif, le traducteur est chargé à partir de la commande suivante :
      load_object "ada2caml";; 
    Après chargement du code, il est possible d'appeler les fonctions exportées des différents modules de ada2caml, en préfixant la fonction appelée par le nom du module requis. Par exemple : adalex__analex.

    On peut aussi ouvrir les modules par la directive #open :

    #open "adalex";;
    #open "adaspec";;
    #open "adainst";;
    #open "adacaml";;
    
    Après l'ouverture des modules, il est possible d'utiliser, directement, les fonctions d'analyse lexicale ou syntaxique, et les fonctions de synthèse.