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 :

[C#] Parser code source C avec regex


Sujet :

C#

  1. #1
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut [C#] Parser code source C avec regex
    Bonjour � tous,

    Je souhaiterais parser un code source C classique afin de r�cup�rer les fonctions et le mettre dans un tableau :
    Code c : 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
     
    // Exemple de code source à parser
    void 
    a(int p1, float p2)
    {
     
    }
     
    void b()
    {
        int p1=5;
        float p2 = 10.0;
        a(p1,p2);
    }
     
    int main()
    {
        int p1=5;
        float p2 = 10.0;
        a(p1,p2);
        b();
    }
    Je voudrais isoler chaque bloc de fonction et le mettre en m�moire :
    tab[0] = "void
    a(int p1, float p2)
    {

    }"

    tab[1] = "void b()
    {
    int p1=5;
    float p2 = 10.0;
    a(p1,p2);
    }"

    tab[2] = "int main()
    {
    int p1=5;
    float p2 = 10.0;
    a(p1,p2);
    b();
    }"
    Je ne suis pas du tout dou� avec les regex, je sais utiliser la classe Regex en C# mais pour trouver l'expression r�guli�re c'est autre chose

    Je pense qu'il faut d�finir un pattern du genre :
    (type_retour|void) (espaces|tabulations|saut ligne) nom_fonction (espaces|tabulations|saut ligne) (param�tres) (espaces|tabulations|saut ligne)
    {
    DU TEXTE
    }


    Enfin, je ne suis m�me pas sur. Pouvez vous m'aider ?

    Merci d'avance
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  2. #2
    Membre confirm�

    Homme Profil pro
    Ing�nieur int�gration
    Inscrit en
    Juillet 2009
    Messages
    62
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activit� : Ing�nieur int�gration

    Informations forums :
    Inscription : Juillet 2009
    Messages : 62
    Par d�faut
    Je pense que l'approche via les les expressions r�guli�res ne soit pas la plus adapt�e pour ce type de probl�matique.

    Il faut plut�t voir du cot� des parsers/analyseurs de textes tel que ANTLR

    A voir Tutoriel sur la mise en place d'une grammaire avec ANTLR

  3. #3
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    D�tails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par d�faut
    Pour la regex on peut tenter mais �a ne fonctionnera pas forc�ment. Le probl�me est que sans information de contexte on peut seulement chercher les formes "identifiant + identifiant + parenth�se gauche". Or m�me s'il ne m'en vient pas � l'esprit il y a peut-�tre des ambigu�t�s, notamment du c�t� du pr�processeur (et comment g�rer ce dernier d'ailleurs ?). Et si des infos de contexte sont n�cessaires alors la regex ne peut pas g�rer �a et il faut un parser "� pile" (pense au parsing d'expressions mises entre parenth�ses).

    Autres contraintes: quid du code malform� et des caract�res exotiques? Je doute que le C suive les cat�gories d'unicode, qui ne devait m�me pas exister � l'�poque. Donc les cat�gories regex pourraient ne pas coller.

    Tout d�pend donc des sources � parser et de ce qu'on veut exactement mais la regex peut se r�v�ler insuffisante. Dans ce cas on peut tenter d'�crire un parsing manuel incluant un comptage de parenth�ses (ce qui peut-�tre simple si on ne veut parser qu'une petite partie). Ou bien avoir recours � un parser generator comme sugg�r� par le moussel. Mais outre que cela ajoute une d�pendance au projet, leur utilisation est malheureusement souvent fastidieuse et t'imposera d'apprendre le fonctionnement d'un g�n�rateur de parser. Un comble ! Cela dit c'est une comp�tence utile.


    Si au vu des contraintes que j'ai �num�r�es la regex peut fonctionner alors il suffit de concat�ner comme suit :
    Identifiant: \w[\w\d]*
    Espaces, tab et sauts de ligne: ([\s\n]|(\r\n))*
    Pour le d�but: (\w[\w\d]*|void)

  4. #4
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut
    Bonsoir,

    Effectivement il semble que l'approche regex ne soit pas la bonne.
    Alors j'avais d�j� vu du c�t� de ANTLR mais il faudrait des semaines pour comprendre comment ca marche et cela rajoute une d�pendance au projet.

    Au final m�me si le style de code � parser reste simple (on part du principe que le code est correct syntaxiquement et avec une imbrication { et } parfaite), je ne vois pas comment r�gler le probl�me des accolades � l'int�rieur d'une fonction.

    Exemple :
    Code c : 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
    void b()
    {
        int p1=5;
        float p2 = 10.0;
        a(p1,p2);
        if ( blabla) {
    
        }
        else {
            while (blabla)
            {
    
            }
        }
    } // <--- il faudrait s'arr�ter � cette accolade d�s qu'on a match� le prototype de la fonction...
    
    float autre_fonction() {}
    Impossible de dire avec une regex, je dois m'arr�te � la "bonne" accolade (celle qui ferme la fonction)

    Ou alors j'ai loup� quelque chose...

    Merci � vous
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  5. #5
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    D�tails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par d�faut
    Effectivement une regex ne peut traiter des structures r�cursives (tu peux bidouiller si la profondeur max de la r�cursion est connue et faible). J'avais zapp� le fait que tu voulais �galement capturer le corps. Tu pourrais toujours bidouiller en utilisant la regex pour capturer l'en-t�te puis utiliser une proc�dure manuelle pour trouver l'accolade de fin. Resteraient quand m�me le probl�me du pr�processeur et celui des cha�nes de caract�res qui pourraient contenir des accolades ou des motifs �quivalents � des en-t�tes de fonction.

    Bref, la regex est limit�e mais avec un peu de bricolage et des sources simples �a peut marcher. Une solution manuelle sera un peu plus puissante mais � nouveau elle �chouera face � certains cas particuliers, sauf � y passer beaucoup de temps pour cr�er un parser complet. Quant � antlr �a ne prend pas des semaines et �a reste la fa�on la plus rapide d'avoir un parser 100% compatible.

    Tout d�pend des sources. Si tu peux bricoler, bricole.

  6. #6
    Expert confirm�
    Avatar de Mat.M
    Profil pro
    D�veloppeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 539
    D�tails du profil
    Informations personnelles :
    Localisation : France, Rh�ne (Rh�ne Alpes)

    Informations professionnelles :
    Activit� : D�veloppeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 539
    Par d�faut
    Citation Envoy� par Aspic Voir le message
    Je souhaiterais parser un code source C classique afin de r�cup�rer les fonctions et le mettre dans un tableau :
    je te souhaite un bon courage c'est assez ardu � faire...
    j'avais commenc� � faire un interpr�teur de langage genre Javascript,langage C pour mon projet ( que je souhaite commercialiser..) mais un jour j'ai vite chang� pour faire un interpr�teur BASIC.

    Ceci dit si je peux essayer de donner des tuyaux je peux
    Je n'utilise pas du tout les expressions r�guli�res.
    J'analyse caract�re par caract�re pour voir si c'est un espace, un chiffre...
    Ensuite l� o� je me suis arrach� les cheveux de la t�te c'est pour d�limiter les blocs avec les accolades.
    En Basic c'est plus facile �tant donn� que �a finit avec End Sub ou End Function
    Maintenant si on souhaite d�limiter les blocs il faut empiler les blocs � l'aide d'une pile ; les blocs de fonctions et d'expressions d�limit�s par des accolades doivent �tre symm�triques �videmment.
    Une pile permet de restituer le dernier �l�ment empil�.


    Citation Envoy� par Aspic Voir le message
    Au final m�me si le style de code � parser reste simple (on part du principe que le code est correct syntaxiquement et avec une imbrication { et } parfaite), je ne vois pas comment r�gler le probl�me des accolades � l'int�rieur d'une fonction.

    s
    pour analyser et d�limiter les blocs on peut aussi �ventuellement utiliser un arbre binaire; chaque noeud de l'arbre est en fait un bloc du source : par exemple pour une condition if , pour une boucle etc...

    ce que j'ai fait dans mon projet d'interpr�teur c'est que le code source initialement en Javascript ( syntaxe proche du C donc ) est compil� dans un pseudo-code ( un peu comme l'Intermediate Language de .NET) et comme �a il est interpr�t� lin�airement par le module d'ex�cution.

  7. #7
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut
    Citation Envoy� par DonQuiche Voir le message
    Resteraient quand m�me le probl�me du pr�processeur et celui des cha�nes de caract�res qui pourraient contenir des accolades ou des motifs �quivalents � des en-t�tes de fonction.
    Pour le pr�processeur, � tout hasard ca ne serait pas possible de r�cup�rer un code interm�diaire o� les #define sont remplac�s juste avant la compilation ? (je pense � une option de gcc qui permettrait de sortir un fichier en code C mais avec une passe du pr�processeur ?)

    Pour les accolades dans une chaine de caract�res, j'ai avait pens� on ne peut pas les virer avec une regex ? Voire m�me virer tout le texte dans les guillemets ? Exemple : printf("je fais foirer le parser { ahahahah"); devient printf(""); ou alors printf();
    Citation Envoy� par DonQuiche Voir le message
    Quant � antlr �a ne prend pas des semaines et �a reste la fa�on la plus rapide d'avoir un parser 100% compatible.
    Un jour, j'apprendrais ce nouvel outil, ca � vraiment l'air pas mal mais au premier abord (en regardant le tuto sur DVP), cela avait l'air compliqu�...
    Pour l'instant �tant donn� que les sources sont simples, je continue en mode bricolage m�me si c'est pas bien � termes j'en suis conscient

    Citation Envoy� par Mat.M
    Ensuite l� o� je me suis arrach� les cheveux de la t�te c'est pour d�limiter les blocs avec les accolades.
    Tu m'�tonnes, je suis entrain de p�ter un c�ble dessus actuellement
    C'est clair que du VB.net aurait �t� plus simple
    Citation Envoy� par Mat.M
    Maintenant si on souhaite d�limiter les blocs il faut empiler les blocs � l'aide d'une pile ; les blocs de fonctions et d'expressions d�limit�s par des accolades doivent �tre symm�triques �videmment.
    Une pile permet de restituer le dernier �l�ment empil�.
    Alors une pile, j'avais eu l'id�e mais je n'ai pas trouv� comment faire au final. D�s que je trouve une accolade ouvrante, j'empile le code lu pr�c�demment (de la pr�c�dente accolade ouvrante jusqu'� celle que je viens de trouver) et que je trouve une accolade fermante, je d�pile le dernier �l�ment mais au final comment reconstituer les blocs ?
    Avec un arbre binaire, je ne vois simplement pas comment on pourrait faire.
    Citation Envoy� par Mat.M
    ce que j'ai fait dans mon projet d'interpr�teur c'est que le code source initialement en Javascript ( syntaxe proche du C donc ) est compil� dans un pseudo-code ( un peu comme l'Intermediate Language de .NET) et comme �a il est interpr�t� lin�airement par le module d'ex�cution.
    C'est toi qui a cr�� le pseudo-code ? Si oui, comment as tu fait ? Et je suppose que parser le pseudo-code �tait plus facile que le code source d'origine ?

    PS : Au final, ton projet a �t� termin� � 100% ?

    Merci beaucoup.
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  8. #8
    Expert confirm�
    Avatar de Mat.M
    Profil pro
    D�veloppeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 539
    D�tails du profil
    Informations personnelles :
    Localisation : France, Rh�ne (Rh�ne Alpes)

    Informations professionnelles :
    Activit� : D�veloppeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 539
    Par d�faut
    salut,

    *pour l'arbre binaire : le main() du programme constitue la t�te de l'arbre
    Ensuite � l'analyse du code source,
    si on rencontre un "if" un "for" ou la d�claration d'une fonction , on cr�er un nouveau noeud qu'on ajoute � l'arbre.
    Soit au noeud principal soit � noeud sous-jacent qui peut-�tre une instruction ou une fonction.
    Puisqu'un if peut encapsuler plusieurs autres if , for etc
    Il faut s'assurer que le nom de fonction ne soit pas d�j� d�clar� ; dans ce cas-l� on parcourir de mani�re r�cursive l'arbre.

    *pour mon projet perso,c'est moi qui ait cr�e totalement la syntaxe du pseudo-code en m'inspirant un peu de la syntaxe assembleur x86.
    C'est parfaitement fonctionnel ; l'utilisateur peut cr�er des formulaires, d�clarer des variables, des noms de proc�dure, faire des boucles et des conditions.

    Pour la finalisation de mon projet ce n'est pas un langage informatique que je veux faire c'est une sorte d'Atelier Logiciel qui pilote des bases de donn�es et je suis en train de le finaliser

  9. #9
    Expert confirm�
    Avatar de Mat.M
    Profil pro
    D�veloppeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 539
    D�tails du profil
    Informations personnelles :
    Localisation : France, Rh�ne (Rh�ne Alpes)

    Informations professionnelles :
    Activit� : D�veloppeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 539
    Par d�faut
    Citation Envoy� par Aspic Voir le message

    Pour les accolades dans une chaine de caract�res, j'ai avait pens� on ne peut pas les virer avec une regex ? Voire m�me virer tout le texte dans les guillemets ? Exemple : printf("je fais foirer le parser { ahahahah"); devient printf(""); ou alors printf();
    si tu cr�es ton propre analyseur lexical/syntaxique et si tu rencontres une cha�ne de caract�res dans le code source , il suffit de mettre un bool�en � true qui indique qu'on a rencontr� une chaine de caract�res.

    Ce que j'ai fait au niveau de l'analyse du code source :
    si le code source est le suivant
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
     
    int i; 
    int j;
    for(i=0;i<100;i++)
    {
     
    }
    l'analyseur syntaxique prend caract�re par caract�re, enl�ve les espaces, tous les caract�res ind�sirables
    les mots sont ajout�s � une collection genre ArrayList ou tout ce que tu veux ce qui au final va donner une collection de cha�nes de caract�res
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
     
    ArrayList instructions=new ArrayList;
    //....
    string strInstruction;
    For( i=0;i<instructions.length()-1;i++)
    { strInstruction =instructions[i];
    // strInstruction vaudra "int" "j" ";""for" etc..
    C'est peut-�tre plus lourd qu'avec des expressions r�guli�res mais �a fonctionne
    Ensuite de cette liste de mots/instructions on regarde si on trouve des mots r�serv�s comme "if" ou "for" etc sinon on construit une table de symboles comme les variables, les proc�dures
    C'est assez basique il y a certainement plus subtil mais �a fonctionne

  10. #10
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    D�tails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par d�faut
    Citation Envoy� par Aspic Voir le message
    Pour le pr�processeur, � tout hasard ca ne serait pas possible de r�cup�rer un code interm�diaire o� les #define sont remplac�s juste avant la compilation ? (je pense � une option de gcc qui permettrait de sortir un fichier en code C mais avec une passe du pr�processeur ?)
    SI c'est le cas, c'est vraiment cool.

    Pour les accolades dans une chaine de caract�res, j'ai avait pens� on ne peut pas les virer avec une regex ? Voire m�me virer tout le texte dans les guillemets ? Exemple : printf("je fais foirer le parser { ahahahah"); devient printf(""); ou alors printf();
    Si tu fais �a tu vas perdre tes cha�nes dans les blocs captur�s et les indices des captures seront erron�s. Du coup il va te falloir une grosse plomberie pour corriger ces informations a posterior.

    Non, si tu restes sur les regex, le mieux � faire � mon avis est d'avoir une simple passe manuelle capable d'identifier les cha�nes et les paires d'accolades. Avec ces infos tu devras cr�er deux fonctions: bool IsInString(int index) et int GetMatchingEndBrace(int index). Ainsi apr�s chaque capture de la regex tu v�rifies qu'elle n'�tait pas dans une cha�ne et tu cherches l'accolade fermante.


    Un jour, j'apprendrais ce nouvel outil, ca � vraiment l'air pas mal mais au premier abord (en regardant le tuto sur DVP), cela avait l'air compliqu�...
    Pas tant que �a en fait, �a s'apprend plut�t bien. Qui plus est c'est ce qu'on appelle un parser LL et c'est beaucoup plus facile � utiliser que les LR avec leurs messages d'erreurs incompr�hensibles (une techno qui devrait � mon avis tomber dans l'oubli). Cela dit, encore une fois, si tu peux t'en passer, fais-le.

    Alors une pile, j'avais eu l'id�e
    Oublie cette approche, il ne faut pas chercher � �crire un vrai parser, ou alors autant se mettre � Antlr. Si tu pars sur une approche manuelle tu dois simplement mettre au point une m�thode capable de trouver la prochaine virgule ou l'accolade correspondante tout en ignorant les cha�nes. Tu n'as pas besoin d'un v�ritable parser capable de reconna�tre les expressions.

  11. #11
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    �tudiant
    Inscrit en
    Ao�t 2005
    Messages
    3 905
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (�le de France)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : Ao�t 2005
    Messages : 3 905
    Par d�faut
    Merci � vous pour vos remarques

    Je suis parti sur une approche plut�t manuelle, je pense que cela suffira dans mon cas, mais je garde � l'id�e l'utilisation d'arbres binaires ou piles si j'en ai besoin � un moment donn�.

    Si je rencontre des probl�mes pr�cis, je continuerai � poster sur ce topic pour ne pas spoiler le forum ^^

    Bonnes f�tes de fin d'ann�e

    PS : Puis-je commercialiser un produit utilisant des outils externes sous licence GNU GPLv2/3 ?
    http://www.developpez.net/forums/d14...ercialisation/
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. Code source projet avec CORBA
    Par mourad1987 dans le forum CORBA
    R�ponses: 1
    Dernier message: 30/04/2012, 13h13
  2. R�ponses: 0
    Dernier message: 07/10/2011, 14h17
  3. parser code source jave pour obtenir un AST
    Par cdm1024 dans le forum G�n�ral Java
    R�ponses: 1
    Dernier message: 10/08/2009, 09h19
  4. R�ponses: 6
    Dernier message: 19/07/2007, 12h30

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