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

  1. #1
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 342
    Points : 12 109
    Points
    12 109
    Billets dans le blog
    7

    Par défaut Supprimer les commentaires d'un code source

    Bonjour !

    j'ai commencé un exercice sur les patterns qui consiste à supprimer les commentaires d'un code source en Pascal et à effectuer d'autres opérations de formatage.

    Voici le script :

    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
     
    function filepath(file)
      if string.find(file, "\\") then
        local r = file
        while string.sub(r, #r) ~= "\\" do
          r = string.sub(r, 1, -2)
        end
        return r
      else
        return ""
      end
    end
     
    local filename = filepath(arg[0]) .. "sample.pas"
    local destfilename = filepath(arg[0]) .. "result.txt"
     
    if #arg == 1 then
      filename = arg[1]
    end
    if #arg == 2 then
      filename = arg[1]
      destfilename = arg[2]
    end
     
    print(filename)
    print(destfilename)
     
    -- lire le contenu du fichier dans une chaîne
     
    io.input(filename)
    local s = io.read("*a")
     
    -- modifier la chaîne
     
      -- commentaires
     
    s = string.gsub(s, "//[^\n]*\n", "\n")
    s = string.gsub(s, "{[^$].-}", "")
    s = string.gsub(s, "%(%*[^$].-%*%)", "")
     
      -- virgules
     
    while string.match(s, "%s,") do
      s = string.gsub(s, "%s,", ",")
    end
    while string.match(s, ",%s") do
      s = string.gsub(s, ",%s", ",")
    end
    s = string.gsub(s, ",", ", ")
     
      -- opérateur
     
    while string.match(s, "%s=") do
      s = string.gsub(s, "%s=", "=")
    end
    while string.match(s, "[^:]=%s") do
      s = string.gsub(s, "([^:])=%s", "%1=")
    end
    s = string.gsub(s, "([^:])=", "%1 = ")
     
      -- opérateur composé
     
    while string.match(s, "%s:=") do
      s = string.gsub(s, "%s:=", ":=")
    end
    while string.match(s, ":=%s") do
      s = string.gsub(s, ":=%s", ":=")
    end
    s = string.gsub(s, ":=", " := ")
     
    -- écrire la chaîne dans un fichier
     
    io.output(destfilename)
    io.write(s)
    Et le code source en Pascal :

    Code delphi : 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
     
    program Source; {pour essayer un programme qui supprime les commentaires}
     
    {$APPTYPE CONSOLE}
     
    {$R *.res}
     
    begin
      WriteLn('Bonjour!');
      {$IFDEF VER230}Write('{ à conserver }'){$ELSE}Write('// à conserver '){$ENDIF};
      {commentaire}Write('(* à conserver *)');
      {commentaire
      sur deux lignes}
      WriteLn;// barres obliques
      (* parenthèses et astérisques *)
      // guillemets dans une chaîne !
      WriteLn('L''oiseau est dans l''arbre.');
      WriteLn('');
      WriteLn('a');
      WriteLn('a''');
      WriteLn('''a');
      WriteLn('''');
      WriteLn('''''');
    end.

    Je sèche sur le point suivant : comment ne pas supprimer les commentaires se trouvant dans les chaînes ?

    Code delphi : 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
    program Source; 
     
    {$APPTYPE CONSOLE}
     
    {$R *.res}
     
    begin
      WriteLn('Bonjour!');
      {$IFDEF VER230}Write(''){$ELSE}Write('
      Write('');
     
      WriteLn;
     
     
      WriteLn('L''oiseau est dans l''arbre.');
      WriteLn('');
      WriteLn('a');
      WriteLn('a''');
      WriteLn('''a');
      WriteLn('''');
      WriteLn('''''');
    end.

  2. #2
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    janvier 2013
    Messages
    388
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Conseil

    Informations forums :
    Inscription : janvier 2013
    Messages : 388
    Points : 713
    Points
    713

    Par défaut

    Bonjour Roland.
    Les chaînes en question commencent par un apostrophe. Il suffit d'ajouter qu'il ne doit pas en avoir au début du motif :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    s = string.gsub(s, "[^']//[^\n]*\n", "\n")
    s = string.gsub(s, "[^']{[^$].-}", "")
    s = string.gsub(s, "[^']%(%*[^$].-%*%)", "")
    Et ça doit suffire.

  3. #3
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 342
    Points : 12 109
    Points
    12 109
    Billets dans le blog
    7

    Par défaut

    Merci pour ta réponse. Content de voir qu'il y a par ici des amateurs de Lua et des expressions régulières.

    La solution proposée fonctionne effectivement avec l'exemple particulier que j'ai donné. Une remarque toutefois, c'est que pour ne pas perdre le caractère initial en cas de remplacement il faudrait, je pense, le capturer et le restituer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    s = string.gsub(s, "([^'])//[^\n]*\n", "%1\n")
    s = string.gsub(s, "([^']){[^$].-}", "%1")
    s = string.gsub(s, "([^'])%(%*[^$].-%*%)", "%1")
    Quoiqu'il en soit, il suffirait qu'il y ait un espace au début de la chaîne pour que ça ne fonctionne plus.

    Code delphi : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      {$IFDEF VER230}Write(' { à conserver }'){$ELSE}Write(' // à conserver '){$ENDIF};
      {commentaire}Write(' (* à conserver *)');

  4. #4
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 342
    Points : 12 109
    Points
    12 109
    Billets dans le blog
    7

    Par défaut

    J'ai essayé d'extraire les chaînes de mon code source afin de vérifier qu'elles ne contiennent pas de commentaire, auquel cas l'opération de formatage serait abandonnée.

    Je n'ai pas trouvé de solution parfaite pour extraire les chaînes : soit il m'en manque, soit j'en ai trop. En attendant de trouver mieux, j'ai retenu le code qui "ratisse le plus large".

    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
    io.input(source)
    local s = io.read("*a")
     
    -- étude préalable
     
    local stop = false
     
    for ss in string.gmatch(s, "[^\n]*[^\n]") do
      local sss = string.match(ss, "'.*'")
      if sss then
        if string.match(sss, "//.*")
        or string.match(sss, "{[^$].-}")
        or string.match(sss, "%(%*[^$].-%*%)") then
          stop = true
        end
      end
    end

  5. #5
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 342
    Points : 12 109
    Points
    12 109
    Billets dans le blog
    7

    Par défaut

    Il est sans doute assez rare de trouver des commentaires dans des chaînes littérales mais le même problème concerne toutes les opérations de formatage qui sont susceptibles d'affecter le contenu des chaînes. La seule solution que je voie est d'extraire toutes les chaînes, de traiter le code, et de remettre les chaînes à leur place. Ça me paraissait compliqué avant de le faire mais finalement avec Lua ce genre de chose se fait facilement.

    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
     
    function filepath(file)
      if string.find(file, "\\") then
        local r = file
        while string.sub(r, #r) ~= "\\" do
          r = string.sub(r, 1, -2)
        end
        return r
      else
        return ""
      end
    end
     
    local filename = filepath(arg[0]) .. "source.pas"
     
    if #arg == 1 then
      filename = arg[1]
    end
     
    --print(filename)
     
    io.input(filename)
    local s = io.read("*a")
     
    local litteral = false
    local last = false
    local n = 0
     
    local i = 1
    local j, k = 0, 0
    local t = {}
     
    while i < #s do
      local c = string.sub(s, i, i)
      if c == "'" then
        n = n + 1 
        if litteral then
          if (n % 2 == 0) then
            if (i < #s) and not (string.sub(s, i + 1, i + 1) == "'") then
              litteral = false
              last = true
              k = i
            end
          end
        else
          litteral = true
          j = i
        end
      end
      if last then
        table.insert(t, string.sub(s, j, k))
        s = string.sub(s, 1, j - 1) .. "_STRING_" .. #t .. "_" .. string.sub(s, k + 1)
        i = j - 1
        last = false
      end
      i = i + 1
    end
     
    print(s)
     
    for i = 1, #t do
      print("_STRING_" .. i .. "_ =[" .. t[i] .. "]")
    end
    Code text : 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
    program source; {pour essayer un programme qui supprime les commentaires}
     
    {$APPTYPE CONSOLE}
     
    {$R *.res}
     
    begin
      WriteLn(_STRING_1_);
      {$IFDEF VER230}Write(_STRING_2_){$ELSE}Write(_STRING_3_){$ENDIF};
      {commentaire}Write(_STRING_4_);
      {commentaire
      sur deux lignes}
      WriteLn;// barres obliques
      (* parenthÞses et astÚrisques *)
      // guillemets dans une cha¯ne !
      WriteLn(_STRING_5_);
      WriteLn(_STRING_6_);
      WriteLn(_STRING_7_);
      WriteLn(_STRING_8_);
      WriteLn(_STRING_9_);
      WriteLn(_STRING_10_);
      WriteLn(_STRING_11_);
      WriteLn(_STRING_12_);
      WriteLn(_STRING_13_);
      WriteLn(_STRING_14_);
    end.
     
    _STRING_1_ =['Bonjour!']
    _STRING_2_ =['{ 1 }']
    _STRING_3_ =['// 2 ']
    _STRING_4_ =['(* 3 *)']
    _STRING_5_ =['L''oiseau est dans l''arbre.']
    _STRING_6_ =['']
    _STRING_7_ =['a']
    _STRING_8_ =['a''']
    _STRING_9_ =['''a']
    _STRING_10_ =['''']
    _STRING_11_ =['''''']
    _STRING_12_ =['{ 4 }''']
    _STRING_13_ =['''{ 5 }']
    _STRING_14_ =['{ 6 }''{ 7 }']
    Appuyez sur une touche pour continuer...

  6. #6
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 342
    Points : 12 109
    Points
    12 109
    Billets dans le blog
    7

    Par défaut

    Et pour reconstituer toute la chaîne (en tenant compte des parties éventuellement supprimées ) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    j, k = string.find(s, "_STRING_[%d]+_")
    while j do
      i = string.match(string.sub(s, j, k), "[%d]+")
      i = tonumber(i)
      s = string.sub(s, 1, j - 1) .. t[i] .. string.sub(s, k + 1)
      j, k = string.find(s, "_STRING_[%d]+_", j)
    end
     
    io.output("result.txt")
    io.write(s)

  7. #7
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 342
    Points : 12 109
    Points
    12 109
    Billets dans le blog
    7

    Par défaut

    La solution que j'ai proposée précédemment (prélever les chaînes littérales, traiter le reste, puis les restituer) est trop simple : elle échoue s'il y a une apostrophe dans un commentaire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    begin
      // '
      WriteLn('un');
    Il faudrait donc commencer par enlever les commentaires, comme j'avais fait au début, mais en tenant compte des chaînes littérales qui pourraient aussi contenir des commentaires. Je ne crois pas qu'on puisse faire cela par des expressions régulières.

  8. #8
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 342
    Points : 12 109
    Points
    12 109
    Billets dans le blog
    7

    Par défaut

    Cette fois, c'est bon (je crois) : le programme suivant extrait d'un code source en Pascal les commentaires et les chaînes littérales, sans erreur, même si les chaînes contiennent des commentaires et les commentaires des apostrophes.

    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
    function filepath(file)
      if string.find(file, "\\") then
        local r = file
        while string.sub(r, #r) ~= "\\" do
          r = string.sub(r, 1, -2)
        end
        return r
      else
        return ""
      end
    end
     
    local source = filepath(arg[0]) .. "source.pas"
    local destination = filepath(arg[0]) .. "result.txt"
     
    if #arg >= 1 then
      source = arg[1]
      if #arg >= 2 then
        destination = arg[2]
      end
    end
     
    print(source)
    print(destination)
     
    io.input(source)
    local s = io.read("*a")
     
    local i, j, k = 1, 0, 0
    local cmt, str = false, false
    local tcmt, tstr = {}, {}
     
    while i <= #s do
      local c = string.sub(s, i, i)
      if cmt then
        if ((cmt == "{") and (c == "}"))
        or ((cmt == "(") and (c == ")") and (string.sub(s, i - 1, i - 1) == "*"))
        or ((cmt == "/") and (string.sub(s, i + 1, i + 1) == "\n")) then
          k = i
          table.insert(tcmt, string.sub(s, j, k))
          s = string.sub(s, 1, j - 1) .. string.sub(s, k + 1)
          cmt = false
          i = j - 1
        end
      else
        if str then
          if (c == "'") then
            str = str + 1
            if (str % 2 == 0) and (string.sub(s, i + 1, i + 1) ~= "'") then
              k = i
              table.insert(tstr, string.sub(s, j, k))
              s = string.sub(s, 1, j - 1) .. string.sub(s, k + 1)
              str = false
              i = j - 1
            end
          end
        else
          if ((c == "{") and (string.sub(s, i + 1, i + 1) ~= "$"))
          or ((c == "(") and (string.sub(s, i + 1, i + 1) == "*"))
          or ((c == "/") and (string.sub(s, i + 1, i + 1) == "/")) then
            j = i
            cmt = c
          else
            if (c == "'") then
              j = i
              str = 1
            end
          end
        end
      end
      i = i + 1
    end
     
    io.output(filepath(arg[0]) .. "debug.txt")
     
    for i = 1, #tcmt do
      io.write("COMMENT=[" .. tcmt[i] .. "]\n")
    end
    for i = 1, #tstr do
      io.write("STRING=[" .. tstr[i] .. "]\n")
    end
     
    io.output(destination)
    io.write(s)

  9. #9
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 342
    Points : 12 109
    Points
    12 109
    Billets dans le blog
    7

    Par défaut

    Bonjour ! Je vous propose la version finale (façon de parler) de mon script. J'ai inclus deux fichiers BAT qui facilitent l'utilisation.
    Fichiers attachés Fichiers attachés

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Supprimer les commentaires d'un fichier source
    Par Roland Chastain dans le forum Langage
    Réponses: 9
    Dernier message: 21/02/2013, 06h52
  2. Supprimer les commentaires pour Doxygen
    Par Garulfo dans le forum Autres éditeurs
    Réponses: 2
    Dernier message: 20/03/2008, 16h13
  3. Supprimer les commentaires.
    Par castaka dans le forum Outils
    Réponses: 4
    Dernier message: 04/12/2007, 18h42
  4. [Tsx-Pl7 Pro] Methode pour supprimer les Commentaires et les Mnémoniques
    Par franck.automaticien dans le forum Automation
    Réponses: 6
    Dernier message: 22/06/2007, 21h40
  5. Comment supprimer les commentaires d'un document Html?
    Par visteur dans le forum Langage
    Réponses: 2
    Dernier message: 27/03/2006, 12h58

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