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 :

Analyseur lexical du langage Pascal


Sujet :

C

  1. #1
    Nouveau membre du Club
    Inscrit en
    Juillet 2012
    Messages
    60
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 60
    Points : 36
    Points
    36
    Par défaut Analyseur lexical du langage Pascal
    Bonjour tout le monde
    J'ai codé un petit analyseur lexical pour le langage C, mais il beugue sans arrêt, après plusieurs tentatives de correction, je le poste sur ce forum espérant que vous pouviez m'éclaircir un peu.
    Je sais que les fonction du header: "verif.h" sont erronées, mais je ne suis pas arrivée à les réctifier :s
    voici mon code joint.
    Merci pour toutes vos réponses
    Fichiers attachés Fichiers attachés

  2. #2
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    - Les .h ne doivent pas (traditionnellement) contenir du code mais des déclarations. Le code se met dans des .c

    - Les fonctions définies dans verif.h :
    La première est équivalente à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int est_commentaire(char com[])  // le 1 de char com[1] ne sert à rien
    {                   
        return strcmp(com,tab_car_spe[1].lexem)==0 ;
    }
    A noter que cette fonction ne teste pas si la chaine com commence par tab_car_spe[1].lexem mais est identique à tab_car_spe[1].lexem

    Pour les autres fonctions, le return 0; est mal placé. Il doit être en dehors de la boucle. Par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int est_mot_cle(char nom[]) // le 20 ne sert à rien
    { 
      int i;  
      for(i=0;i<nbre_mot_cle;i++)
      {                     
         if(strcmp(nom,tab_mot_cle[i].lexem)==0) return 1;
      }
      return 0;
    // ou
    //  for(i=0;i<nbre_mot_cle;i++)
    //      if(strcmp(nom,tab_mot_cle[i].lexem)==0) return 1;
    //  return 0;
    }
    Là encore, le test porte sur l'intégralité de la chaine nom

    - je n'ai pas regardé le reste
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  3. #3
    Nouveau membre du Club
    Inscrit en
    Juillet 2012
    Messages
    60
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 60
    Points : 36
    Points
    36
    Par défaut
    Merci pour ces éclaircicement mais le code beugue toujours même après rectification de mes fonctions....!!

  4. #4
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Ton programme est mal structuré et difficile à étudier pour celui qui ne l'a pas conçu. Il faut remettre de l'ordre avant d'aller plus loin. Tel qu'il est, il est illisible pour moi.

    -1 Supprimer toutes ces variables globales qui obscurcissent le code et le rendent difficile à suivre. Privilégier à la place le passage des arguments aux fonctions. Ceci permet de les rendre autonomes et donc de vérifier leur bon fonctionnement sans s'occuper du reste du code. Ceci fait, il suffit de s'assurer que les conditions d'appel sont correctes pour valider leur utilisation. Si elles utilisent des globales, leur fonctionnement dépend de l'état des globales qui ont pu être modifiées dans n'importe quelle autre partie du code et on ne sait ni où, ni quand, ni par qui, ni pourquoi.

    -2 Les .h ne sont pas normalement des fichiers de code supplémentaires, mais des déclarations de type, de prototypes, de constantes (et si on utilise (hélas) des variables globales des déclarations en extern de celles-ci)
    Le code et la définition des variables doit être mis dans un .c et former une unité de compilation avec le .h associé (correspondant au contenu du .c). Le programme est alors constitué d'un ensemble d'unité de compilation, qui peuvent être compilées indépendamment les unes de autres, qui seront rassemblées pour former le programme complet et exécutable au moment de l'édition de liens.

    Ceci permet de mettre au point chaque module indépendamment des autres et de s'appuyer pour avancer sur des fonctions dont le fonctionnement a été testé et qui peuvent être considérées comme correctes.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  5. #5
    Nouveau membre du Club
    Inscrit en
    Juillet 2012
    Messages
    60
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 60
    Points : 36
    Points
    36
    Par défaut
    Je suis tout à fait consciente de la complexité de mon code, complexité accentuée par l'usage des variables globales, mais il se trouve que c'est un devoir et que ces variables globales me sont imposées par l'énoncé de l'exercice, ainsi que les fonctions à utiliser et les arguments à passer, de ce fait, je n'ai pas vraiment une grande liberté côté méthodologie.

    En ce qui concerne les ".h" et les ".c", j'avoue que je ne faisais pas vraiment la différences, "les headers sont des parcelles de codes composant le projet et servant à "fragmenter" le code afin qu'il soit plus lisible": voilà l'idée que j'avais, mais à présent, grâce à ta remarque j'ai bien compris la différence.

    Merci

  6. #6
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Pour améliorer ton code, outre les indications précédentes:
    pour uni_lex_suiv(), tu as une machine à états
    • nomme les états, plutot que 1, 2, 3. (soit a coup de macro, soit avec une énumération)
    • restructure-la pour supprimer le 1, qui est identique au 0.
    • utilise des énumérations plutot que des chaines de caracteres pour nommer les tokens.
    • créée une fonction pour chaque traitement répétitif.


    Je ne le redirai jamais assez: "Un copié-collé, ça se justifie. Deux, c'est un de trop."
    Code par exemple : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void define_token(TTOKEN token, const char* mot) {
    uni_lex.token=token;
    strcpy(uni_lex.lexem,mot);
    }
    ou mieux:
    Code par exemple : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //uni_lex ne doit pas etre nul
    int define_token(TUNITE_LEXICALE* uni_lex, TTOKEN token, const char* mot) {
    if (uni_lex==NULL) return -1;//erreur: uni_lex ne doit pas etre nul
    uni_lex->token=token;
    strcpy(uni_lex->lexem,mot);
    return 0;//tout s'est bien passé
    }
    //que tu appelleras ainsi:
    TUNITE_LEXICALE uni_lex;
    define_token(&uni_lex, REAL_TOKEN, mot);

    Supprime des variables globales en utilisant les arguments et valeurs de retour.
    je parle de celle-ci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int car_courant;
    FILE * fichier_source;
    char mot[200];
    char op[6];
    int etat=0;
    Concernant les fichiers .h et .c, tu as bien un prototype.h, qui est légitime.
    tous les autres sont en réalité des .c déguisés.
    modifie les en incluant prototype.h en cas de besoin
    retire leur inclusion du XO2_Beta1.c (dont tu devrais changer l'extension, c'est .c, car certains compilateur comprennent .C comme du c++ si tu ne dis rien)
    enfin, compile les indépendamment: gcc *.c -c
    puis lie chaque fichier "objet" obtenu en un unique executable: gcc *.o -o XO2_Beta1
    ainsi, tu pourra ne recompiler que ceux que tu changes, et relier l'ensemble.


    Aucun énoncé ne t'interdit d'utiliser plus d'argument que demandé, quand tu peux le justifier d'un bon commentaire.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  7. #7
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    ces variables globales me sont imposées par l'énoncé de l'exercice
    Ca n'augure rien de bon sur la qualité de l'enseignement. Mais je comprend que tu doives faire avec.

    En ce qui concerne les ".h" et les ".c", ...
    Ce qui sert à fragmenter le code en plusieurs fichiers est l'utilisation de plusieurs unités de compilation.

    Il faut comprendre à quoi sert un .h.
    Lorsqu'on a plusieurs unités de compilation, on sera amené à utiliser dans une unité des choses définies une autre unité (par exemple des types ou des fonctions). Le .h d'une unité sert à faire connaitre aux autres unités ce dont elles ont besoin pour pouvoir utiliser les éléments de l'unité. Le .h n'a pas besoin de comporter toutes les définitions du .c de l'unité de compilation mais celles qui peuvent être utilisées par les autres unités de compilation.

    Pour illustrer, avec 2 unités de compilation A et B.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    ===========================
    A.c
    #include "A.h"                        // Pour assurer la cohérence des déclarations dans le .h et le .c
    typedef ... Type2;                    // Type "privé" du module A (non utilisé ailleurs). 
                                          // Déclaration inutile dans le .h
    int fonction1(Type1 t){...}           // fonction utilisée par B.c -> prototype dans le .h
    static int fonction2 (Type2, t){...}  // fonction "privée" du module A.  Prototype inutile dans A.h
                                          // mais peut être utile en début de A.c
    ----------------------------
    A.h
    typedef ... Type1;                    // Nécessaire ici à cause de la déclaration de fonction1()
    int fonction1(Type1 t);               // prototype de fonction1()
    ===========================
    B.c
    #include "A.h"                       // et faire aussi un #include "B.h" si il existe
    // Code
    // utilisation de fonction1()
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  8. #8
    Nouveau membre du Club
    Inscrit en
    Juillet 2012
    Messages
    60
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 60
    Points : 36
    Points
    36
    Par défaut
    Maintenant j'y vois plus clair. Un grand merci

Discussions similaires

  1. Analyseur lexical et syntaxique sur Pascal
    Par nadjet12 dans le forum Pascal
    Réponses: 2
    Dernier message: 09/04/2009, 23h23
  2. Analyseur lexical en Pascal
    Par acacia dans le forum Langage
    Réponses: 5
    Dernier message: 29/11/2007, 15h43
  3. Avenir du langage Pascal
    Par JoseF dans le forum Langage
    Réponses: 10
    Dernier message: 27/07/2006, 10h20
  4. Analyseur lexical a 3 automates
    Par mehdouch dans le forum C
    Réponses: 2
    Dernier message: 29/03/2006, 11h00

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