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

 C++ Discussion :

[Conseils/Aide] Structure de mon premier programme


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Invité2
    Invité(e)
    Par défaut [Conseils/Aide] Structure de mon premier programme
    Bonjour à toutes et tous,

    Bonjour, je débute en C++, alors je vais tenté de resté très très très imble et sâchez que je prend toute vos réponses en considération. Attention : mon niveau est déconcertant

    Voilà comme premier projet, je veut faire un colorateur syntaxique, oui je sais, c'est gros, c'est dûr et pas la peine de réinventer la roue
    Bon, mon colorateur syntaxique devra faire, à peu prêt comme pygments pour les connaisseurs, colorer en html... il devra être modulable et performant...

    J'ai déjà fait un bout de code, mais, pour pas trop me ridiculiser, dès le début, voilà comment il est constuit :
    • Plus que trois fichier : main.cpp, fonctions.h et langages.h
    • Plus que deux namespace : KolorEngine, KolorEngineLangage
    • Plus de variable globale


    Descriptions des fichiers :

    langages.h :
    • Namepace : KolorEngineLangage (qui contient les fonctions de parsage)
    • Description du fichier : contient les prototypes des fonctions de parsage

    fonctions.h :
    • Namespace : KolorEngine (qui contient les fonctions uselles du programme)
    • Description du fichier : contient les fonctions uselles du programme


    main.cpp :
    • Namespace : KolorEngine, KolorEngineLangage, std
    • Description du fichier : fichier contenant tout le code du programme
    • Nombre de parties : 4


    Description des parties :
    • Partie 1 : Les includes, contient toutes les inclusions nécessaire au bon fonctionnement du programme (mes deux header, <map>, <boost/regex.hpp>, <boost/function.hpp>, <iostream>
    • Partie 2 : La fonction main, appel les fonctions, traite la demande et renvois le code
    • Partie 3 : Définie les fonctions de l'espace nom KolorEngine
    • Partie 4 : Définie les fonctions de l'espace nom KolorEngineLangage


    Fonction de KolorEngine :
    • implode, qui rassemble tout les arguments (sauf les index 0 et 1) pour pouvoir les passer aux REGEX.
    • Appel_fonction, qui contient le liste des langages et qui me permet de les appeler par leurs noms


    Voilà, armez vous de patience, je tente d'apprendre, dites moi en quoi mon approche est mauvaise, qu'elle points sont à revoir (et je sais qu'il y en a).

    Par avance merci de votre aide
    Dernière modification par Invité2 ; 15/08/2008 à 12h23.

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 487
    Par défaut
    Citation Envoyé par katagoto Voir le message
    Voilà, armez vous de patience, je tente d'apprendre, dites moi en quoi mon approche est mauvaise, qu'elle points sont à revoir (et je sais qu'il y en a).
    Ben écoute, dans le principe ça m'a l'air pas mal du tout mais difficile de t'en dire plus sans avoir lu ta première ligne de code ... Le seul conseil que je pourrais te donner est de ne pas multiplier les namespaces. Au vu de ton approche, il semble que ce que tu essaies de regrouper sous des espaces de nommages devrait précisément former des classes.

  3. #3
    Invité2
    Invité(e)
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Ben écoute, dans le principe ça m'a l'air pas mal du tout mais difficile de t'en dire plus sans avoir lu ta première ligne de code ... Le seul conseil que je pourrais te donner est de ne pas multiplier les namespaces. Au vu de ton approche, il semble que ce que tu essaies de regrouper sous des espaces de nommages devrait précisément former des classes.
    Déjà, merci de votre aide, je vais dors et déjà transformer mes namespace en en classe, si vous avez d'autres suggestions

  4. #4
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Je vois au moins 2 optiques assez différentes pour ce genre de programme.

    Soit le travail peut se faire uniquement au niveau lexical (chaque fois que je vois un "int", je le met en bleu), et dans ce cas, ton programme peut ressembler à une suite de rechercher/remplacer à base d'expressions régulières.

    Soit le travail est un peu plus subtil (ce nom là, parmi ceux déclarés par l'utilisateur, c'est une variable, je le met en rouge, ah, non, c'est une fonction, je le met en vert), et dans ce cas là, il me semble que le centre de ton programme est une architecture permettant de représenter le code source, avec en entrée un parseur générant cette architecture à partir du code, et e sortie quelquechose qui génère ton format de sortie en fonction de cette architecture.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #5
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 487
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Soit le travail peut se faire uniquement au niveau lexical [...] Soit le travail est un peu plus subtil
    Et, en gros, on réécrit Lex & Yacc :-)

  6. #6
    Invité2
    Invité(e)
    Par défaut
    Merci de vos réponses et de l'intéret que vous portez à ce topic,

    Moi ce que je voudrait faire c'est, par exemple, dès qu'il tombe sur un type, hop il lui met
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <div class="type_de_base">int</div>
    Pour des types de base (int, long, double, char) ou nom (std::string, std::map), des opérateurs (+, -, ++, --, ~, ., etc.) et biensûr qu'il sâche reconnaitre les variables et les fonctions, les mots clefs, bref, pas une cherche très très poussé...

    Quoi que, par la suite, j'aimerais y intégrer un auto-indenteur...

    Bref, j'ai tout placé en class, avec un static, ais-je fait comme il fallait ?

    Juste une question : le prototype de main est bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int main(int argc, char* argv[])
    Et est-il bien interdit ou du moins déconseillé de le déclarer ?

    Je vous dêmmande ça, car un amis vient de me mettre le doute

    Par avance merci de votre aide et de votre patience...

    PS : si vous le voullez et que vous avez de la morphine je peux vous montrer mon travail...

    Edit : J'avais pas vu tes posts Obsidian, mais pour l'instant j'ai tout compris ^^"
    Dernière modification par Invité2 ; 13/08/2008 à 17h46. Motif: Voir en bas du message

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 11
    Par défaut
    Pour répondre à ta dernière question : en effet, on ne déclare jamais le prototype de main, on implémente la fonction. Voilà tout.

    Sinon le main à deux formes possible.

    Avec deux arguments :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int main(int argc, char* argv[]) // char** argv fait pareil
    Sans arguments :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int main(void) // le void est facultatif
    Et c'est tout.

    void main n'est absolument pas valide.

  8. #8
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 487
    Par défaut
    Citation Envoyé par katagoto Voir le message
    Et est-il bien interdit ou du moins déconseillé de le déclarer ?
    On ne déclare pas main() au préalable parce que cette fonction a presque toujours le même prototype, n'est utilisé par aucune instance de niveau supérieur et n'a pas vocation a être exporté au sein d'un programme tiers (dans une lib).

    Cependant, c'est complètement anodin de le déclarer quand même. D'ailleurs, moi, je ne m'en prive pas quand je stacke tous mes prototypes en tête de fichier. Ça permet de ne pas en oublier, et évite les erreurs.

  9. #9
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 487
    Par défaut
    Citation Envoyé par katagoto Voir le message
    Déjà, merci de votre aide, je vais dors et déjà transformer mes namespace en en classe, si vous avez d'autres suggestions
    Attention, encore une fois, ce n'est qu'une impression, eue en lisant l'esquisse de ton projet. Sans en voir plus, je ne peux pas te dire si c'est bien ou mal.

    Par contre, d'une manière générale, il ne faut pas multiplier les namespaces. Ils sont une réponse au problème de la pollution de l'espace des noms, jusque là unique C, quand deux fonctions ou classes distinctes risquent d'être nommées de la même façon. Donc, si tu te mets à polluer l'espace de nommage des espaces de nommages ...

    Globalement, les namespaces sont utilisés lorsqu'il y a risque de conflit entre le nom d'une de tes entités avec celui d'une entité déjà existante dans une autre projet ou une autre bibliothèque. Par extension, ça va être utile si tu veux précisément réimplémenter toute une bibliothèque à ta propre sauce.

    Ça veut dire que l'on n'utilise en général qu'un seul namespace au sein d'un même (grand) projet, et qu'on ne le fait que si ce qui est écrit est destiné à être utilisé par d'autres projets sous forme de bibliothèque. Si c'est pour compiler directement une application terminale, c'est sans intérêt.

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 11
    Par défaut
    Premièrement, je tiens à dire que je n'ai pas une connaissance poussé du langage C++, ni une structure irréprochable.
    Mes remarques sont donc à prendre avec un esprit critique.

    Alors, comme disait Obsidian :

    Attention, encore une fois, ce n'est qu'une impression, eue en lisant l'esquisse de ton projet. Sans en voir plus, je ne peux pas te dire si c'est bien ou mal.
    Or dans ton cas, ni l'espace de nommage ni les classes ne sont nécessaires, selon l'implémentation que tu utilises.

    En effet, avoir un espace de nommage n'est utile que dans certains cas (entre autre, lorsque plusieurs fonctions, au sein de projet, risque d'avoir le même nom et d'être utilisé dans les mêmes fichiers).
    À date, ça ne semble pas du tout être ton cas.

    Ensuite, créer des classes pour y mettre des fonctions statiques... c'est complètement inutile.
    Je ne sais pas si tu connais bien le paradigme OO et si tu sais comment bien l'implanter en C++. Si ce n'est pas le cas, je te conseil de te plonger plus profondément dans celui-ci avant de te lancer dans un tel projet.
    Cela t'aidera fortement dans ta structure, entre autre.
    Si c'est le cas, je te suggère alors de revoir un peu ton code pour te permettre de le structurer en classe.
    Bien sûr, de ce que tu as de fais jusqu'ici, il est difficile de dire ce qui pourrait former une classe. Mais si tu as, avant de coder, tout mis sur papier (ou si tu sais exactement dans quel direction va ton code), il devrait être facile assez facile d'établir un squelette de ces classes.

    Sinon, en général, le code m'a l'air bien.

    Bonne continuation!

  11. #11
    Invité2
    Invité(e)
    Par défaut
    Citation Envoyé par Mikechaos Voir le message
    En effet, avoir un espace de nommage n'est utile que dans certains cas (entre autre, lorsque plusieurs fonctions, au sein de projet, risque d'avoir le même nom et d'être utilisé dans les mêmes fichiers).
    À date, ça ne semble pas du tout être ton cas.
    Déjà, merci de l'intéret porté à mon travail,

    Ensuite, je me suis servis des namespace pour "diviser" mon travail en plusieurs parties, la partie noyau (détection du langage, appel de la fonction) et la partie des différentes fonctions de parsage, je dois donc revenir aux namespace ^^

    J'avais pris le soins de faire un changelog => ZIP

    voilà mon travail...

    J'attends vos remarques

  12. #12
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 487
    Par défaut
    Citation Envoyé par katagoto Voir le message
    J'attends vos remarques
    (Mon message est passé à la trappe ! Mauvaise manip' sans doute).
    Donc, en vrac :

    - Tes namespaces ne servent vraiment à rien si tes fonctions ne dépassent pas les frontières de ton application (mais bon, ils ne sont pas nocifs non plus).

    - L'un des avantages du C++ est de pouvoir continuer à écrire des fonctions quand ça se justifie plutôt que d'avoir à systématiquement instancier un objet pour le principe. Ok. Cela dit, si tu débutes et que comptes faire une bibliothèque, tu devrais dès le départ concevoir ton projet avec des classes. Enfin, ce n'est que mon avis.

    - Il y a des choses que tu peux factoriser dans ton code :
    Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
            for(int i = 2 ; i < nombre ; ++i)
            {
                if(i == 2)
                {
                    chaine.push_back(*tableau[i]);
                }
                else
                {
                    chaine.push_back(fixe);
                    chaine.push_back(*tableau[i]);
                }
            }
    se simplifie en :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
            for(int i = 2 ; i < nombre ; ++i)
            {
                if(i > 2) chaine.push_back(fixe);
     
                chaine.push_back(*tableau[i]);
            }
    Enfin, dans cette même fonction, tu définis directement dans le code une boucle commençant à 2 pour traiter argc et argv. Très bien, mais ce n'est pas l'objet en soi de ta fonction, et la liste de mots à concaténer pourrait venir d'une autre source.

    À la place, fais plutôt une boucle qui concatène tous les mots et appelle-là, toi, avec un argument de moins :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::string code = KolorEngine::implode(' ', argv+1, argc-1);

  13. #13
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Le truc fou, c'est de parser du C++.

    Tu devrais peut-être utiliser Boost.Wave ?

  14. #14
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 11
    Par défaut
    Citation Envoyé par katagoto Voir le message
    Déjà, merci de l'intéret porté à mon travail,

    Ensuite, je me suis servis des namespace pour "diviser" mon travail en plusieurs parties, la partie noyau (détection du langage, appel de la fonction) et la partie des différentes fonctions de parsage, je dois donc revenir aux namespace
    Ce n'est pas du tout ce que j'ai dit (juste pour être certain qu'il n'y a aucun malentendu).

    Voici ce qui résume exactement mon idée :
    Citation Envoyé par Obsidian
    - Tes namespaces ne servent vraiment à rien si tes fonctions ne dépassent pas les frontières de ton application (mais bon, ils ne sont pas nocifs non plus).

    - L'un des avantages du C++ est de pouvoir continuer à écrire des fonctions quand ça se justifie plutôt que d'avoir à systématiquement instancier un objet pour le principe. Ok. Cela dit, si tu débutes et que comptes faire une bibliothèque, tu devrais dès le départ concevoir ton projet avec des classes. Enfin, ce n'est que mon avis.
    Bonne continuation.

  15. #15
    Invité2
    Invité(e)
    Par défaut
    Merci à tous de participer à mon instruction ^^,

    Citation Envoyé par Mikechaos Voir le message
    Ce n'est pas du tout ce que j'ai dit (juste pour être certain qu'il n'y a aucun malentendu).

    Voici ce qui résume exactement mon idée :

    Bonne continuation.
    D'accords, attend, j'y reviens plus bas ^^

    Citation Envoyé par HanLee Voir le message
    Le truc fou, c'est de parser du C++.

    Tu devrais peut-être utiliser Boost.Wave ?
    J'ai rien compris au site xD

    Citation Envoyé par Obsidian Voir le message
    (Mon message est passé à la trappe ! Mauvaise manip' sans doute).
    Donc, en vrac :

    - Tes namespaces ne servent vraiment à rien si tes fonctions ne dépassent pas les frontières de ton application (mais bon, ils ne sont pas nocifs non plus).

    - L'un des avantages du C++ est de pouvoir continuer à écrire des fonctions quand ça se justifie plutôt que d'avoir à systématiquement instancier un objet pour le principe. Ok. Cela dit, si tu débutes et que comptes faire une bibliothèque, tu devrais dès le départ concevoir ton projet avec des classes. Enfin, ce n'est que mon avis.

    - Il y a des choses que tu peux factoriser dans ton code :
    Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
            for(int i = 2 ; i < nombre ; ++i)
            {
                if(i == 2)
                {
                    chaine.push_back(*tableau[i]);
                }
                else
                {
                    chaine.push_back(fixe);
                    chaine.push_back(*tableau[i]);
                }
            }
    se simplifie en :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
            for(int i = 2 ; i < nombre ; ++i)
            {
                if(i > 2) chaine.push_back(fixe);
     
                chaine.push_back(*tableau[i]);
            }
    Enfin, dans cette même fonction, tu définis directement dans le code une boucle commençant à 2 pour traiter argc et argv. Très bien, mais ce n'est pas l'objet en soi de ta fonction, et la liste de mots à concaténer pourrait venir d'une autre source.

    À la place, fais plutôt une boucle qui concatène tous les mots et appelle-là, toi, avec un argument de moins :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::string code = KolorEngine::implode(' ', argv+1, argc-1);
    Déjà, je me sens idiot, oui plus que d'habitude, de n'avoir pas pensé à cette amélioration...

    Je veux que mon code possède un maximum de structure possible, j'ai pensé à deux objet :
    Le premier serait constitué de trois méthodes et un attribut : implode, appel fonction et et affiche, l'attribut serait la chaine, le constructeur prendrait comme argument argv et argc, qu'il donnerait à implode, l'attribut serait la chaine...
    L'autre objet serait tout les langages validés, là j'ai trois solutions :
    Soit une class hérite de l'autre et alors les parseurs agissent directement sur l'attribut chaine...
    soit ce sont deux objet distinct et là, soit il prenne l'objet de la chaine en référence, pour travailler dessus, soit, il prennent juste la chaine et il retourne le résultat...

    Que faire ?

    Par avance merci de votre aide

  16. #16
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 487
    Par défaut
    Citation Envoyé par katagoto Voir le message
    Déjà, je me sens idiot, oui plus que d'habitude, de n'avoir pas pensé à cette amélioration...
    Ça vient avec l'entraînement, comme tout le reste, ne t'inquiète pas.
    Moi-même, il m'est déjà arrivé de passer trois jours sur un point-virgule surnuméraire.

    Je veux que mon code possède un maximum de structure possible, j'ai pensé à deux objet :
    Le premier serait constitué de trois méthodes et un attribut : implode, appel fonction et et affiche, l'attribut serait la chaine, le constructeur prendrait comme argument argv et argc, qu'il donnerait à implode, l'attribut serait la chaine...
    L'autre objet serait tout les langages validés, là j'ai trois solutions :
    Soit une class hérite de l'autre et alors les parseurs agissent directement sur l'attribut chaine...
    soit ce sont deux objet distinct et là, soit il prenne l'objet de la chaine en référence, pour travailler dessus, soit, il prennent juste la chaine et il retourne le résultat...
    Non, tu retombes dans les travers cités à mon deuxième paragraphe. Il ne faut pas définir de classe « pour le principe », si tu n'as pas l'intention de les instancier plus d'une fois à un même moment.

    Si tu veux faire de la POO efficace, il faut cesser de raisonner de façon purement séquentielle. « Point d'entrée ici; au moment t, je fais ceci; à t+1, je fais cela; etc. ». À la place, il vaut mieux approcher le problème selon cet ordre :

    - J'identifie les structures de données dont je pourrais avoir besoin et qui doivent être persistantes en mémoire. Je distingue bien la nature de chacune d'elles. C'est, d'une certaine manière, ce que tu avais commencé à faire avec tes namespaces, mais sur le code au lieu de le faire sur les données.
    - Je définis des fonctions qui pourraient s'appliquer sur ces structures pour leur faire subir un traitement.
    - Étant donné que ces fonctions et ces structures de données sont intimement liées, je crée un objet qui les rassemble toutes sous forme de membres et de méthodes.
    - Une fois que j'ai des objets distincts avec des propriétés intrinsèques, je peux définir un workflow séquentiel qui les exploite. La plupart du temps, celui-ci tiendra dans ma fonction main().

    En fait, le piège est qu'un parser n'est pas vraiment un projet typique de la POO, c'est plutôt quelque chose que l'on montre lorsque l'on apprend le traitement des langages, donc : automates, expressions régulières, une pile pour les langages de niveau supérieur, mais pratiquement aucune donnée persistante : c'est un traitement de flux : la donnée rentre, elle ressort, tout est séquentiel ... C'est le royaume du goto ! :-)

    En plus, si ton objectif est de faire un coloriseur syntaxique, l'espace sert de séparateur la plupart du temps. Cela n'a donc pas beaucoup d'intérêt de fusionner en une chaîne puisque tu seras obligé de la redécouper en lexons à l'étape d'après.

    Par contre, la plupart des langages peuvent être reconnus avec un simple automate à pile. Or, cet automate sert précisément à retenir l'état du contexte de ce que tu es en train d'analyser. Il en faut donc un par flux si tu veux en analyser plusieurs à la fois. Toutes les informations nécessaires à définir un contexte peuvent donc, elles, former une classe !

    En outre, puisque tu lis la chaîne de gauche à droite, tu n'es pas obligé de tout faire en une fois. Je te conseille donc de créer une classe « Parser » qui contient exactement deux méthodes : « void Reset () », pour faire revenir l'automate à l'état initial, et « std::string Parse (const std::string &) » pour lui donner un morceau de chaîne à lire comme si elle venait de l'entrée standard.

    En fonction de ce que tu viens de lire, soit il n'y a pas d'ambigüité et dans ce cas-là, la méthode renvoie tout de suite ce qu'elle vient de lire, en le colorisant si besoin, et en rendant éventuellement ce qu'il avait pu enregistrer lors des appels précédents, soit ce n'est pas suffisant pour prendre une décision (moitié d'un mot transmis, mot-clé dépendant de ce qui va suivre,etc.) et ta méthode renvoie une chaîne vide, tout en conservant en mémoire le morceau de chaîne que tu lui as filé (en le cumulant aux précédents si nécessaire), ainsi que l'état dans lequel elle se trouve au moment de l'appel. De cette manière, tu ne gardes en mémoire que le nécessaire et tu peux analyser un code de longueur virtuellement infinie.

    Ensuite, tu dérives ta classe « Parser » pour la spécialiser dans les différents langages que tu sais reconnaître : « CParser », « ShellParser », « SyslogParser », etc. Dérivant toutes de la même classe-mère, elles hériteront toutes des mêmes méthodes et s'utiliseront de la même manière (concept de l'« interface »).

    Tu obtiens donc des « outils » qui peuvent être exploités à loisir dans un programme de plus haut niveau, et de manière indépendante, en parallèle.

Discussions similaires

  1. Demande d'aide pour mon premier programme
    Par ne2sbeal dans le forum Windows Forms
    Réponses: 6
    Dernier message: 21/01/2009, 21h53
  2. Demande d'aide pour débuter mon premier algorithme
    Par Pierre.g dans le forum Algorithmes et structures de données
    Réponses: 7
    Dernier message: 23/08/2006, 10h04
  3. [JDOM] Mon premier programme java-xml
    Par adilo dans le forum Format d'échange (XML, JSON...)
    Réponses: 3
    Dernier message: 12/07/2006, 13h12
  4. [Language] Aide sur mon premier programme Java?
    Par hash2zo dans le forum Langage
    Réponses: 15
    Dernier message: 27/09/2005, 19h26
  5. [Débutant] Mon premier programme: rien ne va...
    Par vincent0 dans le forum OpenGL
    Réponses: 10
    Dernier message: 02/08/2005, 13h59

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