IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Pascal Discussion :

Reconnaissance d'un code source en Pascal


Sujet :

Langage Pascal

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 172
    Billets dans le blog
    9
    Par défaut Reconnaissance d'un code source en Pascal
    Bonjour !

    Je m'étais amusé à faire un formateur (?) de code basé sur les expressions régulières. Ce formateur devait supprimer les commentaires et espacer régulièrement les caractères. Cependant j'ai très vite rencontré un problème avec les chaînes littérales : il fallait les épargner, ce qui paraissait impossible avec les moyens que j'avais choisi d'utiliser. La solution que j'ai trouvée est d'extraire les chaînes littérales, de les placer dans un tableau, de les remplacer provisoirement dans le code par un matricule, afin de les restituer après traitement du code.

    Voici le programme que j'ai imaginé pour faire cela.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
     
    program extractor2;
     
    {$APPTYPE CONSOLE}
     
    uses
      Classes, SysUtils, IOUtils;
     
    function SubString(const aSource: string; aStart: integer; aEnd: integer = MAXINT): string;
    begin
      result := Copy(aSource, aStart, aEnd - aStart + 1);
    end;
     
    var
      allText: string;
      i, j, k: integer;
      c: char; { Commentaire. }
      l: integer; { Chaîne littérale. }
      d: boolean; { Directive compilateur. }
      tc, tl, td: TStringList; { Tableau commentaires, tableau chaînes littérales, tableau directives. }
     
    begin
      tc := TStringList.Create;
      tl := TStringList.Create;
      td := TStringList.Create;
     
      if (ParamCount = 1) and FileExists(ParamStr(1))then
        allText := TFile.ReadAllText(ParamStr(1))
      else
        allText := TFile.ReadAllText('extractor2.pp');
     
      i := 1;
      j := 0;
      k := 0;
     
      c := #0; { Pas de commentaire en cours. }
      l := 0; { Pas de chaîne littérale en cours. }
      d := FALSE; { Pas de directive en cours. }
     
      while i <= Length(allText) do
      begin
        if c <> #0 then { On est en train de parcourir un commentaire et on en cherche la fin. }
        begin
          { La variable c contient le premier caractère trouvé, qui permet de savoir à quel type de
             commentaire on a affaire et donc comment il se termine. }
          if ((c = '{') and (allText[i] = '}'))
          or ((c = '(') and (allText[i] = ')') and (allText[i - 1] = '*'))
          or ((c = '/') and (i < Length(allText)) and (allText[i + 1] = #13)) then
          begin
            k := i;
            tc.Append(SubString(allText, j, k));
            { Les commentaires sont purement et simplement supprimés. }
            allText := Format(
              '%s%s',
              [SubString(allText, 1, j - 1), SubString(allText, k + 1)]
            );
            c := #0;
            i := j - 1;
          end;
        end else
          if l <> 0 then { On est en train de parcourir une chaîne littérale et on en cherche la fin. }
          begin
            if allText[i] = '''' then { Si le caractère courant est un guillemet simple... }
            begin
              Inc(l); { on le compte. }
              { Si le nombre de guillemets trouvés est pair et que le caractère suivant n'est pas un
                guillemet, on a trouvé la fin de la chaîne. }
              if (l mod 2 = 0) and (i < Length(allText)) and (allText[i + 1] <> '''') then
              begin
                k := i;
                { On place une copie de la chaîne, guillemets compris, dans un tableau. }
                tl.Append(SubString(allText, j, k));
                { On remplace la chaîne littérale par un motif contenant le numéro de la chaîne, son
                  index dans le tableau. }
                allText := Format(
                  '%s_litteral_%d_%s',
                  [SubString(allText, 1, j - 1), tl.Count, SubString(allText, k + 1)]
                );
                l := 0;
                i := j - 1;
              end;
            end;
          end else
            { Même procédure pour les directives. }
            if d then
            begin
              if allText[i] = '}' then
              begin
                k := i;
                td.Append(SubString(allText, j, k));
                allText := Format(
                  '%s_directive_%d_%s',
                  [SubString(allText, 1, j - 1), td.Count, SubString(allText, k + 1)]
                );
                d := FALSE;
                i := j - 1;
              end;
            end else
              { Autrement, on cherche le début d'un commentaire, }
              if ((allText[i] = '{') and (i < Length(allText)) and (allText[i + 1] <> '$'))
              or ((allText[i] = '(') and (i < Length(allText)) and (allText[i + 1] = '*'))
              or ((allText[i] = '/') and (i < Length(allText)) and (allText[i + 1] = '/')) then
              begin
                j := i;
                c := allText[i];
              end else
                { ou d'une chaîne littérale, }
                if allText[i] = '''' then
                begin
                  j := i;
                  l := 1;
                end else
                  { ou d'une directive. }
                  if ((allText[i] = '{') and (i < Length(allText)) and (allText[i + 1] = '$')) then
                  begin
                    j := i;
                    d := TRUE;
                  end;
     
        Inc(i);
      end;
     
      TFile.WriteAllText('1.txt', allText);
     
      with TStringList.Create do
      begin
        for i := 0 to tc.Count - 1 do Append(Format('comment=[%s]', [tc[i]]));
        for i := 0 to tl.Count - 1 do Append(Format('literal=[%s]', [tl[i]]));
        for i := 0 to td.Count - 1 do Append(Format('directive=[%s]', [td[i]]));
        SaveToFile('2.txt');
        Free;
      end;
     
      tc.Free;
      tl.Free;
      td.Free;
    end.
    Si aucun argument n'est passé au programme, il traite pour démonstration son propre code source.
    Fichiers attachés Fichiers attachés

  2. #2
    Responsable Pascal, Lazarus et Assembleur


    Avatar de Alcatîz
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Mars 2003
    Messages
    8 052
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2003
    Messages : 8 052
    Billets dans le blog
    2
    Par défaut
    Bonjour Roland,

    J'ai compilé et testé ton code source : si l'on met un commentaire de type double slash, le programme ne traite plus par la suite aucun commentaire ni aucune chaîne.

    Si je n'ajoute pas la directive {$MODE DELPHI}, le paramètre de la forme aEnd: integer = MAXINT déclenche une erreur de compilation (Free Pascal 2.6.4 sous Linux).
    Règles du forum
    Cours et tutoriels Pascal, Delphi, Lazarus et Assembleur
    Avant de poser une question, consultez les FAQ Pascal, Delphi, Lazarus et Assembleur
    Mes tutoriels et sources Pascal

    Le problème en ce bas monde est que les imbéciles sont sûrs d'eux et fiers comme des coqs de basse cour, alors que les gens intelligents sont emplis de doute. [Bertrand Russell]
    La tolérance atteindra un tel niveau que les personnes intelligentes seront interdites de toute réflexion afin de ne pas offenser les imbéciles. [Fiodor Mikhaïlovitch Dostoïevski]

  3. #3
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 172
    Billets dans le blog
    9
    Par défaut
    @Alcatîz

    Merci pour l'essai et le rapport d'erreur.

    Pour les commentaires de type double slash qui sont mal gérés, je n'observe pas cette erreur chez moi mais c'est sans doute lié aux fins de ligne différentes sous Linux ? Je pense que la modification suivante devrait résoudre le problème :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
          //or ((c = '/') and (i < Length(allText)) and (allText[i + 1] = #13)) then
          or ((c = '/') and (i < Length(allText)) and (allText[i + 1] in [#10, #13])) then
    Pour le mode de compilation, oui c'est vrai. Donc à l'avenir je penserai à mettre une directive directement dans le code.

  4. #4
    Responsable Pascal, Lazarus et Assembleur


    Avatar de Alcatîz
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Mars 2003
    Messages
    8 052
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2003
    Messages : 8 052
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Roland Chastain Voir le message
    c'est sans doute lié aux fins de ligne différentes sous Linux ? Je pense que la modification suivante devrait résoudre le problème
    Oui, ça marche !
    Règles du forum
    Cours et tutoriels Pascal, Delphi, Lazarus et Assembleur
    Avant de poser une question, consultez les FAQ Pascal, Delphi, Lazarus et Assembleur
    Mes tutoriels et sources Pascal

    Le problème en ce bas monde est que les imbéciles sont sûrs d'eux et fiers comme des coqs de basse cour, alors que les gens intelligents sont emplis de doute. [Bertrand Russell]
    La tolérance atteindra un tel niveau que les personnes intelligentes seront interdites de toute réflexion afin de ne pas offenser les imbéciles. [Fiodor Mikhaïlovitch Dostoïevski]

  5. #5
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 172
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par Alcatîz Voir le message
    Oui, ça marche !
    Merci pour le retour.

    Voici une version plus complète du programme, qui restitue les chaînes extraites (au moyen des expressions régulières de la bibliothèque FLRE).
    Fichiers attachés Fichiers attachés

  6. #6
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 491
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 491
    Par défaut
    salut

    cela marche pas mal même en Delphi 7 après quelque modification

Discussions similaires

  1. Codes sources Pascal : où les trouver, comment participer ?
    Par Alcatîz dans le forum Contribuez
    Réponses: 5
    Dernier message: 14/03/2024, 17h16
  2. PasDoc : Utilitaire de documentation de code source Pascal
    Par forum dans le forum Outils à télécharger
    Réponses: 0
    Dernier message: 23/03/2011, 21h20
  3. [Pascal] Comment nettoyer un code source ?
    Par ILP dans le forum Outils
    Réponses: 2
    Dernier message: 09/10/2009, 22h59
  4. Réponses: 4
    Dernier message: 14/12/2008, 20h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo