AnaGram :


Analyse de Grammaire Formelles pour

des systèmes L

Documentation

Texte du Programme

Documentation

du programme AnaGram


 Gilles HUNAULT, Philippe ALBERT, Angers - 94


 

Anagram :


    Analyse d'une  grammaire et  Affichage des  productions.
    Le nom du  fichier associé à  la grammaire est  passé en
    paramètre.


 

Les paramètres possibles sont :


    p1 : nom de grammaire(.grm).
    p2 : le mot STOP pour un arrêt après l'analyse
         seulement de la grammaire (pas de productions)
         ou le mot DBG pour mise au point, FILTRE pour
         choisir les affichages, NOSTAT pour éviter les
         statistiques d'utilisation des règles, etc.
    p3 : le mot SIMPLIF pour une simplification.
    p4 : le mot CUMUL pour un cumul.
    p5 : le mot INT pour une interprétation numérique
         des symboles (fichier .INT), les valeurs de cette
         interprétation étant stockées dans un fichier .SIN
    p6 : le mot FOR (plus un nombre d'étape). Par défaut le
         nombre d'étape est 5.
    p7 : le mot GPL pour générer un fichier lisible par
         Gnuplot (cela induit forcement une interprétation
         numérique, l'option INT est donc automatiquement
         activée).
    p8 : le mot REP pour que la génération de productions se
         fasse en mode répétition, sinon elle se fait en
         mode modulo.

    Si  l'ordre  des  paramètres  est  a  priori  fixé,   le
    programme sait "à peu  près" reconnaitre les mots  STOP,
    INT, etc.


 

Déroulement :


    On lit dans cet ordre sur la ligne 1 l'alphabet puis les
    variables  sur  la  ligne  2  puis le symbole de départ.
    Enfin, chaque  production est  lue, à  raison d'une  par
    ligne, avec en fin de ligne l'impulsion correspondant à
    la production.

 

Variables fondamentales :


  Ligne alphabet   : LA ; symboles A.i en nombre NA
  Ligne variables  : LV ; symboles V.i en nombre NV
  Symbole terminal : S
  Ligne production : LP ; partie gauche p.g.i
                          partie droite p.d.i
                          en nombre np
  Impulsion associé à la production : E.i

 

Méthode :


    Chaque  production  génère  une  ligne NLS qu'on renomme
    ensuite LS ; NLS  comptient NT mots qu'on  note toujours
    MS. On recherche la production qui va s'appliquer à MS.
    Pour cela on vérifie :
              * la présence de MS dans la partie gauche de
    la production (pour les deux modes).
              * que le reste de la division de l'impulsion
    E.i par l'indice MS.T de MS est bien égale à zéro (en
    mode MODULO).
              * que le nombre de fois, de suite, ( = E.i )
    où la règle de production doit s'appliquer n'est pas
    dépassé (mode REPETITION).

    Exemple : r1 est définie par : a > b [1]
              r2 est définie par : a > c [2]
              En mode MODULO il s'applique, à l'étape 1 : r1
                                                      2 : r2
                                                      3 : r1
                                                      4 : r2
              EN mode REPETITION, à l'étape 1 : r1
                                            2 : r2
                                            3 : r2
                                            4 : r1

    On remplace alors  ms par la partie droite de la
    production associée.   En  fin de  programme, on affiche
    combien de fois chaque règle est utilisée.

    Un symbole de l'alphabet est toujours recopié, mais  pas
    une variable.  Les règles peuvent avoir des  productions
    multiples ; ainsi a > a | b est valide.  La machine fait
    un tirage alétaoire du n³ de production à utiliser.

 

Interprétation numérique :


    Seules  les  variables  de  poids  non  nul doivent être
    entrées ; toute variable  non indiquée se voit  affecter
    un poids égal à 0.

 

Remarques sur les paramètres :


 

Les mots suivants sont reconnus

             CUMUL
             DBG
             FILTRE
             For [nbetap], par default: 5
             GPL
             INT
             NOAFF
             NOSTAT
             NOWAIT
             REP
             SIMPLIF
             STOP

 Pour que ANAGRAM fonctionne vous devez posséder les
 fichiers :
             ANAGRAM.HLP
             ANAGRAM.REX
             CUMULE.REX
             DSE.REX
             EXISTE.REX
             MONTRE.REX
             SIMPLE.REX


Texte

du programme AnaGram

#! /home/xed/srexx
/* Anagram.Rex */


 

/* # 0.0 Détection des paramètres */


 parse arg nomf lignearg  /* parse est obligatoire pour UNIX */

 lignearg = upper(lignearg)

 if wordpos("DBG",lignearg) > 0 then do
     signal on failure
     signal on halt
     signal on error
     signal on syntax
     debug = "ON"
end

 if wordpos("STOP"   ,lignearg)  > 0 then do ; arret     = "STOP" ; end
 if wordpos("CUMUL"  ,lignearg)  > 0 then do ; cumul     = "OUI"  ; end
 if wordpos("SIMPLIF",lignearg)  > 0 then do ; simplif   = "OUI"  ; end
 if wordpos("FILTRE" ,lignearg)  > 0 then do ; filtrage  = "OUI"  ; end
 if wordpos("INT"    ,lignearg)  > 0 then do ; interp    = "INT"  ; end
 if wordpos("NOSTAT" ,lignearg)  > 0 then do ; nostat    = "OUI"  ; end
 if wordpos("NOAFF"  ,lignearg)  > 0 then do ; affiche   = "NON"  ; end
 if wordpos("NOWAIT" ,lignearg)  > 0 then do ; nowait    = "OUI"  ; end
 if wordpos("FOR"    ,lignearg)  > 0 then do
    etapf = "OUI"
    say lignearg
    parse var lignearg with "FOR" nef .
    if (nef = "") | \datatype(nef,"W") then do ; nef = 5 ; end
 end
 if wordpos("GPL"    ,lignearg)  > 0 then do
    gnuplt   = "GPL"
    interp   = "INT"
 end
 if wordpos("REP"    ,lignearg)  > 0 then do
    gen      = "REP"
    pas      = 1
 end ; else do
    gen      = "MOD"    /* option par défaut */
    pas      = 2
 end

 if debug = "ON" then do
    if arret    = "STOP" then do ; say " on stoppe après analyse " ; end
    if cumul    = "OUI"  then do ; say " on cumule "               ; end
    if simplif  = "OUI"  then do ; say " on simplifie "            ; end
    if filtrage = "OUI"  then do ; say " on filtre "               ; end
    if interp   = "INT"  then do ; say " il y a interprétation numérique "  ; end
    if gnuplt   = "GPL"  then do ; say " il y a génération d'un fichier lisible par Gnuplot"  ; end
    if etapf    = "OUI"  then do ; say " en route pour " nef " étapes "  ; end
    call charout , "    ok ? "
    pull .
 end


 /* attention au disque virtuel */
 virtuel = "D:" /* ou virtuel = "" sont ok */
 virtuel = "/tmp/"   /* pour Unix */
 virtuel = ""   /* pour Unix */

 

/* # 0.1 Gestion de la demande d'aide */


 /* Si le paramètre est ? on affiche un texte d'aide */
 if nomf = '?' | nomf = '' then do
    call montre "anagram.hlp"
    exit
 end /* finsi nomf = '?' | nomf = '' */

 

/* # 0.2 Gestion des paramètres et fichiers */

 /*          - nom du fichier grammaire        */
 /*          - fichier d'interprétation        */

 /* Si on ne voit pas le fichier sur le répertoire courant, */
 /* on le dit et on abandonne le programme.                 */

 ip = pos(".",nomf)
 if  ip=0
     then do ; fichgram=nomf||".grm" /* minuscule pour Unix */ ; end ;
     else do
          fichgram=nomf
          nomf = substr(nomf,1,ip-1)
     end
 /*  fin de si */

 if existe(fichgram) = ""  then do
    say " fichier " fichgram "non vu "
    say " abandon du programme "
    exit -1
 end /* if existe(fichgram) = 0 */

 sorint = nomf".sin"
 sorgpl = nomf".gpl"
 call dse(sorint)
 call dse(sorgpl)

 

/* # 1.0 Analyse de la grammaire */


 

/* # 1.0 Lecture du fichier grammaire */


 /* On lit l'aphabet, les variables, le symbole de départ */
 /* dans les trois première lignes du fichier .           */
 /* Chaque règle de production est lue à raison d'une     */
 /* par ligne, la partie gauche et la partie droite       */
 /* sont séparées par le symbole >                        */

 

/* # 1.1 Lecture de l'alphabet */


 LL = linein( fichgram )
 if pos(";",LL) > 0
    then do ; parse value LL with LA ";" rems ; end ;
    else do ; LA = LL ; end
 /* fin de si */
 na = words(LA)
 do i = 1 to na
    A.i = word(LA,i)
 end /* do i = 1 to na */

 

/* # 1.2 Lecture des variables */


 /* On considère que trouver un symbole de variable égal    */
 /* à un symbole d'alphabet est une erreur ; on le signale  */
 /* en cours de lecture et on rappelle le nombre d'erreurs  */
 /* en fin de lecture.                                      */

 LL = linein( fichgram )
 if pos(";",LL) > 0
    then do ; parse value LL with LV ";" rems ; end ;
    else do ; LV = LL ; end
 err = 0
 nv = words(LV)

 do i = 1 to nv
    vtmp = word(LV,i)
    V.i  = vtmp
    if pos(vtmp,LA) > 0 then do
       err = err + 1
       say "                " vtmp " déja vu dans " LA
    end
 end /* do i = 1 to nv */

 if err > 0 then do
    say err " erreur(s) pour les variables "
 end /* if err > 0 */

 

/* # 1.3 Lecture du symbole de départ */


 /* C'est une erreur que de ne pas trouver le symbole              */
 /* de départ dans la liste des variables s'il n'a qu'une lettre.  */
 /* En mode MODULO on attribut un indice égale à 1 au symbole      */
 /* de départ : de facon à avoir  S, puis un blanc, puis l'indice. */

 LL = linein( fichgram )
 if pos(";",LL) > 0
    then do ; parse value LL with S ";" rems ; end ;
    else do ; S = LL ; end
 S = strip(S,'B')

 if gen = "MOD" then do
    nS = S||" "
    p = pos(" ",nS)
    do while p > 0
       nS = substr(nS,1,p)||"1 "||substr(nS,p+1)
       p = pos(" ",nS,p+3)
    end  /* do while p > 0 */
    nS = strip(nS,'B')
 end /* if gen = "MOD" */
 else do ; nS = S ;end

 if pos(S,LV) = 0 & length(S) = 1 then do
   err = err + 1
   say  "erreur ! ; symbole de départ non vu comme variable "
   say  " symbole de départ : " S
   say  " liste des variables " LV
   pull .
 end /* pos(S,LV) = 0 */

 

/* # 1.4 Lecture des règles de production */


 /* On vient tester que chaque partie gauche notée X  */
 /* a chacun de  ses mots (noté XJ) dans LAuLv qui    */
 /* est la concaténation de LA et LV  ; même test     */
 /* pour chaque partie gauche LY et ses mots YJ       */
 /* pour un bel affichage, on supprime les blancs     */
 /* de tête et de queue éventuels.                    */

 /* On associe à la règle nø i :                             */
 /*        p.g.i    la partie droite avant >                 */
 /*        p.r.i    le nombre de productions séparées par |  */
 /*        p.d.i.1  est la première production               */
 /*        p.d.i.2  est la deuxième production               */
 /*         ...                                              */
 /*        p.d.i.(p.r.i) est la dernière                     */
 /*        p.n.i    compte le nombre de fois où la règle     */
 /*                  est utilisée.                           */
 /*        e.i      est l'impulsion associée à la règle,     */
 /*                  elle correspond au modulo (option MOD)  */
 /*                  ou au nombre de répétitions de la règle */
 /*                  (option REP). Si e.i n'existe pas dans  */
 /*                  le fichier de grammaire, on lui         */
 /*                  attribut la valeur 1 .                  */

 i = 0
 LAuLV = la lv
 do while lines(fichgram)> 0 /* > 0 pour Unix */
      i = i+1
      lp = linein( fichgram )

      if pos("[",lp) = 0 then do
         parse value lp with x ">" y ";" rems
         e.i = 1
         end
      else do ; parse value lp with x ">" y "[" e.i "]" ";" rems ; end

      x = strip(x,'B')

      if gen = "REP" then do
         /* Le test suivant va compter le nombre de règles s'adressant */
         /* à la même partie gauche.                                   */
         if x = temoin then do ; nbr.x = nbr.x + 1 ; end
         else do ; nbr.x = 1 ; end
         p.g.i = x /* partie gauche */
         temoin = p.g.i
      end /* if gen = "REP" */
      else do ; p.g.i = x ; end

      y = strip(y,'B') "|"
      ly = y
      ind124 = pos("|",ly)
      nbpr = 0
      do while ind124 > 0
          nbpr = nbpr + 1
          p.d.i.nbpr = strip(substr(ly,1,ind124-1),'B') /* partie droite */
          ly = substr(ly,ind124+1)
          ind124 = pos("|",ly)

          if gen = "MOD" then do
            /* On attribut un indice égale à 1 à chaque mot de la  */
            /* partie droite de la règle. Cet indice servira, par  */
            /* la suite à déterminer la règle devant s'appliquer.  */
             resul = ''
             rest = p.d.i.nbpr||" "
             do while pos(" ",rest) > 0
                parse value rest with m " " rest
                m = strip(m,'B')||" 1 "
                resul = resul||m
             end  /* do while pos(" ",rest) > 0 */
             p.d.i.nbpr = strip(resul,'B')
          end /* if gen = "MOD" */

      end /* do while ind124 > 0 */
      p.r.i = nbpr
      p.n.i = 0 /* nombre de fois */

      do j = 1 to words(x)
         xj = word(x,j)
         if pos(xj , laulv ) = 0 then do
             say "erreur ; partie gauche de règle invalide " xj
             err = err + 1
             pull .
         end /* if pos(x  laulv ) = 0 */
      end /* do j = 1 to word(x) */

      do j = 1 to words(y)
         yj = word(y,j)
         if pos( yj , laulv ) = 0 & yj  \= "|" then do
             say "erreur ; règle nø " i " invalide : "  lp
             say "erreur ; partie droite de règle invalide " yj
             err = err + 1
             pull .
         end /* if pos(y , laulv ) = 0 */
      end /* do j = 1 to word(y) */

 end /* while lines(fichgram) */
 np = i

 

/* # 2.0 Affichage de la grammaire */


 /* On rappelle tout d'abord les constituants de la grammaire. */

 /* "cls" */
 say " Analyse du fichier grammaire : " fichgram
 say " ----------------------------   "
 say

 if gen = "MOD" then do ; say " La génération de productions se fera en mode MODULO" ; end
 else do ; say " La génération de productions se fera en mode REPETITION" ; end
 say

 say " Alphabet : "
 do i = 1 to na
    say "    " substr(A.i "      ",1,6)  " est le symbole numéro " i
 end /* do i = 1 to na */
 if na = 0 then do
    say "    (aucun alphabet, sans doute un système L)"
 end
 say

 say " Variables : "
 do i = 1 to nv
    say "    " substr(V.i "      ",1,6) " est la variable numéro " i
 end /* do i = 1 to nv */
 say

 say " Symbole de départ est : " S
 say

 if (np >= 3) & (etapf \= "OUI") & nowait \= "OUI" then do
   call charout , "                  Enter pour continuer "
   pull .
 end /* if np > 5 */

 say " Productions : "
 do i = 1 to np
    call charout , "     production " format(i,2) " : " p.g.i " ---> "
    do j = 1 to p.r.i
       call charout , p.d.i.j
       if j < p.r.i then do ; call charout , " | " ; end
    end
    say
    if (i = 20) & (etapf \= "OUI")  then do
       call charout , "                  Enter pour continuer "
       pull .
    end /* if i = 20 */
 end /* do i = 1 to np */
 say

 say " Impulsions : "
 do i = 1 to np
    say "     Pour la production "format(i,2)" : ["e.i"]"
 end
 say

 call charout , "                  Enter pour continuer "
 pull .

 if interp="INT" then do
    say
    say " Interprétation Numérique : "
    fichint = nomf||'.int'
    if existe(fichint) = ""  then do
       say "     Fichier " fichint "non vu "
       say "     Abandon du programme "
       exit -1
    end /* if existe(fichint) = 0 */
    vaut. = 0
    do while lines(fichint) > 0
       lg = linein(fichint)
       ma = word(lg,1) ; mb = word(lg,2) ;
       vaut.ma = mb
       say "      " ma " vaut " mb
    end
    say

 end

 if err > 0 | arret = "STOP" then do ; exit ; end

 /* # 3.0 Productions étape par étape */

 /* une boucle infinie et qui  s'arrête à chaque étape         */
 /* est utilisée ; on sort soit par la frappe d'un mot, soit   */
 /* par le Ctrl-Break habituel.                                */

 

/* # 3.1 Génération des productions */


 chdep     = ""
 Filtre    = ""
 Ofltre    = ""
 AfficheSt = ""
 SupVar    = ""

 if filtrage = "OUI" then  do
    call charout , " Affichage des productions "
    call charout , " avec le Start Symbol ? (NON ou enter pour oui) "
    pull AfficheSt .
    call charout , " Filtre de début d'affichage ? "
    parse pull Filtre
    call charout , " Filtre d'omission en début  ? "
    parse pull Ofltre
    call charout , " Suppression des variables sauf le SS ? "
    parse pull SupVar
    call charout , " Chaîne de départ (et indice si mode = MODULO) ? "
    parse pull chdep
 end /* fin de si sur filtrage */
 if chdep = "" then do ; chdep = nS ; end
 lonfil = length(Filtre)
 lonOfl = length(Ofltre)

 etape = 0 ; say ; say " Etape : " etape
 if filtrage \= "OUI" then do ; say " " S ; end
 else do ; say " " chdep ; end
 say ;  vu.chdep = 1
/* if interp="INT"
      then do
           say "  valeur : " format(vaut.chdep,5)
      end
     else do ; say ; end */
 fichprod = virtuel||"anagram.prd" /* et non pas "f:anagram.prd" */
 fichsor  = virtuel||"anagram.sor"
 call dse(fichprod)
 /* pas de call dse(fichsor) car il est fait dans
    la boucle de réécriture */
 call lineout fichprod , chdep
 call lineout fichprod

 /* toutes les productions obtenues à une étape sont stockées    */
 /* dans le fichier fichprod. on écrit les nouvelles productions */
 /* dans fichsor. bien sùr, en fin d'étape, fichsor  est recopié */
 /* dans fichprod. chaque production lue s'appelle ls            */

 do nr = 1 to np ; p.n.nr = 0 ; test.nr = e.nr
    do iet = 1 to 50 ; p.n.nr.iet = 0 ; end
 end

infini:
do forever
   call dse(fichsor)
   etape = etape + 1
   tot.etape = 0
   say " Etape : " etape
   vu. = 0  ; vu.tmp = 0
   do while lines(fichprod) >0
      ls = linein(fichprod)
      nt = words(ls)
     /* à chaque étape, chacune des productions précédentes          */
     /* qu'on note  LS est analysée : elle contient NT mots nommés   */
     /* MS. On va rechercher la régle qui s'applique.                */
     /* On remplace alors MS par son substitué.                      */
     /* On passe alors  au mot suivant.                              */
     /* Après l'affichage pur et dur de chaque nouvelle              */
     /* production, on tente  - un affichage simplifié :             */
     /*               aacbbbc donne aýcb3c   ( fichier SIMPLE.REX )  */
     /*                       - un affichage cumulé :                */
     /*               aacbbbc donne aýcýb3   ( fichier CUMULE.REX )  */

      declenche = 0
      alphapres = 0
      nls = ""
      do m = 1 to nt by pas
         nr = 0
         ms = strip(word(ls,m),'B')

         if gen = "MOD" then do

         /*       GENERATION DES PRODUCTIONS EN MODE MODULO          */
         /* On va chercher la règle qui s'applique à MS. Pour cela   */
         /* on test la présence de MS dans la partie droite de       */
         /* chaque règle, et le modulo donné par la division de      */
         /* l'indice de MS (MS.T) par l'impulsion associé à la règle */
         /* (E.Q). Si plusieurs règle sont susceptibles de           */
         /* s'appliquer on prend celle ayant l'impulsion la plus     */
         /* importante, ou la première des deux si elles ont la      */
         /* même impulsion.                                          */

            ms.t = strip(word(ls,m+1),'B')
            val = 0
            do q = 1 to np
              if pos(ms,p.g.q) > 0 then do
                declenche = 1
                if ( ms.t // e.q = 0 ) & ( e.q > val ) then do
                   val = e.q
                   nr = q
                end /* fin si (ms.t//e.q=0)&(e.q>val) */
              end /* fin si pos(ms,p.g.q) */
            end /* do q = 1 to np */

            if ( nr \= 0 ) then do
                nbpec = p.r.nr

                if nbpec = 1 then do ; h = 1 ; end
                else do
                    alea = random(1,nbpec)
                    h = alea
                end  /* else do */

                p = wordpos(ms,p.d.nr.h)
                if p > 0 then do         /* test s'il y a réécriture du mot */
                    nms.t = ms.t + 1
                    nms = subword(p.d.nr.h,1,p)||" "||nms.t||" "||subword(p.d.nr.h,p+2)
                    nms = strip(nms,'B')
                end  /* if p > 0 */
                else do ; nms = strip(p.d.nr.h,'B') ; end

                p.n.nr = p.n.nr + 1
                p.n.nr.etape = p.n.nr.etape + 1
                tot.etape = tot.etape + 1

            end  /* if nr \= 0 */
            else do
                if wordpos(ms,LA) = 0 then do
                    nms.t = ms.t + 1
                    nms = ms||" "||nms.t
                end /* if wordpos(ms,LA) = 0 */
            end  /* else do de if nr \= 0 */

            if wordpos(ms,LA) > 0 then do
                nms.t = ms.t + 1
                nms = ms||" "||nms.t
                alphapres = 1
            end  /* if worpos(ms,LA) > 0 */

         nls = nls||" "||nms

         end /* if gen = "MOD" */

         if gen = "REP" then do

         /*       GENERATION DES PRODUCTIONS EN MODE REPETITION      */

         /* Si aucune règle ne s'applique NBR est mis à 0            */
         if datatype(nbr.ms,'N') = 0 then do ; nbr.ms = 0  ; end

         /* On va rechercher la règle qui s'applique le mieux        */
         /* à MS. On test si plusieurs règles sont susceptibles      */
         /* de s'appliquer, si oui on recherche laquelle est la      */
         /* bonne en vérifiant que MS est bien présent dans la       */
         /* partie gauche de la règle Q, et que le nombre de fois où */
         /* la règle doit s'appliquer (E.Q) n'est pas dépassé        */
         /* (TEST.Q > 0). Si toutes les règles correspondants au mot */
         /* ont été appliquées le bon nombre de fois, on             */
         /* réinitialise la variable TEST.Q  (= E.Q) .               */

         /* ATTENTION : l'application des règles se fait suivant     */
         /* leur ordre dans le fichier de grammaire                  */
           tem = 0
           if nbr.ms > 1  then do while(nr = 0)
               q = 1
               do while(tem = 0)
                  if pos(ms,p.g.q) > 0 & test.q \= 0 then do
                     test.q = test.q - 1
                     nr = q
                     tem = 1
                  end  /* if pos(ms,p.g.q) > 0 & test.q \= 0 */
                  else do ; q = q + 1 ; end
                  if q > np then do ; tem = 1 ; end
               end  /* do while(tem = 0) */

               if nr = 0 then do
                  do k = 1 to np
                     if pos(ms,p.g.k) > 0 then do ; test.k = e.k ; end
                  end  /* do k = 1 to np */
                  tem = 0
               end /* if nr = 0 */

           end /* if nbr.ms > 1 */
           else do q = 1 to np
              if pos(ms,p.g.q) > 0 then do ; nr = q ; end
           end /* else do q = 1 to np */

           if (nr \= 0 ) then do
              nbpec = p.r.nr

              if nbpec = 1 then nms = strip(p.d.nr.1,'B')
              else do
                    alea = random(1,nbpec)
                    nms = strip(p.d.nr.alea,'B')
              end  /* else do */

              p.n.nr = p.n.nr + 1
              p.n.nr.etape = p.n.nr.etape + 1
              tot.etape = tot.etape + 1
              declenche = 1
              nls = nls||" "||nms
           end /* if nr \= 0 */

           if wordpos(ms,LA) > 0 then do
              nms = ms
              nls = nls||" "||nms
              alphapres = 1
           end  /* if wordpos(ms,LA) > 0 */

         end /* if gen = "REP" */

      end /* m = 1 to nt by pas */

      nls= strip(nls,'B')
      vu.tmp   = vu.tmp   + 1
      aff = pos(s,nls) = 0 | AfficheSt = ""
      aff = aff & (declenche | alphapres)
      aff = aff & (vu.tmp = 1)
      if filtrage = "OUI" then do
          if lonfil > 0 then do ; aff = aff & (substr(nls||"       ",1,lonfil) = Filtre) ; end
          if lonOfl > 0 then do ; aff = aff & (substr(nls||"       ",1,lonOfl)\= Ofltre) ; end
      end /* filtrage = "OUI" */
      if SupVar <> "" then do ;
         do iv = 1 to nv
            if V.iv \= S then do ; aff = aff & pos(V.iv,nls) = 0 ; end
         end /* fin pour iv */
      end /* fin de si suvar <> "" */
     /* affichage soigné */
     tt = 0
     if aff & affiche \= "NON" then do i = 1 to words(nls) by pas
        mot = strip(word(nls,i),'B')
        call charout ," "mot
        tt = tt + length(mot) + 1
        if tt >= 64 then do ; say ; tt = 0 ; end
     end /* finsi aff & affiche */
     say

     call lineout fichsor , nls

 

/* # 3.2 Cumul */


     if cumul = "OUI" then do ;
     call cumule(pas nls) ; end

 

/* # 3.3 Simplification */


     if simplif = "OUI" then do ; call simple(pas nls) ; end

 

/* # 3.4 Interprétation numérique */


     if interp="INT" then do
        v = 0
        do j = 1 to words(nls) by pas
           ind = word(nls,j)
           v = v + vaut.ind
        end
        say "  valeur    : " format(v,5)
        call lineout sorint , v
     end

   end /* } do while lines(fichprod)*/
   if declenche = 0 then do
      say
      say " Plus aucune règle ne s'applique... abandon avec complétion."
      if ( etapf = "OUI" ) & ( etape < nef ) & ( interp = "INT" ) then do k = etape to nef
         call lineout sorint , v
      end
      call lineout sorint
      call GNUPLOT
      exit
   end
   call lineout fichsor
   call lineout fichprod
   "cp " fichsor fichprod
   call lineout fichprod
/*   copy fichsor fichprod '> nul'  */

   /* relance éventuelle */
   if etapf \= "OUI" & nowait \= "OUI" then do
        say
        call charout , copies(" ",55) " fin de l'étape "
        pull rep
        if length(rep) > 0 then live = "oui"
   end ; else if etape = nef then leave
   if live = "oui" then leave
end /* forever */

 

/* # 4.0 Affichage des statistiques */


 if nostat \= "OUI" then do
    say
    say " Comptage des Productions : sur " etape " étape(s) "
    say ; call charout , "Prod nø"
    taillesor = 5
    do i = 1 to np
       call charout , format(i,taillesor)
    end /* i = 1 to np */
    say ; say ; call charout , "       "
    do ie = 1 to etape
      do i = 1 to np
        call charout ,  format(p.n.i.ie,taillesor)
/*        if ie = 20 then do
           call charout , "                  Enter pour continuer "
           pull .

        end /* if (ie == 20 )  */
*/
      end /* do i = 1 to np */
      call charout , "    (étape " format(ie,2) ") total "
      say            format(tot.ie,taillesor)
      call charout , "       "
   end /* if ie = 1 to etape */
    say
    call charout ,  " Total "
    do i = 1 to np
      call charout ,  format(p.n.i,taillesor)
    end
    call lineout sorint
    say
end

 

/* # 5.0 Fabrication d'un fichier utilisable par gnuplot */


GNUPLOT :
if gnuplt = "GPL" then do
   txt = "plot '"sorint"' with linespoints"
   call lineout sorgpl,txt
   call lineout sorgpl
   'gpl' nomf
   say
   say " Pour revoir le graphique tapez : gpl "nomf
   say "                             OU : gnuplot "sorgpl
end  /* if gnuplot = "GPL" */

exit

error:
failure:
halt:
syntax:
 say
 say " déroutement volontaire, ligne " Sigl
 do tag  = 1 to 5
    vtag = sigl-3+tag
    say "("vtag") " sourceline(vtag)
 end
 trace '?i'
 say " donc..."
exit