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 Perl Discussion :

Parsing de fichiers C


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    130
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Doubs (Franche Comté)

    Informations forums :
    Inscription : Août 2008
    Messages : 130
    Par défaut Parsing de fichiers C
    Salut à tous!

    Je suis débutant en Perl et je dois dévelloper un parser de fichiers d'entête en C:
    Ce parser devra extraire les constantes d'énumérations déclarées dans des fichiers *.h

    exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    typedef enum
    {
       constante1 = valeur1,
       constante2
    }
    Nom_enum;
    Pour le moment, j'arrive à extraire ces noms de constante.
    Mais le but maintenant est de pouvoir extraire le Nom_enum afin de pouvoir trier (car le fichier d'en tête est rempli d'enum et de constantes :p ) puis enfin incrémenter la valeur1.
    Voici mon code (merci à Djibril pour l'aide):

    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
     
    #!/usr/bin/perl
    use warnings;
    use strict;
     
    use Regexp::Common qw /comment/;
    use Perl6::Slurp;
     
    # Englobe le fichier .h
    my $CodeFichierC = slurp "pub_serv.h";
     
    #ouverture du fichier *.txt en mode Ecriture
    open WRITER, '>', "decode2.txt" or die "Le fichier ne peut être édité !\n";
     
    # Suppression des commentaires C
    my $RegexComment = $RE{comment}{'C++'}; #C++ pour supprimer /* */ ET //
    $CodeFichierC =~ s{$RegexComment}{}g;
     
     
     
    # Recupère les define
    my @define = $CodeFichierC =~ m{
      ^\s*            # La ligne commence par un espace ou non
      \#define        # suivi de #define
      \s*             # espace ou non
      ([^\n]+)\s*     # contenu define
      \n              # se termine par un retour chariot
    }mgix;
     
    my %VariableDefine;
     
    foreach my $Define (@define) 
    {
       my ( $var, $value ) = split( /\s+/, $Define );
       $VariableDefine{$var} = $value || '';
    }
     
    print WRITER "Defines: \n\n";
     
    foreach my $var ( keys %VariableDefine ) 
    {
       print WRITER "$var = $VariableDefine{$var}\n";
    }
     
    print WRITER "\n============\n\n";
     
    #  Bloc typedef
    my @typedef = $CodeFichierC =~ m/
       (?:
       enum[^{]+{        # Ligne typedef avec accolade
       ([^;]+)			 # contenu tout sauf accolade fermante
       }				 # accolade fermante                     
       )
       /mgix;
     
    my $CodeTypedef = join( '', @typedef );
    $CodeTypedef =~ s{\n}{}g;
     
    my %Constante = $CodeTypedef =~ m{
       (\w+)\s*    # variable
       =*          # Egual ou non
       \s*(\S+)\s*  # valeur (tout sauf un espace)
       }mxig;
     
    my $valeur_enum;
    my $nom_enum;
     
    foreach my $test($CodeFichierC)
    {
     
    	if($test=~ m/(\s*enum\n{)(.*)(})([\w]+);/)#essais pour choper le nom de l'énum mais ne fonctionne pas
    	{
     
    	   $nom_enum = ($test =~ m/(\s*enum\n{)(.*)(})([\w]+);/);	
    	   print WRITER "\n===\n";
               print WRITER "$4\n";
               print WRITER "\n===\n";
    	}
    }
     
    print WRITER "Constantes definies dans les typedef: \n\n";
    foreach my $var ( keys %Constante ) 
    {
       $Constante{$var} =~ s{,}{}g;
     
       if ( exists $VariableDefine{ $Constante{$var} } ) 
       {
          print WRITER "$var = $VariableDefine{$Constante{$var}} <===($Constante{$var})\n";
     
       }
       else 
       {
          print WRITER "$var =";
          print WRITER $valeur_enum++;
          print WRITER "\n"; 
       }
    }
     
     
    close(WRITER);
    Si quelqu'un à des conseils à me donner, je suis preneur

    Merci d'avance

  2. #2
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 822
    Par défaut
    Donne un exemple de fichier C plus conséquent s'il te plait et correct, pas des blabblabla.

    Avec des defines, contantes, enum bien déclarés, etc etc

    Merci

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    130
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Doubs (Franche Comté)

    Informations forums :
    Inscription : Août 2008
    Messages : 130
    Par défaut
    La forme est correcte:
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    typedef enum
      {
        NO_CARD = 0    ,
        CARD_INSERTED  ,
        CARD_REMOVED   ,
        CARD_DETECTED  ,
        CARD_JAM       ,
        CARD_SCANNED
      }
      CARD_STATUS;

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    #define TOP_CAD_PRIVATE_COMMAND   254
    #define MAX_COMMAND_NUM           255


    Pour les define ca roule

    Le soucis est pour les enums

  4. #4
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 822
    Par défaut
    Bon Ton soucis est que tu n'as pas compris le script que je t'ai fais et tu ne maitrises pas les expressions régulières.

    Bon, je vais te réécrire ton code avec plus de commentaires. Tu prendras le soins de le lire et d'essayer de comprendre tout ce qui est marqué dedans, sinon ça ne t'apportera absolument rien.

  5. #5
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Par défaut
    Je suis pas sûr d'avoir tout pigé dans le source fourni (car les traitements des différents éléments du fichier header s'enchevêtrent, semble-t-il), mais dans ce qui suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #  Bloc typedef
    my @typedef = $CodeFichierC =~ m/
       (?:
       enum[^{]+{        # Ligne typedef avec accolade
       ([^;]+)			 # contenu tout sauf accolade fermante
       }				 # accolade fermante                     
       )
       /mgix;
    J'aurais tendance à dire qu'il serait plus intéressant de construire un hash dont la clé serait le nom de l'enum et la valeur, le contenu de l'enum, et ensuite, parcourir cette table pour extraire la constante et incrémenter les autres valeurs à partir de cette constante.

    Ceci doit être possible grâce à quelque chose comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    my %typedef = ();
    while ($CodeFichierC =~ m/
            (?:
            enum[^{]+{        # Ligne typedef avec accolade
            ([^}]+)           # contenu tout sauf accolade fermante
            }                 # accolade fermante                     
            ([^;]+)           # Nom de l'enum avant le ;
            )
            /mgix); {
      $typedef{$2} = $1;
    }
    Au passage, l'expression régulière initiale contenait une erreur (par rapport au commentaire qu'elle mentionne) : le contenu de l'enum allait jusqu'au ; et non jusqu'à l'accolade fermante comme indiqué dans le commentaire.

  6. #6
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 822
    Par défaut
    C'est absolument ce que je suis en train de lui faire, avec plus de commentaires dans le code.

  7. #7
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Par défaut
    Une autre idée serait peut-être de regarder du coté du CPAN : C::Scan::Constants
    Here's a brief overview of the module:

    * Provides a function, "extract_constants_from()", that extracts a list of information relating to #define constants and "#typedef enum" style constants found in a supplied list of C header (.h) files.
    ...

Discussions similaires

  1. Parsing de fichier XML en C
    Par longbeach dans le forum XML
    Réponses: 12
    Dernier message: 12/12/2006, 16h31
  2. Parsing gros fichier performant ?
    Par jaggy19 dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 09/11/2006, 13h11
  3. parsing de fichier texte
    Par robert_trudel dans le forum Access
    Réponses: 4
    Dernier message: 03/06/2006, 17h45
  4. [DOM] [DocumentBuilder] Problème de parsing de fichier
    Par tck-lt dans le forum Format d'échange (XML, JSON...)
    Réponses: 9
    Dernier message: 13/04/2006, 17h18
  5. Parsing de fichier en C++ : Au secours :(
    Par Triqueur dans le forum C++
    Réponses: 4
    Dernier message: 16/02/2006, 14h49

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