Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 23/02/2017, à 18:09

NotsosmartChicken

Problème Analyseur lexical Flex

Bonjour,

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 lorsqu'il parse le fichier source correspondant. 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). Débutant avec Flex, je rencontre un problème et j'aurais bien besoin de conseils pour me débloquer … sad

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

[a-zA-Z0-9]+  	{	if (yyin == hfile)
			  {
			    printf ("word :%s\n", yytext);


			    if (fctON == 1)
			      {
				allocationfonctions (yytext);
			      }

			    else if (strcmp (yytext, "extern") == 0)
			      {
				printf ("extern found\n");
				fctON = 1;
				cptWords = 0;
			      }
			    else if (strcmp (yytext, "extern") != 0)
			      {
				ECHO;
			      }
			  }
			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 :

int allocationfonctions (char *data)
{
  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 :

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;
    }

  trashfile = fopen ("trash.c", "w");

  if (!trashfile)
    {
      printf ("I don't know where to throw\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;
  yyout = trashfile;
  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 ();

  free (fonctions);
  fclose (hfile);
  fclose (cfile);
  fclose (thatfile);
  fclose (trashfile);
  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 :

#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 ça va, les ré allocations fonctionnent et le parser semble faire ce que je veux, 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, celles où je n'ai pas écrit après leur création). Or je croyais que ce paramètre ne contenait que le caractère courant ?

Si quelqu'un connait bien flex 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 : Pour les âmes charitables qui se sentent prêtes à aider mais qui connaissent peu ou pas flex, ou pour les curieux qui souhaitent en savoir plus, j'ajoute un lien vers une documentation assez complète sur le sujet, où je n'ai pas vu de solution à mon problème mais que d'autres peuvent comprendre mieux qui moi :
http://www.delafond.org/traducmanfr/man … lex.1.html

Hors ligne