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

C++ Discussion :

Expression rationnelle: détecter les commentaires multilignes dans un fichier c++


Sujet :

C++

  1. #1
    Membre habitué Avatar de Rodrigue
    Inscrit en
    Août 2002
    Messages
    487
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 487
    Points : 157
    Points
    157
    Par défaut Expression rationnelle: détecter les commentaires multilignes dans un fichier c++
    Bonjour,

    Je souhaiterais détecter les commentaires multilignes (/* ... */) contenus dans des fichiers C++: .h, .cpp.

    Pour ce faire, j'utilise boost::regex. J'ai déjà trouvé une expression rationnelle (ou régulière comme vous souhaitez ) qui détecte les commentaires contenus sur une seule ligne.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "/\\*([[:punct:]]|[[:alnum:]]|[[:blank:]])*\\*/"
    Mais pas moyen de lui faire reconnaître les multilignes, j'ai bien essayé de remplacer [:blank:] par [:space:], voir même :
    mais le problème c'est qu'il ne s'arrête pas au premier */ mais au dernier.

    Voici l'exemple simple sur lequel je travaille:
    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
    /* Check to see if a file is a PNG file using png_sig_cmp().  png_sig_cmp()
     * returns zero if the image is a PNG and nonzero if it isn't a PNG.
     *
     * The function check_if_png() shown here, but not used, returns nonzero (true)
     * if the file can be opened and is a PNG, 0 (false) otherwise.
     *
     * ...
     */
    #define PNG_BYTES_TO_CHECK 4
    int check_if_png(char *file_name, FILE **fp)
    {
       char buf[PNG_BYTES_TO_CHECK];
     
       /* Open the prospective PNG file. */
       if ((*fp = fopen(file_name, "rb")) == NULL)
          return 0;
     
       /* Read in some of the signature bytes */
       if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK)
          return 0;
     
       /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
          Return nonzero (true) if they match */
     
       return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK));
    }
    Le résultat est donc:
    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
    /* Check to see if a file is a PNG file using png_sig_cmp().  png_sig_cmp()
     * returns zero if the image is a PNG and nonzero if it isn't a PNG.
     *
     * The function check_if_png() shown here, but not used, returns nonzero (true)
     * if the file can be opened and is a PNG, 0 (false) otherwise.
     *
     * ...
     */
    #define PNG_BYTES_TO_CHECK 4
    int check_if_png(char *file_name, FILE **fp)
    {
       char buf[PNG_BYTES_TO_CHECK];
     
       /* Open the prospective PNG file. */
       if ((*fp = fopen(file_name, "rb")) == NULL)
          return 0;
     
       /* Read in some of the signature bytes */
       if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK)
          return 0;
     
       /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
          Return nonzero (true) if they match */
    J'utilise comme option de recherche:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    boost::match_flag_type flags = boost::match_default;
     
       while(boost::regex_search(start, end, what, expression, flags))
    Merci pour votre aide!
    Rodrigue

  2. #2
    screetch
    Invité(e)
    Par défaut
    le regexp matche la plus grande occurrence de ton expression

    or

    a deux patterns qui "matchent" la regexp :

    et donc il prend la plus longue occurrence!

    je ne sais pas si il y a un moyen de dire a boost de ne pas poursuivre la recherche lorsqu'une serie match le pattern (quel langage barbare desole) mais sinon il faut que tu reconnaisses le pattern qui commence par /*, ne contient pas */ et se termine par */. c'est chiant car */ tient sur deux caracteres, c'est donc plus difficile a reconnaitre

  3. #3
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Salut,

    Essaye par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "/\\*(~[\\*])*\\*(~[\\*/](~[\\*])*\\*|\\*)*/"
    Source : The JavaCC FAQ, la note 4.
    J'ai transcrit en regex standard dans une chaîne C viteuf donc c'est peut-être pas exactement ça, en tous cas c'est beaucoup plus compliqué que ce que tu proposes pour obtenir une expression correcte.

    MAT.

  4. #4
    Membre habitué Avatar de Rodrigue
    Inscrit en
    Août 2002
    Messages
    487
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 487
    Points : 157
    Points
    157
    Par défaut
    Merci pour le lien
    J'ai essayé et ça ne fonctionne pas
    JAVACC:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "/*" (~["*"])* "*" (~["*","/"] (~["*"])* "*" | "*")* "/"
    Si je traduis (je pense que ~ est l'opérateur d'exclusion ^
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "/\\*(^[*])*\*(^[*/](^[*])*\*|\*)*/"
    Rodrigue

  5. #5
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Les * dans doivent être échappés par \\ en tous cas.
    Après peut-être que ^\\* suffit et qu'il n'y a pas besoin de ^[\\*], je ne sais plus

    MAT.

  6. #6
    Membre habitué Avatar de Rodrigue
    Inscrit en
    Août 2002
    Messages
    487
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 487
    Points : 157
    Points
    157
    Par défaut
    J'ai trouvé !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "/\\*([^*]|(\\*+([^*/])))*\\*+/"
    Cette expression prend n'importe quel type de commentaire

    Maintenant le problème, ce sont les commentaires //.
    J'ai encore le même problème quand je fais:
    Ce n'est pas logique comme écriture...
    Rodrigue

  7. #7
    Membre habitué Avatar de Rodrigue
    Inscrit en
    Août 2002
    Messages
    487
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 487
    Points : 157
    Points
    157
    Par défaut
    Pourquoi faut-il que je tape:
    plutôt que:
    On dirait que le $ n'est pas bien interprété (comme s'il s'agissait de la fin du texte, plutôt que de la fin de la ligne)
    Rodrigue

  8. #8
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Il me semblait que justement l'appariement de parenthèses (ce qui est le cas ici) était un problème non soluble par des regex. Me suis-je trompé ?
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  9. #9
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    Juin 2004
    Messages
    68
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2004
    Messages : 68
    Points : 86
    Points
    86
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Il me semblait que justement l'appariement de parenthèses (ce qui est le cas ici) était un problème non soluble par des regex. Me suis-je trompé ?
    Non tu ne te trompes pas mais ici ce n'est pas un probleme d'appariement de parenthèses. Le but ici n'est pas d'avoir autant de parenthèses ouvrantes que fermantes mais une parenthèse ouvrante puis n'importe quoi, y compris des parenthèses ouvrantes, et une parenthèse fermante.

    En fait le probleme de l'appariement de parenthèses c'est le langage a^nb^n et celui des commentaires multilignes du C++ est a+b. Et ce dernier langage on sait le matcher avec une Regex!

    ^n signifiant puissance n en therme de langage donc a^n => n fois a
    a+ signifiant ici au moins une fois a

  10. #10
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Effectivement, les commentaires en C++ ne s'imbriquent pas. Donc pas de problèmes.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  11. #11
    Membre habitué Avatar de Rodrigue
    Inscrit en
    Août 2002
    Messages
    487
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 487
    Points : 157
    Points
    157
    Par défaut
    Citation Envoyé par capitN.flam Voir le message
    Non tu ne te trompes pas mais ici ce n'est pas un probleme d'appariement de parenthèses. Le but ici n'est pas d'avoir autant de parenthèses ouvrantes que fermantes mais une parenthèse ouvrante puis n'importe quoi, y compris des parenthèses ouvrantes, et une parenthèse fermante.

    En fait le probleme de l'appariement de parenthèses c'est le langage a^nb^n et celui des commentaires multilignes du C++ est a+b. Et ce dernier langage on sait le matcher avec une Regex!

    ^n signifiant puissance n en therme de langage donc a^n => n fois a
    a+ signifiant ici au moins une fois a

    Si le problème d'appariement des parenthèses (ou des accolades) ne peut être solutionné avec les regex, comment faut-il s'y prendre? Faut-il se déplacer de proche en proche, avec un compteur, pour déterminer la dernière parenthèse/accolade? Ou existe-t-il un moyen plus simple?
    Rodrigue

  12. #12
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    Juin 2004
    Messages
    68
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2004
    Messages : 68
    Points : 86
    Points
    86
    Par défaut
    Citation Envoyé par Rodrigue Voir le message
    Si le problème d'appariement des parenthèses (ou des accolades) ne peut être solutionné avec les regex, comment faut-il s'y prendre? Faut-il se déplacer de proche en proche, avec un compteur, pour déterminer la dernière parenthèse/accolade? Ou existe-t-il un moyen plus simple?
    Pour savoir si quelque chose est bien parenthésé le moyen le plus simple est effectivement d'utilisé un compteur initialisé à 0:
    • à chaque fois que l'on rencontre une parenthèse ouvrante on ajoute 1
    • à chaque fois que l'on rencontre une parenthèse fermante on soustrait 1
    • si au cours du parcours compteur < 0 alors c'est mal parenthésé
    • à la fin si:
      • compteur < 0 alors plus de parenthèse fermante que d'ouvrante
      • compteur > 0 alors plus de parenthèse ouvrante que de fermante
      • compteur = 0 alors c'est bien parenthésé

  13. #13
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Il doit y avoir un contruct qui dit le moins possible de caractères. En perl, c'est avec un '?', avec boost je ne sais plus.

    Sinon ... pourquoi faire ?
    Un streambuf filtrant ne conviendrait-il pas mieux ?
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  14. #14
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Pour matcher /* n'importe quoi */ il suffit de faire /\*.*?/\*
    Boost ftw

  15. #15
    Membre habitué Avatar de Rodrigue
    Inscrit en
    Août 2002
    Messages
    487
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 487
    Points : 157
    Points
    157
    Par défaut
    Désolé, mon alim (Antec, oui je milite contre cette marque désormais) a claqué, emportant dans la foulée mon processeur... J'ai donc changé complètement de config . Excusez-moi donc de ne pas avoir pu répondre plus tôt...

    Citation Envoyé par Luc Hermitte Voir le message
    Il doit y avoir un contruct qui dit le moins possible de caractères. En perl, c'est avec un '?', avec boost je ne sais plus.

    Sinon ... pourquoi faire ?
    Un streambuf filtrant ne conviendrait-il pas mieux ?
    Je ne sais pas ce qu'il en est à propos de streambuf... Pourrais-tu m'en dire plus, stp?
    Rodrigue

  16. #16
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Tu t'en sors bien. Toi, ce n'est pas ton disque qui a laché.

    Sinon, regarde :
    - la FAQ de fclc++
    - les deux articles de James Kanze avec "filtering streambuf" dedans
    - boost.iostream qui a repris l'idée.

    A quoi cele servirait ici ?
    A lire un flux comme si tous les caractères de commentaires n'avaient jamais existés. Ce qui facilite l'analyse de code. Sauf si tu veux aussi extraire les commentaires pour les traiter.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  17. #17
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 107
    Points : 122
    Points
    122
    Par défaut
    cf flex, c'est fait pour çà.

  18. #18
    Membre habitué Avatar de Rodrigue
    Inscrit en
    Août 2002
    Messages
    487
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 487
    Points : 157
    Points
    157
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    Tu t'en sors bien. Toi, ce n'est pas ton disque qui a laché.
    Oups ! Désolé pour toi... J'ai déjà failli avoir la même chose. Heureusement, j'avais tout sauvegardé deux jours avant!!! Ce n'était même pas dû au disque dur mais à la carte mère (le contrôleur disque faisait n'importe quoi et m'a claqué deux disques durs de suite ).

    Citation Envoyé par Lemel
    cf flex, c'est fait pour çà.
    J'ai déjà essayé avec Flex/Bison: j'ai porté sous visual studio "CTree parser" de Shaun Flisakowski mais bon les résultats n'étaient pas géniaux. Peut-être que je n'ai pas regardé aux bons endroits!
    Que me conseilles-tu de faire?
    Rodrigue

  19. #19
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    La macro-syntaxe de C++ n'est pas LALR, ça ne se parse donc pas avec (f)lex.
    Boost ftw

  20. #20
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 107
    Points : 122
    Points
    122
    Par défaut
    La macro-syntaxe de C++ n'est pas LALR, ça ne se parse donc pas avec (f)lex.
    Tu peux développer ? Tu ne parles pas plutôt de bison ? Car flex c'est juste un "matcher" d'expression régulières c'est tout.
    J'ai déjà essayé avec Flex/Bison: j'ai porté sous visual studio "CTree parser" de Shaun Flisakowski mais bon les résultats n'étaient pas géniaux. Peut-être que je n'ai pas regardé aux bons endroits!
    Que me conseilles-tu de faire?
    je te conseille de d'abord utiliser flex style C (afin de faire fonctionner et vite le bousin). Cela fait un moment que j'en ai pas fait, mais j'ai du l'utiliser pour parser du html donc c'est largement possible :-) (car avec toutes les exceptions à la règle que connais ce langage à cause des WebDevelopper cela me semble plus compliqué que du bête C++ bien normalisé).
    Tu devrais t'en sortir en quelques lignes de codes grand max (5-10 lignes je dirais).


    http://www.gnu.org/software/flex/man...r/flex_19.html (explique la génération de code pour flex).

Discussions similaires

  1. Comment sont sélectionnés les commentaires apparaissant dans les actus (hors du forum) ?
    Par goomazio dans le forum Mode d'emploi & aide aux nouveaux
    Réponses: 2
    Dernier message: 24/01/2013, 21h43
  2. détecter les lignes parallèles dans une image
    Par clynda dans le forum ImageJ
    Réponses: 4
    Dernier message: 17/06/2010, 01h28
  3. Détecter les modifications faites dans une zone de texte avec la souris
    Par nosferapti dans le forum Général JavaScript
    Réponses: 11
    Dernier message: 24/09/2009, 09h48
  4. [Free Pascal] Détecter les lignes identiques dans deux tableaux de texte
    Par jeanmich dans le forum Free Pascal
    Réponses: 11
    Dernier message: 10/01/2009, 15h43
  5. Réponses: 5
    Dernier message: 16/03/2005, 22h17

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