Aller au menu - Aller au contenu

[Atelier] Préprocesseur C

Craque ton caleçon !

Pour accéder à cette section
Connectez-vous !
connexion_rpx
Page 1  2  Suivante
Auteur Message
1 visiteur sur ce sujet (1 Anonyme)
Page 1  2  Suivante
Hors ligne shareman # Posté le 24/09/2009 à 21:48:46
charlotte <3
Avatar

Ville : Mertzwiller
Pays : France métropolitaine

Bonjour à tous !

À travers ce topic co-écrit avec GuilOooo, c'est encore un nouvel atelier qui s'ouvre sur le forum "Autres langages". Celui-ci est un peu particulier, dans le sens où ce n'est pas un exercice de programmation très courant qui vous sera proposé. Cet atelier se veut donc plutôt singulier, et en même temps ludique (on l'espère ;)) et enrichissant.

Avant la présentation du sujet, encore quelques mots. Comme toujours, c'est un atelier, ça doit donc être divertissant et apporter quelque chose à tout le monde. N'hésitez donc pas à poster vos propositions de code, à commenter celles des autres (ssi. vous vous en sentez capable), ou à poser des questions si quelque chose vous échappe ; il y aura toujours quelqu'un pour y répondre ! Et encore une fois comme toujours, il n'y aura pas de correction, pas de classement, pas de gagnant, pas de récompense. Juste des discussions passionnantes autour de codes qui le seront tout autant (enfin ça, on l'espère :) ).

Thème : mini-préprocesseur pour langage C



Le but du jeu, aujourd'hui, va être de coder un mini-préprocesseur pour le langage C.

Il s'agit d'un programme qui lit un texte, et interprète certains mots (qu'on nomme des *directives*) comme « #define » ou « #include » et à partir de ces directives interprétées, fournissant en sortie un autre texte, sans ces directives mais avec tous les changements nécessaires. Mais soyons clair : Le but n'est pas de coder un préprocesseur complet, qui exécute toutes les directives prévues par le langage C, mais seulement quelques unes (enfin, vous pouvez toujours faire plus :p), le but n'étant pas d'envisager une distribution de votre chef d'œuvre mais de s'entraîner.
Pour ceux qui ne voient absolument pas ce que signifie "préprocesseur pour langage C" ou (inclusif) qui ne savent plus du tout en quoi consiste son rôle, deux liens : first and last.

Bon, vous êtes maintenant en droit de vous demander : À quoi cela va-t-il me servir ? Question stupide pour les uns, parfaitement légitime pour les autres. En réalité, cet exercice se veut comme dit "enrichissant", c'est à dire que non seulement il vous fait bosser vos connaissances sur le rôle d'un préprocesseur, mais en plus, il va vous permettre de vous familiariser avec des techniques de programmation fondamentales (analyse lexicale et syntaxique, recherche de sous-chaînes, etc.). Plus ambitieux encore : vous faire découvrir de nouvelles techniques.

Pour en revenir à l'exercice, deux détails qui ont leur importance (ou pas) :
- Il sera inutile de se focaliser sur les entrées / sorties (mais si vous tenez à faire un truc parfait à ce niveau, libre à vous comme toujours) : le but n'est pas ici de coder une GUI ou de faire une entrée hyper-sécurisée. Si vous avez du mal à vous en sortir avec ce genre de chose, vous pouvez même écrire le code à interpréter en dur dans votre source ;

- Même si, à première vue, vous pourriez être tentés de faire un programme qui modifie le fichier initial au fur et à mesure qu'il interprète les commandes, nous vous conseillons plutôt de séparer l'entrée de la sortie.

Quelques directives importantes



Code : C - les inclusions de fichiers
1
2
#include "monfichier.h"
#include <fichier.h>


Cette directive du langage C, qui est d'ailleurs sans doute la plus connue, sert à inclure un fichier dans le fichier courant. Vous allez donc devoir copier le contenu du fichier spécifié dans la sortie. Trois points sur lesquels il faudra être vigilant :

- Il y a une différence entre <> et "". Je vous ai donné deux liens plus haut, la réponse y est ;) ;
- Le fichier inclue doit lui aussi passer par votre préprocesseur avant de l'inclure à proprement parler ;
- Le chemin du fichier spécifié peut être un chemin absolu ou relatif. Si le fichier n'existe pas, on arrête l'analyse et on indique une erreur (et comme tout bon programme, en donnant le maximum de détails sur cette erreur).

Code : C - les définitions
1
2
3
#define TXT
#define TXT BLABLA HAHA
#define TXT(a, b) BLABLA a HAHA b


Sans doute la directive la plus connue après #include, la #define. Pour ne pas vous emmêler les pinceaux, nous allons séparer trois aspects de cette directive (les trois "formes" que vous pouvez voir dans le code du dessus) :

- la #define simple, qui définit juste un mot ("définir" ici ne veut rien dire de particulier, le préprocesseur doit juste se souvenir qu'il a définit ce mot)
- la #define qui sert à remplacer un mot (le mot #definé) par un texte. Si votre programme rencontre une ligne comme la ligne 2 du code plus haut, il doit se souvenir qu'à chaque occurrence du mot "TXT" dans votre texte, il doit écrire "BLABLA HAHA" dans la sortie, à la place de "TXT". Cette forme de la #define a donc un rôle de substitution de texte.
- la macro. Plus chaud à implémenter (encore une fois, ou pas). La macro agit comme la deuxième forme de #define que nous avons vu mais prend des paramètres. Ces paramètres peuvent être du texte totalement quelconque. Dans la définition de la macro, ces textes paramétriques sont désignés par des identifiants. Lors de la substitution de texte, ces identifiants sont remplacés par les textes passés en paramètre à la macro lors de son "appel".
À titre d'exemple : devra résulter d'un "appel" à "TXT(tralala, ceci est un exemple)" le texte suivant : "BLABLA tralala HAHA ceci est un exemple".

Il existe des opérateurs que l'on peut appeler dans la définition d'une macro : # et ##. # ajoute les guillemets autour d'un texte et ## concatène deux textes. Pour plus de détails, il y a les liens plus haut ;).

Code : C - l'annulation d'une définition
1
#undef TXT

Très simplement : cette instruction demande au préprocesseur d' "oublier" que TXT a été #definé.

Code : C - les structures conditionnelles
1
2
3
4
#ifdef TRUC_DEFINE
#ifndef TRUC_DEFINE
#else
#endif


Les structures conditionnelles (enfin une partie d'entre-elles) du préprocesseur C. #ifdef TXT imprime le texte suivant cette directive (jusqu'au prochain #else ou #endif correspondant) si et seulement si TXT a été #definé préalablement. #ifndef TXT fonctionne exactement sous le même principe, sauf qu'on imprimera le texte si et seulement si TXT n'a pas été #definé préalablement. #else exprime un "sinon" (je pense que vous comprennez maintenant comment ça va marcher) ; et #endif doit finir toute structure conditionnelle.

Voilà. Ici, il y a que quelques directives, il s'agit en fait des plus importants (sans dire que d'autres ne sont pas importants). Essayez déjà de voir ce que vous pouvez gérer de tout ça avant d'aller plus loin, mais n'hésitez pas non plus à vous lancer des défis à vous-mêmes (ou pourquoi pas entre-vous, participants) :p.

Deux petits détails supplémentaires que je n'ai pas réussi à caser avant :
- Il n'y a pas de notion de portée !
- Les noms des #define doivent utiliser exactement le même alphabet que les noms de variables en C.

Vous êtes encore là ?



Nous insistons encore : allez à votre rythme. Vous n'êtes pas obligés de tout faire pour pouvoir poster, vous pouvez vous contenter de poser des questions, ou même poster votre code à différentes étapes de sa fabrication (c'est d'ailleurs très judicieux comme procédé, le risque de se planter totalement est moins important).

Dernier point important : vu que nous sommes ici pour coder et critiquer du code, on veut du *code*. Si vous postez un exécutable, il risque d'être ignoré car personne n'aura rien à dire dessus (ou sinon "ouais ça marche, super") ! De plus, on préfère avoir votre code ici, même s'il est long. Vous pouvez utiliser la balise secret pour le cacher s'il gênerait la navigation, ou au pire des cas pastebin ou pocoo pour l'uploader. Dans les autres cas, lorsque quelqu'un lira le sujet, dans longtemps, il ne retrouvera peut-être plus vos œuvres, ce serait dommage :) .

On veut du code certes, mais aussi du code intéressant. Si vous postez un code identique aux trois précédents, comprenez que ce n'est pas très intéressant pour les autres. Ce n'est pas une contrainte (loin de là), mais cherchez aussi à innover, faire "autrement" que les autres, optimiser les codes des autres éventuellement.

Bon atelier à tous !

PS : Exemple "avant preproc, après preproc".
Édité le 26/09/2009 à 19:37:21 par shareman

Nouvel atelier : Codez votre propre petit préprocesseur pour langage C !
Citation : Woody Allen
Si l'au-delà existe, c'est à quelle distance du centre ville, et c'est ouvert jusqu'à quelle heure ?
 
Connecté Colb-Seton # Posté le 25/09/2009 à 18:21:58
Avatar

Ah un nouvel atelier ! Une petite question :
Le prépocesseur en C peut être considéré comme un "mini" langage, donc faudrait il coder un ptit langage avec la synthaxe prépocesseur, ou simplement reproduire les prépocesseur du C ?
Parce que je vois mal comment coder des bouts du C sans le C en entier.
Merci,

 
Connecté Pouet_forever # Posté le 25/09/2009 à 18:54:11
Trance forever :)
Avatar

Le but (si j'ai bien compris) est que tu indiques ton fichier à "compiler" (main.c :D ) et ensuite c'est toi qui l'analyse et pas le C :)
Et tu sors un autre fichier qui contient tout ce qui a été modifié.

Je sais pas si ce que j'ai dit est clair ^^

Tuto sur le préprocesseur C

Pourquoi en vieillissant les biscuits durs deviennent mous et les biscuits mous deviennent durs ?
Est-ce que le mot «tumeur» a été inventé par un médecin qui aime l'humour noir? :lol:
warning: target of assignment not really an lvalue; this will be a hard error in the future

Codes sources Apple c'est par là -> Apple Open Source

 
Hors ligne gnomnain # Posté le 25/09/2009 à 18:56:18
Avatar
Newsers

Citation : Colb-Seton
Ah un nouvel atelier ! Une petite question :
Le prépocesseur en C peut être considéré comme un "mini" langage, donc faudrait il coder un ptit langage avec la synthaxe prépocesseur, ou simplement reproduire les prépocesseur du C ?
Parce que je vois mal comment coder des bouts du C sans le C en entier.
Merci,

En fait, le préprocesseur C peut s'utiliser avec autre chose que du C. Par exemple, tu peux t'en servir comme un tout petit langage de templates quand tu as juste à faire quelques trucs simples (sans boucles).

Image utilisateur
«Software and cathedrals are much the same - first we build them, then we pray»
Haskell - Learn You a Haskell - Real World Haskell - xmonad

Pourquoi on ne viendra pas vous plagier (ou "On veut les sources !")
Apprenez Haskell ! - #sdz
 
Connecté Colb-Seton # Posté le 25/09/2009 à 19:07:18
Avatar

Citation : Pouet_forever
Je sais pas si ce que j'ai dit est clair ^^

Pas vraiment non ^^ .
Citation : gnomnain
En fait, le préprocesseur C peut s'utiliser avec autre chose que du C. Par exemple, tu peux t'en servir comme un tout petit langage de templates quand tu as juste à faire quelques trucs simples (sans boucles).

Merci, mais ça ne répond pas à ma question qui est :
Citation : Moi-même
faudrait il coder un ptit langage avec la synthaxe prépocesseur, ou simplement reproduire les prépocesseur du C ?

 
Hors ligne GuilOooo # Posté le 25/09/2009 à 19:11:02
PriPrOTtTt§!!!§
Avatar
Modérateurs
Flux RSS

On reproduit le préprocesseur C. On ne crée pas de langage.

EDIT : enfin, si tu veux le faire après, tu peux aussi hein :D . Mais l'idée ici c'est vraiment d'imiter le préproc. En vrai, je n'ai pas compris ce que tu entendais par « créer un ptit langage avec la syntaxe du préprocesseur », où as-tu vu ça dans le sujet ?
Édité le 25/09/2009 à 19:15:18 par GuilOooo

Attention, je mords !
Blog de l'Homme Moderne Erlang Buzzerl Real World Haskell Haskell Learn yourself Haskell
 
Connecté Colb-Seton # Posté le 25/09/2009 à 19:16:37
Avatar

Citation : Colb-Seton
je vois mal comment coder des bouts du C sans le C en entier


Edit : Citation : GuilOooo
EDIT : enfin, si tu veux le faire après, tu peux aussi hein :D . Mais l'idée ici c'est vraiment d'imiter le préproc. En vrai, je n'ai pas compris ce que tu entendais par « créer un ptit langage avec la syntaxe du préprocesseur », où as-tu vu ça dans le sujet ?

Bah c'est que j'arrive pas à me représenter ce que ça pourrait donner. Donc je cherche des pistes.
Édité le 25/09/2009 à 19:18:34 par Colb-Seton

 
Hors ligne shareman # Posté le 25/09/2009 à 19:25:00
charlotte <3
Avatar

Ville : Mertzwiller
Pays : France métropolitaine

En fait, tu dois te poser la question : qu'est-ce que tu dois pouvoir faire ?

- tu dois pouvoir reconnaitre les directives ;

- mais tu dois aussi pouvoir retrouver un "appel" à #define au sein d'un code et agir en fonction du type de #define qu'il s'agit. Pour cela, il faudra un peu se creuser les méninges pour éviter de faire du O(n^42) (sache que tout le préproc (du moins ce que l'on propose d'implémenter ici) peut être implémenté de manière linéaire en la taille du fichier d'entrée).

Mais remarque qu'à aucun moment tu ne dois toucher à la grammaire du langage C, donc j'ai envie de dire que le C là-dedans (en oubliant le préproc), on s'en fiche pas mal.

Mais je peur que tu n'ai simplement pas compris ce que doit vraiment faire un préproc. Est-ce cela ta difficulté ?
Édité le 25/09/2009 à 19:26:55 par shareman

Nouvel atelier : Codez votre propre petit préprocesseur pour langage C !
Citation : Woody Allen
Si l'au-delà existe, c'est à quelle distance du centre ville, et c'est ouvert jusqu'à quelle heure ?
 
Connecté Colb-Seton # Posté le 25/09/2009 à 19:35:21
Avatar

Citation : shareman
Mais je peur que tu n'ai simplement pas compris ce que doit vraiment faire un préproc. Est-ce cela ta difficulté ?

En effet je crois que t'as mis le doigt dessus. Pour moi les prépocs, ce sont des instructions, qui ne nécessitent pas de place en mémoire.
Édité le 25/09/2009 à 19:35:56 par Colb-Seton

 
Connecté Maxibolt # Posté le 25/09/2009 à 19:36:46
Devenir Gris.
Avatar

Et pourquoi ils ne nécessitent pas de place, d'après toi ? T'es pas loin en fait.

Oui oui, on a compris.
BHM, ser bi1, manjay zan.
Sota : « Le Python, c'est comme la fonction "Recherche", tant que tu ne l'emploies pas, ça ne sert à rien. »
 
Hors ligne Eyyub # Posté le 25/09/2009 à 19:45:10
#k3v1n5 rulz
Avatar

Citation : Maxibolt
Et pourquoi ils ne nécessitent pas de place, d'après toi ? T'es pas loin en fait.

Parce que ça sert juste à indiquer certaines choses ?

Image utilisateur
©Nathan21
 
Connecté Maxibolt # Posté le 25/09/2009 à 19:46:41
Devenir Gris.
Avatar

Et qu'est ce qu'on en fait, de ces indications ?

Oui oui, on a compris.
BHM, ser bi1, manjay zan.
Sota : « Le Python, c'est comme la fonction "Recherche", tant que tu ne l'emploies pas, ça ne sert à rien. »
 
Connecté Colb-Seton # Posté le 25/09/2009 à 19:47:08
Avatar

Je crois que j'ai trouvé. J'ai confondu le prépocesseur, et les directives :/ .
Donc d'après moi le but du topic serait :
Analyser les directives du programme C, et de retranscrire le tout dans un fichier .txt par exemple.
Nan ?

 
Hors ligne Eyyub # Posté le 25/09/2009 à 19:47:30
#k3v1n5 rulz
Avatar

Citation : Maxibolt
Et qu'est ce qu'on en fait, de ces indications ?

C'est comme des commentaires, mais pour le compilateur peut être ?

Image utilisateur
©Nathan21
 
Connecté Maxibolt # Posté le 25/09/2009 à 19:49:07
Devenir Gris.
Avatar

colb-seton -> retranscrire quoi ?
eyyub -> juste des commentaires ? Il n'en fait absolument rien ?

Oui oui, on a compris.
BHM, ser bi1, manjay zan.
Sota : « Le Python, c'est comme la fonction "Recherche", tant que tu ne l'emploies pas, ça ne sert à rien. »
 
Hors ligne Eyyub # Posté le 25/09/2009 à 19:51:00
#k3v1n5 rulz
Avatar

Citation : Maxibolt
Eyyub -> juste des commentaires ? Il n'en fait absolument rien ?

Si si, mais comme les commentaires servent à indiquer des choses au programmeur, pour le compilateur ça va être des indications, indiquer un fichier à lier etc...?

Image utilisateur
©Nathan21
 
Hors ligne shareman # Posté le 25/09/2009 à 19:51:52
charlotte <3
Avatar

Ville : Mertzwiller
Pays : France métropolitaine

Bon, un exemple. Tu pars de ces fichiers :

Code : C - titre.h
1
Le Corbeau et le Renard

Code : C - fable.h
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#define VRAI_TEXTE
#include "titre.h"
Maître Corbeau, sur un arbre perché,
Tenait en son bec un fromage.
#define ANIMAL1 Renard
Maître ANIMAL1, par l'odeur alléché,
Lui tint à peu près ce langage :
#ifdef VRAI_TEXTE
Hé ! bonjour, Monsieur du Corbeau.
Que vous êtes joli ! que vous me semblez beau !
#else
Hep ! Salut, Monsieur du Renard.
Que vous êtes sublime ! que vous me semblez vaillant !
#endif
#define SANS_VERBE(vb) sans vb
SANS_VERBE(mentir), si votre ramage
Se rapporte à votre plumage,
Vous êtes le Phénix des hôtes de ces bois.


Ton programme "préprocesseur" qui prend en entrée le fichier fable.h doit produire en sortie le fichier suivant (appelé arbitrairement "fable.h", ça c'est pas important) :

Code : C - fable.h
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Le Corbeau et le Renard
Maître Corbeau, sur un arbre perché,
Tenait en son bec un fromage.
Maître Renard, par l'odeur alléché,
Lui tint à peu près ce langage :
Hé ! bonjour, Monsieur du Corbeau.
Que vous êtes joli ! que vous me semblez beau !
Sans mentir, si votre ramage
Se rapporte à votre plumage,
Vous êtes le Phénix des hôtes de ces bois.

Nouvel atelier : Codez votre propre petit préprocesseur pour langage C !
Citation : Woody Allen
Si l'au-delà existe, c'est à quelle distance du centre ville, et c'est ouvert jusqu'à quelle heure ?
 
Connecté Colb-Seton # Posté le 25/09/2009 à 19:53:53
Avatar

Oué je crois avoir compris. Merci !
Et ben ça va pas être très simple tout ça !

 
Connecté Maxibolt # Posté le 25/09/2009 à 19:56:02
Devenir Gris.
Avatar

eyyub, ces indications, c'est tes directives. Et le programme qui en tient compte, c'est le préprocesseur.

Oui oui, on a compris.
BHM, ser bi1, manjay zan.
Sota : « Le Python, c'est comme la fonction "Recherche", tant que tu ne l'emploies pas, ça ne sert à rien. »
 
Hors ligne Eyyub # Posté le 25/09/2009 à 19:58:55
#k3v1n5 rulz
Avatar

Citation : Maxibolt
eyyub, ces indications, c'est tes directives. Et le programme qui en tient compte, c'est le préprocesseur.

Ahh oui, effectivement j'ai confondu, excusez moi ...

Image utilisateur
©Nathan21
 
Connecté GurneyH # Posté le 25/09/2009 à 22:15:38
Avatar

Ou encore, avant la compilation, le préprocesseur transforme un fichier source en lui ajoutant(#include), en enlevant parfois(#ifdef), ou en transformant(#define)...
C'est un exercice très intéressant que vous proposez... Plus accessible que l'atelier petit langage, et très instructif sur la manière dont fonctionne le préprocesseur en général.
Vraiment une bonne idée.

 
Hors ligne Cacophrene # Posté le 29/09/2009 à 21:49:34
Il est vraiment TeX-TuX
Avatar
Flux RSS

Ville : Le cannet
Pays : France métropolitaine
études : Université de Nice Sophia Antipolis

Bonjour à tous !

Dommage qu'il n'y ait pas encore de codes par ici. :( Bon, voici ma contribution sans prétention rédigée en OCaml. Je le dis tout de suite : ce premier jet n'évoluera probablement pas, sauf pour corriger les bugs flagrants qui m'auraient échappés (code peu testé). Je vous détaille son fonctionnement ci-dessous :

  • Lire le fichier donné en entrée (j'ai utilisé fable.h ci-dessus).
  • Le découper en lignes.
  • Remplacer la liste de lignes par une liste de commandes du préprocesseur.
  • Exécuter la liste de commandes pour produire une liste de lignes (la sortie).
  • Écrire les lignes dans le fichier de sortie.

Limitations : cette méthode exige que les commandes n'occupent qu'une seule ligne et qu'il n'y ait qu'une commande par ligne. L'utilisation du module Genlex crée des contraintes sur la syntaxe des variables et des valeurs associées. L'inclusion de fichier ne fonctionne qu'avec la syntaxe #include "fichier". Ce code ne permet pas de définir des macros. La fonction List.map n'étant pas tail-rec, les fichiers volumineux provoqueront un débordement de pile. Le traitement des #ifdef et #ifndef interdit certaines imbrications. Ces limitations peuvent être levées, mais je ne le ferai pas.

Compilation/test :
  • Interpréteur : ocaml -I +camlp4 dynlink.cma camlp4o.cma str.cma
  • compilation : ocamlc -pp str.cma camlp4o


Complexité : Pour un fichier de N lignes, le premier parcours sert à créer la liste de commandes, le second à les exécuter, le troisième et dernier à les écrire dans le fichier de sortie. On est donc à la louche en O(N), mais il faut aussi tenir compte de la complexité des fonctions qui manipulent les regexp. Bref je ne crois pas que ce soit rigoureusement linéaire...

Tout le code se trouve entre les balises secret ci-dessous car il est un peu long. Je donne ici la signature commentée des principales fonctions de mon code en guise de vue d'ensemble :

Code : OCaml
 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
type t =
    Line of string              (* Ligne quelconque        *)
  | Define of string            (* #define VARIABLE        *)
  | Keyval of string * string   (* #define VARIABLE VALEUR *)
  | Include of string           (* #include "FICHIER"      *)
  | Ifdef of string             (* #ifdef VARIABLE         *)
  | Ifndef of string            (* #ifndef VARIABLE        *)
  | Else                        (* #else                   *)
  | Endif                       (* #endif                  *)
(* Le type des commandes du préprocesseur. *)

(* Fonctions auxiliaires. *)
module Aux :
  sig
    val read : string -> string
      (* Lire un fichier. *)
    val split : string -> string list
      (* Découper un texte en liste de lignes. *)
    val write : string -> string list -> unit
      (* Écrire une liste de lignes dans un fichier. *)
  end

(* Analyse lexicale. *)
module Lex :
  sig
    val tokenize : char Stream.t -> Genlex.token Stream.t
      (* Convertir un flot de caractères en flot de lexèmes. *)
    val loop : Genlex.token Stream.t -> t option
      (* Convertir un flot de lexèmes en commande du préprocesseur. *)
    val from_string_list : string list -> t list
      (* Convertir une liste de lignes en liste de commandes. *)
  end

(* Lancement du préprocesseur. *)
module Run :
  sig
    val def : (string, unit) Hashtbl.t
      (* Les variables définies (sorte de StringSet pour fainéants). *)
    val key : (string, string) Hashtbl.t
      (* Les variables associées à une valeur. *)
    val run_define : string -> unit
      (* Mémorise une variable. *)
    val run_keyval : string -> string -> unit
      (* Mémorise une variable et lui associe une valeur. *)
    val run_include : string -> string
      (* Insère le contenu d'un fichier. *)
    val pattern_of_keyvals : unit -> Str.regexp
      (* Crée un motif regexp à partir des noms de variables qui ont une valeur
       * associée. *)
    val run_replace : string -> string
      (* Remplace toutes les variables par leur valeur associée. *)
    val from_token_list : t list -> string list
      (* Crée une liste de lignes à partir d'une liste de commandes. *)
  end


Pour le code, c'est ici :

Secret (cliquez pour afficher)

Code : OCaml
  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
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
type t =
  | Line    of string
  | Define  of string
  | Keyval  of string * string
  | Include of string
  | Ifdef   of string
  | Ifndef  of string
  | Else
  | Endif

(* Fonctions auxiliaires, sans grand intérêt ici. *)
module Aux =
  struct
    let read file =
      let ich = open_in file in
      let len = in_channel_length ich in
      let str = String.create len in
      really_input ich str 0 len;
      close_in ich;
      str

    let split = Str.split (Str.regexp "\n")

    let write file contents =
      let och = open_out file in
      List.iter (Printf.fprintf och "%s\n") contents;
      close_out och
  end

module Lex =
  struct
    open Genlex
    let tokenize = make_lexer ["#"]

    let loop = parser
      | [< 'Kwd "#"; t >] ->
        begin match t with parser    
          | [< 'Ident "include"; 'String file >] -> Some (Include file)
          | [< 'Ident "ifdef"; 'Ident x >] -> Some (Ifdef x)
          | [< 'Ident "ifndef"; 'Ident x >] -> Some (Ifndef x)
          | [< 'Ident "else" >] -> Some Else
          | [< 'Ident "endif" >] -> Some Endif
          | [< 'Ident "define"; 'Ident x; t >] ->
            begin match t with parser
              | [< 'Ident y >] -> Some (Keyval (x, y))
              | [< >] -> Some (Define x)
            end
          | [< >] -> None
        end
      | [< >] -> None

    let from_string_list =
      List.map (fun str ->
        match loop (tokenize (Stream.of_string str)) with
        | None -> Line str
        | Some token -> token
      )
  end

module Run =
  struct
    let def = Hashtbl.create 7
    let key = Hashtbl.create 7

    let run_define str = Hashtbl.add def str ()
    let run_keyval = Hashtbl.add key

    (* Insérer un fichier. *)
    let run_include file =
      try Aux.read file with
      | _ -> Printf.eprintf "File %S not found.\n%!" file; exit 2

    (* Construire le motif à partir de toutes les valeurs. *)
    let pattern_of_keyvals () =
      let buf = Buffer.create 16 in
      Hashtbl.iter (fun key _ ->
        if Buffer.length buf > 0 then Buffer.add_string buf "\\|";
        Buffer.add_string buf key
      ) key;
      Str.regexp (Buffer.contents buf)

    (* Remplacer toutes les variables par leur valeur. *)
    let run_replace =
      Str.global_substitute (pattern_of_keyvals ()) (fun x ->
        Hashtbl.find key (Str.matched_group 0 x)
      )

    let from_token_list l =
      Hashtbl.clear def; 
      Hashtbl.clear key;
      let rec loop = function
        | [] -> []
        | Define str :: t -> run_define str; loop t
        | Keyval (x, y) :: t -> run_keyval x y; loop t
        | Ifdef x :: t -> if Hashtbl.mem def x then loop t else skip t
        | Ifndef x :: t -> if not (Hashtbl.mem def x) then loop t else skip t
        | Include file :: t -> run_include file :: loop t
        | Line str :: t -> run_replace str :: loop t
        | Else :: t -> jump t
        | _ :: t -> loop t
      (* Ignorer un ifdef ou ifndef : atteindre else ou endif. *)
      and skip = function
        | [] -> []
        | Else :: t | Endif :: t -> loop t
        | _ :: t -> skip t
      (* Ignorer un else : atteindre endif. *)
      and jump = function
        | [] -> []
        | Endif :: t -> loop t
        | _ :: t -> jump t 
      in loop l
  end

let _ = 
  let str = Aux.read "fable.h" in
  let tokens = Lex.from_string_list (Aux.split str) in
  let res = Run.from_token_list tokens in
  Aux.write "out.h" res



C'est tout pour ma participation. Bonne programmation.

Edit: il manquait le cas Ifndef dans le code !

Cordialement,
Cacophrène
Édité le 06/10/2009 à 19:06:01 par Cacophrene
 
Hors ligne robocop # Posté le 29/09/2009 à 22:15:05
Avatar

Très belle démonstration ! Bravo, c'est très propre.
 
Hors ligne shareman # Posté le 29/09/2009 à 22:15:45
charlotte <3
Avatar

Ville : Mertzwiller
Pays : France métropolitaine

Merci pour ta participation ! :)

À première vue, ton code semble très bon. Je vais me pencher dessus plus en détail. Même si tu dis que tu ne le feras pas, je t'encourage quand même très fortement à implémenter les macros et à optimiser un peu le tout dans la mesure du possible. En tout cas, bravo pour ce code, c'est de la qualité.

Nouvel atelier : Codez votre propre petit préprocesseur pour langage C !
Citation : Woody Allen
Si l'au-delà existe, c'est à quelle distance du centre ville, et c'est ouvert jusqu'à quelle heure ?
 
Hors ligne Cacophrene # Posté le 29/09/2009 à 22:24:57
Il est vraiment TeX-TuX
Avatar
Flux RSS

Ville : Le cannet
Pays : France métropolitaine
études : Université de Nice Sophia Antipolis

Re !

Citation : robocop
Très belle démonstration ! Bravo, c'est très propre.


Citation : shareman
À première vue, ton code semble très bon. Je vais me pencher dessus plus en détail. Même si tu dis que tu ne le feras pas, je t'encourage quand même très fortement à implémenter les macros et à optimiser un peu le tout dans la mesure du possible. En tout cas, bravo pour ce code, c'est de la qualité.

Merci à tous les deux pour vos commentaires sympathiques. :) ;) Pour les macros et les optimisations qui peuvent être apportées à ce code, je ne garantis rien. C'est bien beau de jouer à coder, mais pendant ce temps le reste ne se fait pas :lol: Dans quelques jours peut-être...

@+
Cacophrène
 
Hors ligne robocop # Posté le 29/09/2009 à 22:26:31
Avatar

Au final, ça serait pas mal dans ocaml un outils un petit peu plus modulaire que genlex, sans pour autant passer par le monstre ocamllex. Tu as des infos sur ce genre de trucs Cacophrene ?
Édité le 29/09/2009 à 22:28:15 par robocop
 
Hors ligne Cacophrene # Posté le 29/09/2009 à 22:36:36
Il est vraiment TeX-TuX
Avatar
Flux RSS

Ville : Le cannet
Pays : France métropolitaine
études : Université de Nice Sophia Antipolis

Re !

Citation : robocop
Au final, ça serait pas mal dans ocaml un outils un petit peu plus modulaire que genlex, sans pour autant passer par le monstre ocamllex. Tu as des infos sur ce genre de trucs Cacophrene ?

En fait le fichier genlex.ml comporte beaucoup de paramètres en dur. Comme on ne peut pas les modifier, certaines choses deviennent lourdes à gérer. Un exemple : la commande #include <fichier> est problématique avec Genlex parce que beaucoup de caractères ne sont pas autorisés dans les identifiants. Ainsi #include <fable-2.h> ne peut pas être parsé simplement. D'un autre côté, il y a fort à parier pour qu'une version très fortement paramétrable de Genlex soit aussi beaucoup plus lente et, en fin de compte, sans grand intérêt dans la vraie vie. Donc soit il y a des libs externes qui proposent des solutions (peut-être quelque chose comme OCaml Batteries Included, mais je ne connais pas assez pour être catégorique), soit il faut passer par lex/yacc, même si c'est moins léger.

Cordialement,
Cacophrène
Édité le 29/09/2009 à 22:37:48 par Cacophrene
 
Hors ligne Yannshu # Posté le 30/09/2009 à 13:46:08
while (1337)
Avatar

Oh, je n'avais point vu ce beau sujet interessant. :)

J'vais commencer a coder un p'tit truc ;).
 
Connecté Pouet_forever # Posté le 02/10/2009 à 10:47:01
Trance forever :)
Avatar

Bon ... je me suis pris la tête, j'ai galérer mais j'ai réussi à pondre quelque chose :)
Ce n'est pas complètement terminé mais c'est pour avoir des avis si ya quelque chose qui cloche (yen à sûrement pas mal ^^ )
J'ai pas vraiment géré la casse et compagnie ... :(

J'aimerais avoir des conseils sur la manière de procéder pour les macros, parce que j'ai mon idée mais ça m'a l'air laborieux (encore ?!?)

Je vais l'améliorer par la suite, mais voilà la première version :)

Secret (cliquez pour afficher)
Code : C - main.c
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#include "inclusions.h"

int main (int argc, char *argv[]) {
	FILE *F = NULL;
	FILE *final = fopen("out.c", "w+");
	if (argc > 1)
		F = fopen(argv[1], "r");
	else
		F = fopen("main.c", "r");
	if (F == NULL) {
		erreur(0);
		return 0;
	}
	rewind(F);
	analyse(F, final);
	fclose(F);
	fclose(final);
    return 0;
}


Secret (cliquez pour afficher)
Code : C - analyse.c
  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
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include "inclusions.h"

#define MAX 150

typedef struct def def;
struct def
{
    char nom[MAX];
	char replace[MAX];
    struct def *suiv;
};

void recupInclude(char str[], char nom[])
{
	int i = 8, j = 0;
	while (str[i++] != '"');
	while ((nom[j++] = str[i++]) != '"');
	nom[j-1] = '\0';
}

def *ajouterDef(def *declar, char nom[], char replace[])
{
    def* newDef = malloc(sizeof(def));
	
	strcpy(newDef->nom , nom);
	strcpy(newDef->replace, replace);
	newDef->suiv = NULL;
	
    if(declar == NULL)
        return newDef;
    else {
        def* tmp = declar;
        while(tmp->suiv != NULL)
            tmp = tmp->suiv;
        tmp->suiv = newDef;
        return declar;
    }
}

void recupDefine(def **declar, char str[])
{
	int i = 7, j = 0;
	char nom[MAX] = "", replace[MAX] = "";
	while (str[i++] == ' ');
	i--;
	while (str[i] != '\n' && (nom[j++] = str[i++]) != ' ');
	nom[j-1] = '\0';
	if (str[i] == '\n') {
		*declar = ajouterDef(*declar, nom, replace);
		return;
	}
	j = 0;
	while (str[i++] == ' ');
	i--;
	while (str[i] != '\n' && (replace[j++] = str[i++]) != ' ');
	*declar = ajouterDef(*declar, nom, replace);
}

int verifIfdef(def *declar, char ifdef[])
{
	if (declar == NULL)
		return 0;
	def* tmp = declar;
	while (tmp->suiv != NULL) {
		if (!strcmp(tmp->nom, ifdef))
			return 1;
		tmp = tmp->suiv;
	}
	return 0;
}

int recupIfdef(size_t n, def *declar, char str[])
{
	char ifdef[MAX] = "";
	int i = n, j = 0;
	while (str[i++] == ' ');
	i--;
	while (str[i] != '\n' && (ifdef[j++] = str[i++]) != ' ');
	ifdef[j-1] = '\0';
	return verifIfdef(declar, ifdef);
}

void ecrire(FILE *F, FILE *final, int etat)
{
	char str[MAX] = "";
	while (1) {
		fgets(str, MAX, F);
		if (etat == 1 && !strncmp(str, "#else", 5)) {
			while (1) {
				fgets(str, MAX, F);
				if (!strncmp(str, "#endif", 6))
					return;
			}
		}
		
		if (etat == 2 && !strncmp(str, "#endif", 6))
			return;
		fprintf(final, "%s", str);
	}
}

void analyse(FILE *F, FILE *final)
{
	int sinon = 0;
	def *declar = NULL;
	char str[MAX] = "";
	while (fgets(str, MAX, F) != NULL) {
		if (!strncmp(str, "#define", 7)) {
			recupDefine(&declar, str);
			
		}
		else if (!strncmp(str, "#include", 8)) {
			char name[MAX] = "";
			FILE *F1 = NULL;
			recupInclude(str, name);
			if ((F1 = fopen(name, "r")) == NULL) {
				erreur(0);
				return;
			}
			rewind(F1);
			analyse(F1, final);
			fclose(F1);
			fputc('\n', final);
		}
		else if (!strncmp(str, "#ifdef", 6)) {
			if (recupIfdef(6, declar, str)) {
				ecrire(F, final, 1);
			}
			else
				sinon = 1;
		}
		else if(!strncmp(str, "ifndef", 7)) {
			if(!recupIfdef(7, declar, str)) {
				ecrire(F, final, 1);
			}
			else
				sinon = 1;
			}
		else if(!strncmp(str, "#else", 5)) {
			if (sinon) {
				ecrire(F, final, 2);
				sinon = 0;
			}
		}
		else {
			fprintf(final, "%s", str);
		}
	}
}


Secret (cliquez pour afficher)
Code : C - erreur.c
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include "inclusions.h"

void erreur(int err)
{
	switch (err) {
		case 0:
			printf("Fichier introuvable.");
			break;
		default:
			printf("Le programme à récupéré d'une erreur sérieuse."); // Clin d'oeil aux windowsiens :D
			break;
	}
}
</secret<

<secret>Code : C - analyse.h
1
2
3
4
5
6
#ifndef ANALYSE_H
#define ANALYSE_H

void analyse(FILE *F, FILE *final);

#endif


Secret (cliquez pour afficher)
Code : C - erreur.h
1
2
3
4
5
6
#ifndef ERREUR_H
#define ERREUR_H

void erreur(int err);

#endif


Secret (cliquez pour afficher)
Code : C - inclusions.h
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#ifndef INCLUSIONS_H
#define INCLUSIONS_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "erreur.h"
#include "analyse.h"

#endif


Avec ton code Shareman, j'arrive à ce résultat là :

Code : Autre
1
2
3
4
5
6
7
8
9
10
Le Corbeau et le Renard
Maître Corbeau, sur un arbre perché,
Tenait en son bec un fromage.
Maître ANIMAL1, par l'odeur alléché,
Lui tint à peu près ce langage :
Hé ! bonjour, Monsieur du Corbeau.
Que vous êtes joli ! que vous me semblez beau !
SANS_VERBE(mentir), si votre ramage
Se rapporte à votre plumage,
Vous êtes le Phénix des hôtes de ces bois.
Édité le 10/01/2010 à 17:17:58 par Pouet_forever

Tuto sur le préprocesseur C

Pourquoi en vieillissant les biscuits durs deviennent mous et les biscuits mous deviennent durs ?
Est-ce que le mot «tumeur» a été inventé par un médecin qui aime l'humour noir? :lol:
warning: target of assignment not really an lvalue; this will be a hard error in the future

Codes sources Apple c'est par là -> Apple Open Source

 
Hors ligne shamanas # Posté le 02/10/2009 à 22:47:58
Firefox ftw!
Avatar
Flux RSS

Ville : Thessalonique
Pays : Grèce

Salut :) Voici ce que j'ai reussi a coder pour l'instant(code mal organise :p ). Je vais reposter quand j'ameliorerai. Pour l'instant #include marche bien et #define (les "fonctions" define aussi! :) )
Code(un fichier :S :p ):
Code : C++
  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
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#include <iostream>
#include <fstream>
#include <vector>

enum State
{
    DEFINE_FIRST,DEFINE_SECOND,DEFINE_FUNCTION_FIRST,DEFINE_FUNCTION_SECOND,INCLUDE,OPENQUOTES,NOCOMMAND
};

class Define
{
    public:
        Define();
        Define(const std::string& firstPart, const std::string& secondPart);
        std::string firstPart() const;
        std::string secondPart() const;
        void setFirstPart(const std::string& firstPart);
        void setSecondPart(const std::string& secondPart);
    private:
        std::string _firstPart;
        std::string _secondPart;
};
class DefineFunction : public Define
{
    public:
        DefineFunction(const std::string& firstPart,const std::string& secondPart, const std::string& parenthesis);
        std::string parenthesis() const;
        void setParenthesis(const std::string& parenthesis);
    private:
        std::string _parenthesis;
};

std::vector<Define> defines;
std::vector<DefineFunction> defineFuncs;

std::string analyze(const std::string& raw_contents);
std::string defineAnalyze(const std::string& utilT);
std::string openFile(const std::string& path);

int main(int argc, char **argv)
{
    if(argc > 1)
    {
        std::cout << openFile(argv[1]) << std::endl;
    }
    else
    {
        std::cout << openFile("lol.h") << std::endl;
    }
    return 0;
}

std::string openFile(const std::string& path)
{
    std::ifstream input(path.c_str());
    if(input)
    {
        std::string contents;
        std::string line;
        while(getline(input, line))
        {
            contents += line + '\n';
        }
        contents[contents.length()-1] = '\0';
        contents = analyze(contents);
        input.close();
        return contents;
    }
    else
        std::cerr <<"File "<< path << " missing";
    return std::string();
}

std::string analyze(const std::string& raw_contents)
{
    State nextState = NOCOMMAND;
    std::string final_contents;
    std::string util;
    for(unsigned int i = 0; i < raw_contents.length(); i++)
    {
        if(raw_contents[i] == '"' && (nextState == INCLUDE || nextState == OPENQUOTES))
        {
            if(nextState == INCLUDE)
            {
                nextState = OPENQUOTES;
            }
            else
            {
                final_contents += openFile(util);
                util.clear();
                nextState = NOCOMMAND;
            }
        }
        else if(raw_contents[i] == '(' && nextState == DEFINE_FIRST)
        {
            defineFuncs.push_back(DefineFunction(util,"",""));
            util.clear();
            nextState = DEFINE_FUNCTION_FIRST;
        }
        else if(raw_contents[i] == ')' && nextState == DEFINE_FUNCTION_FIRST)
        {
            defineFuncs.at(defineFuncs.size()-1).setParenthesis(util);
            util.clear();
        }
        else if((raw_contents[i] == ' ' || raw_contents[i] == '\n') && (nextState == DEFINE_FIRST || nextState == DEFINE_FUNCTION_FIRST))
        {
            if(nextState==DEFINE_FIRST)
            {
                defines.push_back(Define(util,""));
                util.clear();
                nextState = DEFINE_SECOND;
            }
            else
            {
                nextState = DEFINE_FUNCTION_SECOND;
            }
        }
        else if(raw_contents[i] == '\n' && nextState == DEFINE_FUNCTION_SECOND)
        {
            defineFuncs.at(defineFuncs.size()-1).setSecondPart(util);
            util.clear();
            nextState=NOCOMMAND;
        }
        else if(raw_contents[i] == ' ' && nextState == DEFINE_FUNCTION_SECOND)
        {
            util+=' ';
        }
        else if((raw_contents[i] == '\n' || raw_contents[i] == EOF) && nextState == DEFINE_SECOND)
        {
            defines.at(defines.size()-1).setSecondPart(util);
            util.clear();
            nextState=NOCOMMAND;
        }
        else if(raw_contents[i] == '\n' && nextState != NOCOMMAND)
        {
            nextState = NOCOMMAND;
        }
        else if((raw_contents[i] == '\n' || raw_contents[i] == EOF) && nextState == NOCOMMAND)
        {
            util = defineAnalyze(util);
            util+='\n';
            final_contents+=util;
            util.clear();
        }
        else
        {
            util += raw_contents[i];
            if(util == "#include ")
            {
                nextState = INCLUDE;
                util.clear();
            }
            else if(util == "#define ")
            {
                nextState = DEFINE_FIRST;
                util.clear();
            }
        }
    }
    if(nextState==NOCOMMAND)
    {
        final_contents+=util;
    }
    return final_contents;
}
std::string defineAnalyze(const std::string& utilT)
{
    std::string util = utilT;
    for(unsigned int a = 0; a < defines.size(); a++)
    {
        if(util.find(defines.at(a).firstPart()) != std::string::npos)
        {
            util.replace(util.find(defines.at(a).firstPart()),defines.at(a).firstPart().length(),defines.at(a).secondPart());
        }
    }
    for(unsigned int i = 0; i < defineFuncs.size(); i++)
    {
        if(util.find(defineFuncs.at(i).firstPart()) != std::string::npos)
        {
            std::string param;
            if(util[util.find(defineFuncs.at(i).firstPart())+defineFuncs.at(i).firstPart().length()]=='(')
            {
                int b = util.find(defineFuncs.at(i).firstPart())+defineFuncs.at(i).firstPart().length()+1;
                char buf = util[b];
                while(buf!=')')
                {
                    param+=buf;
                    b++;
                    buf = util[b];
                }
                std::string beReplaced;
                beReplaced = defineFuncs.at(i).secondPart();
                beReplaced.replace(beReplaced.find(defineFuncs.at(i).parenthesis()),defineFuncs.at(i).parenthesis().length(),param);
                util.replace(util.find(defineFuncs.at(i).firstPart()),defines.at(i).firstPart().length()+param.length()+2,beReplaced);
            }
        }
    }
    return util;
}

Define::Define(const std::string& firstPart, const std::string& secondPart)
{
    _firstPart = firstPart;
    _secondPart = secondPart;
}
Define::Define()
{
}
std::string Define::firstPart() const
{
    return _firstPart;
}
std::string Define::secondPart() const
{
    return _secondPart;
}
void Define::setFirstPart(const std::string& firstPart)
{
    _firstPart = firstPart;
}
void Define::setSecondPart(const std::string& secondPart)
{
    _secondPart = secondPart;
}

DefineFunction::DefineFunction(const std::string& firstPart, const std::string& secondPart, const std::string& parenthesis)
{
    setFirstPart(firstPart);
    setSecondPart(secondPart);
    _parenthesis = parenthesis;
}
std::string DefineFunction::parenthesis() const
{
    return _parenthesis;
}
void DefineFunction::setParenthesis(const std::string& parenthesis)
{
    _parenthesis = parenthesis;
}


using namespace global supprime
les doubles ## ne marchent plus
system("PAUSE") supprime: pas besoin sous code::blocks :-°
Eh op les std::string en arguments sont devenus const std::string& ^^
Factorisation complete :p
Changement du char(NULL) en '\0'
Le else if j'avais oublier apres une modification ^^ merci d'avoir note


note: j'edite a achaque amelioration du code
Édité le 03/10/2009 à 21:22:26 par shamanas

Image utilisateur
Image utilisateur
Concours wingineer, meilleur classement: 37eme
 

Retour au forum "Autres langages" ou à la liste des forums

Pour accéder à cette section
Connectez-vous !
connexion_rpx