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

Générateurs de compilateur Discussion :

Problème parser flex stockage de données


Sujet :

Générateurs de compilateur

  1. #1
    Candidat au Club
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Février 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2017
    Messages : 3
    Points : 2
    Points
    2
    Par défaut Problème parser flex stockage de données
    Bonjour,

    Je viens vers vous car je débute avec flex et j'aurais bien besoin de conseils pour me débloquer

    Je cherche à créer un parser avec flex qui va récupérer les noms de fonctions dans un header afin de les réutiliser plus tard. Je désire stocker ces noms de fonctions dans un tableau que j'alloue dynamiquement car je souhaite pouvoir parser n'importe quel header avec (donc n'importe quel nombre de fonctions). Voilà en gros l'objectif de mon code

    Dans les règles de production flex afin d'identifier les mots j'ai indiqué :

    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
    [a - zA - Z0 - 9] +
    {
      if (yyin == hfile)
        {
          if (strcmp (yytext, "extern") == 0)
    	{
    	  fctON = 1;
    	  cptWords = 0;
    	}
          else if (fctON == 1)
    	{
    	  allocationfonctions (yytext);
    	}
          else
    	{
    	  printf ("%s\n", yytext);
    	}
        }
      else if (yyin == cfile)
        {
          if (comON == 1)
    	{
    	  comment = yytext;
    	}
          else
    	{
    	  ECHO;
    	}
        }
    }
    qui lorsque je suis en train de parser le header hfile va identifier "extern" et faire appel à la fonction allocationsfonctions ci dessous pour les mots suivants jusqu'à rencontrer le caractère '(' qui repassera fctON à 0 (code non indiqué ici).

    La fonction allocationfonctions :

    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
    int
    allocationfonctions (char *data)
    {
      int i = 0;
      char *word = strcat (data, "");
      printf ("mot a stocker : %s\n", word);
      if (cptWords == 0)
        {
          if (n >= 5)
    	{
    	  fonctions = realloc (fonctions, (n + 2) * sizeof (chaine));
    	  if (fonctions == NULL)
    	    {
    	      printf ("erreur lors de la reallocation\n");
    	      return -1;
    	    }
    	  fonctions[n] = "fctname";
    	  fonctions[n + 1] = "fctname";
    	}
     
          fonctions[n + 1] = word;
     
          printf ("result : fonctions[%d]=%s\n", n + 1, fonctions[n + 1]);
          cptWords++;
          n += 2;
          return 1;
        }
      else
        {
          if (n >= 5)
    	{
    	  fonctions = realloc (fonctions, (n + 1) * sizeof (chaine));
    	  if (fonctions == NULL)
    	    {
    	      printf ("erreur lors de la reallocation\n");
    	      return -1;
    	    }
    	  fonctions[n] = "fctname";
    	}
     
          fonctions[n] = word;
     
          printf ("result : fonctions[%d]=%s\n", n, fonctions[n]);
          cptWords++;
          n += 1;
          return 1;
        }
    }
    Le passage par un paramètre word avec strcat était une tentative d'éviter le problème que je pointe plus bas avec l'ajout d'un caractère nul, mais ça n'a rien changé

    Et voici le main qui initialise tout ça :

    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
    int
    main (void)
    {
     
      int i;
      hfile = fopen ("HelloWorld.h", "r");
     
      if (!hfile)
        {
          printf ("I don't know where to read\n");
          return -1;
        }
     
      cfile = fopen ("HelloWorld.c", "r");
     
      if (!cfile)
        {
          printf ("I don't know where to read\n");
          return -1;
        }
     
      thatfile = fopen ("result.c", "w");
     
      if (!thatfile)
        {
          printf ("I don't know where to write\n");
          return -1;
        }
     
      chaine = malloc (8 * sizeof (char));
      if (chaine == NULL)
        {
          printf ("erreur de memoire - ligne\n");
          return 0;
        }
      fonctions = malloc (5 * sizeof (chaine));
      if (fonctions == NULL)
        {
          printf ("erreur de memoire - tableau\n");
          return 0;
        }
      for (i = 0; i < 5; i++)
        {
          fonctions[i] = "fctname";
          printf ("valeur defaut fonction[%d]:%s\n", i, fonctions[i]);
        }
     
      yyin = hfile;
      yylex ();
      printf ("end of first parsing\n\n\n");
     
      for (i = 0; i < n; i++)
        {
          printf ("fonction[%d]:%s\n", i, fonctions[i]);
        }
     
      printf ("start of second parsing\n\n");
      yyin = cfile;
      yyout = thatfile;
      yylex ();
     
      for (i = 0; i < n; i++)
        {
          printf ("fonction[%d]:%s\n", i, fonctions[i]);
        }
     
      free (fonctions);
      fclose (hfile);
      fclose (cfile);
      fclose (thatfile);
      return 0;
    }
    Avec ce code je souhaite avoir au final par exemple :

    fonctions[0]:fctname

    fonctions[1]:int fonctions[2]:main fonctions[3]:fctname

    fonction[4]:int fonctions[5]:calc fonction[6]:fctname etc...

    avec le HelloWorld.h suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #ifndef HELLOWORLD_FLEX
    #define HELLOWORLD_FLEX
     
    extern int main ();
    extern int calc (int nombre);
    extern float testerpresent ();
     
     
    #endif
    Or lorsque j'exécute mon code après compilation (l'instruction flex ne retourne pas de warning, gcc affiche des warning car je passe des char* dans les printf où il attends des string) j'ai le résultat suivant:

    valeur defaut fonction[0]:fctname
    valeur defaut fonction[1]:fctname
    valeur defaut fonction[2]:fctname
    valeur defaut fonction[3]:fctname
    valeur defaut fonction[4]:fctname
    ifndef
    HELLOWORLD
    FLEX
    define
    HELLOWORLD
    FLEX
    mot a stocker : int
    result : fonctions[1]=int
    mot a stocker : main
    result : fonctions[2]=main
    mot a stocker : int
    result : fonctions[4]=int
    mot a stocker : calc
    result : fonctions[5]=calc
    int
    nombre
    mot a stocker : float
    result : fonctions[7]=float
    mot a stocker : testerpresent
    result : fonctions[8]=testerpresent
    endif
    end of first parsing
    Jusqu'ici tout va bien vous me direz, les ré allocations fonctionnent et tout, oui en effet c'est ce que je croyais... mais lorsque je redemande d'afficher le contenu du tableau une fois le parsing du fichier fini c'est la douche froide :

    fonction[0]:fctname
    fonction[1]:int main();
    extern int calc(int nombre);
    extern float testerpresent();


    #endif

    fonction[2]:main();
    extern int calc(int nombre);
    extern float testerpresent();


    #endif

    fonction[3]:fctname
    fonction[4]:int calc(int nombre);
    extern float testerpresent();


    #endif

    fonction[5]:calc(int nombre);
    extern float testerpresent();


    #endif

    fonction[6]:fctname
    fonction[7]:float testerpresent();


    #endif

    fonction[8]:testerpresent();


    #endif
    Que s'est il passé durant le parsing ? le seul endroit où j’écris dans le tableau fonctions[] est la fonction allocationfonctions, appelée dans un cas assez précis J'ai l'impression que le parser a stocké dans yytext tous les caractères entre 2 appels de la fonction et les a remis dans tout le tableau (sauf les zones mémoire avec fctname). Or je croyais que ce paramètre ne contenait que le caractère courant ?

    Si quelqu'un connait bien flex (ou voit une erreur dans mon code C, ce qui est possible aussi) j'aimerais comprendre ce qui s'est passé pour le corriger.

    Je vous remercie d'avance pour vos réponses, toute suggestion est la bienvenue !

    PS : ceci est mon premier post, si jamais je ne suis pas assez précis ou s'il vous faut plus de code n'hésitez pas à me le dire. J'ai essayé de fournir tout le nécessaire mais j'ai peut-être un peu la tête dans mon programme...

  2. #2
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Je n'ai pas regardé le code encore énormément mais le plus grand souci est que tu es en train d'utiliser flex tout seul mais tu veux faire une analyse sémantique en même temps. Et c'est sûrement parce que tu ne veux pas gérer toute la grammaire du langage mais en principe tu dois le définir correctement pour obtenir ce que tu veux vraiment bien.

    Sinon tu vas passer un temps fou à tenter de corriger ce code pour transformer flex en un analyseur lexical avec intelligence. C'est généralement voué à l'échec quand tu passeras des fichiers plus complexes...

  3. #3
    Candidat au Club
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Février 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2017
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Merci pour ta réponse.

    Mon objectif est à la fin d'ajouter automatiquement un squelette de commentaire au dessus de chaque début de fonction de mon fichier source (que je parse directement à la suite du header dans mon fichier flex). Je me disais donc que basiquement je pouvais dans mon source, suite à une détection de \n, comparer les mots identifiés en début de ligne avec ceux que j'aurais stocké entre "extern" et "(" dans le header.

    L'utilisation de l'analyse sémantique me semblait une approche un peu lourde pour ce que je souhaite faire par rapport à l'ajout d'une fonction en C dans l'analyse lexicale. Sachant que je redéfinirais mes fonctions dans le fichier bison sans à priori les changer beaucoup, je ne sais pas si cela résoudra mon problème.. Avec ce que j'ai dit plus haut est ce que tu penses qu'une analyse de toute la grammaire me soit nécessaire ?
    Comme je débute j'ai peut-être fait une erreur de jugement

    en combinant avec bison j'aurais du coup des règles du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Expr    :  Expr
    		{ ne rien faire }
    	| "extern " Expr Expr "("
                    {stocker Expr Expr}
    ;
    c'est ça ? Avec par la suite la gestion de plus ou moins de Expr si par exemple la fonction est déclarée en static et la gestion du parsing des deux fichiers depuis bison au lieu de flex

  4. #4
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Ok pourquoi pas . Je ne dis pas que tu ne peux pas le faire. Peut-être est-ce plus rapide?

    J'avais fait un truc similaire à une époque et j'avais trouvé que lire ligne par ligne et traiter la ligne directement était plus facile qu'utiliser flex comme entrée.

    Si j'avais lu ce message correctement, j'aurai pu te dire que ton souci majeur est que tu dois tout de suite faire une copie du paramètre (char *data). Ce pointeur est un pointeur interne de flex et tu ne dois pas t'en servir directement. Tu dois faire une copie pour que cela fonctionne.

    Fais attention aussi, ton strcat est faux, tu n'avais pas le droit d'ajouter des choses à cette chaîne non plus.

  5. #5
    Candidat au Club
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Février 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2017
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Merci pour ces indications ! En effet c’était un problème de pointeur Je suis passé par strdup pour stocker les valeurs dans mon tableau et mon problème s'est résolu ! Du coup j'arrive bien à parser mon fichier et récupérer ce qu'il me faut. Je testerai ça sur de plus gros programmes pour voir si flex seul tiens le coup !
    En ce qui concerne le problème de ce sujet c'est résolu

  6. #6
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    N'oublie pas de désallouer la mémoire et t'assurer que tu as assez de mémoire quand tu fais des choses comme strcat ;-)

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 25/06/2015, 16h55
  2. Problème Stockage de données
    Par MrAd11 dans le forum Tomcat et TomEE
    Réponses: 1
    Dernier message: 28/08/2012, 14h56
  3. Problème de stockage de données en request
    Par fatenatwork dans le forum Servlets/JSP
    Réponses: 1
    Dernier message: 14/12/2007, 17h45
  4. Stockage de données cartographiques en BDD
    Par Mack.51 dans le forum Décisions SGBD
    Réponses: 3
    Dernier message: 16/06/2004, 12h48
  5. Stockage de données & lecture d'un fichier texte
    Par petitours dans le forum C++Builder
    Réponses: 6
    Dernier message: 13/03/2004, 14h05

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