OVH Cloud OVH Cloud

string --> template type

7 réponses
Avatar
Benoit Rousseau
Bonjour,
J'implemente un petit "compilateur". Je définie les objets de bases
comme suit :

class Value; //LE type de base, purement virtuel (une sorte de void)

template <class T>
class Basetype : public Value {
//Les types de base (int, long, double, ...)
//Je pense que ca peut être étendu a des types plus complexes,
//mais pas pour le moment
public:
Basetype( const T& v ) : value( v ) {}
Basetype( ) {}

T value;
};

Quand je parse mon fichier, j'ai une ligne toute simple que je parse mot
à mot pour ne pas faire trop compliqué pour le moment :

new int i 2

new : mot reservé
int : type
i : nom
2 : valeur par défaut

Et je crées l'objet comme suit :
Value* v;
if( type_name == "int" ) {
v = new Basetype<int>;
} else if( type_name == "uint" ) {
v = new Basetype<unsigned int>;
} else if( type_name == "long" ) {
v = new Basetype<long>;
} else if( type_name == "ulong" ) {
v = new Basetype<unsigned long>;
} else if( type_name == "double" ) {
v = new Basetype<double>;
} ...

Est ce qu'il y a un moyen de faire plus proprement ? Par une map par
exemple (l'avantage de map est que je pourrais y ajouter mes propres
types composés)
map < string, (function static ?) > type_creator;
v = type_creator["int"](); //Je pense que c'est pas trop loin de çà ?

Comment vous faites pour parser une entrée ? mot à mot ou Lex/Yacc ?

J'ai encore un petit problème pour différencier définition et
instanciation, mais je pense que ca suivra sur *.compilers.*


--------------------------------------------
Benoît Rousseau : roussebe at spray dot se
Jouez en programmant : http://realtimebattle.sourceforge.net/

7 réponses

Avatar
Christophe Lephay
Benoit Rousseau wrote:
Quand je parse mon fichier, j'ai une ligne toute simple que je parse
mot à mot pour ne pas faire trop compliqué pour le moment :

new int i 2

new : mot reservé
int : type
i : nom
2 : valeur par défaut

Et je crées l'objet comme suit :
Value* v;
if( type_name == "int" ) {
v = new Basetype<int>;
} else if( type_name == "uint" ) {
v = new Basetype<unsigned int>;
} else if( type_name == "long" ) {
v = new Basetype<long>;
} else if( type_name == "ulong" ) {
v = new Basetype<unsigned long>;
} else if( type_name == "double" ) {
v = new Basetype<double>;
} ...

Est ce qu'il y a un moyen de faire plus proprement ? Par une map par
exemple (l'avantage de map est que je pourrais y ajouter mes propres
types composés)
map < string, (function static ?) > type_creator;
v = type_creator["int"](); //Je pense que c'est pas trop loin de çà ?


C'est tout à fait celà qu'il te faut, le map renvoyant une fonction membre
statique responsable de la création des différents objets...

Chris

Avatar
kanze
Benoit Rousseau wrote in message
news:<3fbaa52b$0$21375$...

J'implemente un petit "compilateur". Je définie les objets de bases
comme suit :

class Value; //LE type de base, purement virtuel (une sorte de void)

template <class T>
class Basetype : public Value {
//Les types de base (int, long, double, ...)
//Je pense que ca peut être étendu a des types plus complexes,
//mais pas pour le moment
public:
Basetype( const T& v ) : value( v ) {}
Basetype( ) {}

T value;
};

Quand je parse mon fichier, j'ai une ligne toute simple que je parse
mot à mot pour ne pas faire trop compliqué pour le moment :

new int i 2

new : mot reservé
int : type
i : nom
2 : valeur par défaut

Et je crées l'objet comme suit :
Value* v;
if( type_name == "int" ) {
v = new Basetype<int>;
} else if( type_name == "uint" ) {
v = new Basetype<unsigned int>;
} else if( type_name == "long" ) {
v = new Basetype<long>;
} else if( type_name == "ulong" ) {
v = new Basetype<unsigned long>;
} else if( type_name == "double" ) {
v = new Basetype<double>;
} ...

Est ce qu'il y a un moyen de faire plus proprement ? Par une map par
exemple (l'avantage de map est que je pourrais y ajouter mes propres
types composés)

map < string, (function static ?) > type_creator;
v = type_creator["int"](); //Je pense que c'est pas trop loin de çà ?


La plus général, c'est map< string, Factory* >, où Factory est une
classe abstraite (interface), mais dans beaucoup de cas, la fonction
statique ou globale suffit. L'avantage de la fabrique, c'est que tu peux
en créer des instances statiques qui s'insèrent automatiquement dans le
map dans leur constructeur, du genre :

// Singleton pour le map...
class VariableFactoryMap
{
public:
static VariableFactoryMap& instance() ;
void insert(
std::string const& typeid,
Factory* factory ) ;
Value* create(
std::string const& typeid,
std::istream& suite ) ;

private:
std::map< std::string, Factory* >
myMap ;
} ;

class Factory
{
protected:
Factory( std::string const& typeid )
{
VariableFactoryMap::instance().insert( typeid, this ) ;
}
// ...
} ;

class IntFactory : public Factory
{
// ...
private:
IntFactory() ;
static IntFactory seuleInstance ;
} ;

IntFactory IntFactory::seuleInstance ;

Avec cette technique, tu peux ajouter un nouveau type sans modifier une
seule ligne du code existant.

Comment vous faites pour parser une entrée ? mot à mot ou Lex/Yacc ?


Tout dépend de la complexité du langage : j'utilise volentiers lex et
yacc, mais pour des cas simple, mot à mot avec un parseur à descente
récursive fait bien l'affaire, et c'est souvent plus facile à mettre en
oeuvre.

J'ai encore un petit problème pour différencier définition et
instanciation, mais je pense que ca suivra sur *.compilers.*


--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

Avatar
Jean-Marc Bourguet
writes:

Comment vous faites pour parser une entrée ? mot à mot ou Lex/Yacc ?


Tout dépend de la complexité du langage : j'utilise volentiers lex
et yacc, mais pour des cas simple, mot à mot avec un parseur à
descente récursive fait bien l'affaire, et c'est souvent plus facile
à mettre en oeuvre.


lex et yacc me semblent surtout convenir pour des langages de
complexites moyennes. Quand c'est trop complexe, il faut trop de
hacks, quand c'est trop simple, c'est plus facile de tout faire a la
main. Deux choses qui augmentent l'interet de ces outils:

- la volatilite du langage, quand il change beaucoup ca peut etre
plus facile de les utiliser
- l'experience, quand on ne les connait pas, c'est moins
interessant de les apprendre pour un projet isole.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
kanze
Jean-Marc Bourguet wrote in message
news:...
writes:

Comment vous faites pour parser une entrée ? mot à mot ou Lex/Yacc ?


Tout dépend de la complexité du langage : j'utilise volentiers lex
et yacc, mais pour des cas simple, mot à mot avec un parseur à
descente récursive fait bien l'affaire, et c'est souvent plus facile
à mettre en oeuvre.


lex et yacc me semblent surtout convenir pour des langages de
complexites moyennes. Quand c'est trop complexe, il faut trop de
hacks, quand c'est trop simple, c'est plus facile de tout faire a la
main.


En effet, je m'en servais pour C et pour Basic (et pcc les utilisait),
mais d'après ce que j'ai entendu dire, la plupart des compilateurs C++
s'en passe, et préfèrent un parseur écrit à la main, à déscente
récursive.

Dans l'ensemble, j'utilise lex plus souvent que yacc. Mais même là, pour
des choses simple, mes FieldArray sont souvent plus simple à mettre en
oeuvre.

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16



Avatar
Loïc Joly
Jean-Marc Bourguet wrote:

lex et yacc me semblent surtout convenir pour des langages de
complexites moyennes. Quand c'est trop complexe, il faut trop de
hacks, quand c'est trop simple, c'est plus facile de tout faire a la
main. Deux choses qui augmentent l'interet de ces outils:

- la volatilite du langage, quand il change beaucoup ca peut etre
plus facile de les utiliser
- l'experience, quand on ne les connait pas, c'est moins
interessant de les apprendre pour un projet isole.


Une question rapide : Est-ce que l'un d'entre vous a déjà utilisé Spirit
? Et si oui, comment le situez vous par rapport à Lex/Yacc ?

--
Loïc

Avatar
Jean-Marc Bourguet
Loïc Joly writes:

Jean-Marc Bourguet wrote:

lex et yacc me semblent surtout convenir pour des langages de
complexites moyennes. Quand c'est trop complexe, il faut trop de
hacks, quand c'est trop simple, c'est plus facile de tout faire a la
main. Deux choses qui augmentent l'interet de ces outils:
- la volatilite du langage, quand il change beaucoup ca peut etre
plus facile de les utiliser
- l'experience, quand on ne les connait pas, c'est moins
interessant de les apprendre pour un projet isole.


Une question rapide : Est-ce que l'un d'entre vous a déjà utilisé Spirit ?


Pas moi. J'ai rapidement survole mais n'ai pas regarde les choses en
details.

Et si oui, comment le situez vous par rapport à Lex/Yacc ?


Je connais trop bien lex/yacc et pas assez Spirit pour commenter en
profondeur. Mais je n'ai rien vu de suffisemment nouveau pour
percevoir l'interet d'investir dans Spirit si on connait deja
lex/yacc.

En fait je connais trop bien lex/yacc pour envisager -- en
production -- autre chose pour la classe de probleme ou je crois que
les generateurs automatiques sont une bonne solution: le cout de
l'apprentissage ne serait jamais recupere par le gain eventuel. En
experimentation, ca vaudrait vraissemblablement la peine (puisque
l'objectif alors est l'apprentissage) mais mes interets sont
suffisemment differents pour le moment que pour faire autre chose
qu'un suivit de loin et quand je travaillais sur des parseurs, les
langages etaient trop complexes a mon avis pour lex/yacc (bien qu'une
des implementations utilisait l'equivalent, d'ou mon opinion
d'ailleurs).

Pour info, la chose la plus importante qui me semble manquer aux
generateurs automatiques est une gestion correcte des erreurs dans
l'entrees. J'ai vu des papiers interessants mais rien vu venir dans
des generateurs destines a la production.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Samuel Krempp
le Thursday 20 November 2003 08:49, écrivit :

Une question rapide : Est-ce que l'un d'entre vous a déjà utilisé Spirit
? Et si oui, comment le situez vous par rapport à Lex/Yacc ?


je l'ai utilisé un peu, pour parser des expressions mathématiques simples.
Je n'ai jamais utilisé Lex/Yacc, mais spirit me correspondait mieux car ça
fonctionne en ajoutant simplement du code dans mon programme. ça ne me
disait rien d'avoir un ensemble de fichiers supplémentaires et des
pré-compilations à gèrer dans mon makefile.

--
Sam