Ini parser flex++ / bison++

Soyez le premier à donner votre avis sur cette source.

Vue 7 090 fois - Téléchargée 358 fois

Description

Bonjour tout le monde !

Voilà les sources d'un parseur de fichier INI généré grâce à flex++ et bison++ . Il n'y a rien d'extraordinaire à faire un parseur avec flex, mais le challenge est tout autre quand on doit le faire avec flex++ et bison++ puis l'intégrer dans une application C++ (et pas seulement pour un but pédagogique). Je livre donc le travail de 4 jours de galère en espérant qu'il puisse servir à d'autres.

Source / Exemple :


######################################################################################################################
parseurINI.l
######################################################################################################################
%{
#define _SKIP_YYFLEXLEXER_
#include "Scanner.h"
#include "ParseurINI.h"
%}

%option noyywrap
%option c++
%option yyclass="Scanner"

%%
\n			{yylineno++;}
[ \t]*			{; /* spaces */}
;[^\n]*			{; /* comments */}
[^ \t\n\r;=\[\]]+	{return YY_ParseurINI_CLASS::CHAINE ;}
.			{return yytext[0] ;}
%%

######################################################################################################################
parseurINI.y
######################################################################################################################
%name ParseurINI
%define LSP_NEEDED

%define CONSTRUCTOR_PARAM istream* pFile
%define CONSTRUCTOR_INIT : scanner(pFile)
%define CONSTRUCTOR_CODE {yyparse() ;}

%define LEX_BODY {return scanner.yylex();}

%define MEMBERS \
virtual ~ParseurINI() {} \
private: \
Scanner scanner ;\
map<string, map<string, string> > mapSections ; \
string sectionCourante ;\
public:\
const map<string, string> operator[] (string section) {return mapSections[section] ;}

%define ERROR_BODY {cerr << "error on line : " << scanner.lineno() << ", last token : '" << scanner.YYText() << "'" << endl;}

%header{
  // Inspiré de :
  // https://www.mirbsd.org/htman/i386/man1/lex.htm
  // http://pwet.fr/man/linux/commandes/bison
  // http://docs.linux.cz/programming/c++/www.icce.rug.nl/documents/cplusplus/cplusplus19.html#l362
  // Et beaucoup de courage !

#include <map>
#include <string>
#include <iostream>
#include <fstream>
#include "Scanner.h"
#include <string.h>

  using namespace std;
%}

%union { char chaine[500];}
%token <chaine> CHAINE
%type <chaine> chaine

%start fichier
%%

fichier:

	| section fichier
	| regle fichier
	;

section:
'[' chaine ']'		{sectionCourante = $2;}
	;

regle:
chaine '=' chaine	{(mapSections[sectionCourante])[$1] = $3;}
	;

chaine:
CHAINE			{strcpy($$, scanner.YYText());}
        ;
%%

######################################################################################################################
Scanner.h
######################################################################################################################
#ifndef _SCANNER_H_
#define _SCANNER_H_

#if ! defined(_SKIP_YYFLEXLEXER_)
#include <FlexLexer.h>
#endif

using namespace std ;

class Scanner: public yyFlexLexer
{
 public:
  Scanner (istream* pFile) : yyFlexLexer(pFile) {}
  int yylex();
};

#endif

######################################################################################################################
Main.cpp
######################################################################################################################
#include <map>
#include <string>
#include <vector>
#include <iostream>

#include "ParseurINI.h"

using namespace std;

int main()
{
  try
    {
      ifstream config ("config.ini") ;
      // &cin for stdin
      ParseurINI parseur(&config) ;

      map<string, string> sectionMain = parseur["Main"] ;
      cout << "Serveur MySQL : " << sectionMain["ServeurMySQL"] << endl ;

    }
  catch(string s)
    {
      cout << s << "\n" ;
      return 1 ;
    }
  catch(...)
    {
      cout << "Erreur innatendue\n" ;
      return 1 ;
    }

  return 0 ;
}

######################################################################################################################
Makefile
######################################################################################################################
COMPILE := -c
FLAGS := -Wall
CC := g++
EXEC := main.exe

all: ParseurINI.o lex.yy.o Main.o
	${CC} ${FLAGS} $^ -o ${EXEC}

%.o:%.cpp
	${CC} ${FLAGS} ${COMPILE} $^ -o $@

ParseurINI.o: parseurINI.l parseurINI.y Scanner.h
	bison++ -o ParseurINI.cpp -h ParseurINI.h -d parseurINI.y
	flex++ parseurINI.l
	g++ ${COMPILE} lex.yy.cc
	g++ ${COMPILE} ParseurINI.cpp

clean:
	rm -f *~ *.o *.gch ParseurINI.h ParseurINI.cpp lex.yy.cc ${EXEC}

Conclusion :


Les fichiers ont été crées sous Debian GNU/Linux donc attention à l'encodage.
g++ 4.3.2
flex++ 2.5.35
bison++ 1.21.9-1

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Merci, effectivement une super initiative d'avoir publié ces petits bouts de code !
le_duche
Messages postés
164
Date d'inscription
lundi 13 juin 2005
Statut
Membre
Dernière intervention
26 février 2009
-
N'oubliez pas que Flex et Bisons ont des équivalents (utiles pour trouver des tuto): Lex et Yacc
boubakerabdallah
Messages postés
1
Date d'inscription
samedi 7 février 2009
Statut
Membre
Dernière intervention
17 février 2009
-
C'est vraiment très intéressant,car je suis maintenant à la recherche de tous sortes de code flex
cs_exar
Messages postés
287
Date d'inscription
vendredi 5 décembre 2003
Statut
Membre
Dernière intervention
22 avril 2012
1 -
Merci bien ! Je vais commencer à m'y intéresser... Je vais certainement en avoir besoin pour un projet qui stagne dans mon esprit depuis quelques temps.
Bonne soirée !
cs_neria
Messages postés
320
Date d'inscription
vendredi 21 février 2003
Statut
Membre
Dernière intervention
16 février 2009
-
J'ai pas mal cherché un peu partout, mais il n'y a qu'un seul exemple sur le web et il n'est pas très explicite. Mes ressources ont été principalement :

# // Inspiré de :
# // https://www.mirbsd.org/htman/i386/man1/lex.htm
# // http://pwet.fr/man/linux/commandes/bison
# // http://docs.linux.cz/programming/c++/www.icce.rug.nl/documents/cplusplus/cplusplus19.html#l362

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.