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 :

pour soumettre un programme dans la section code sources


Sujet :

C++

  1. #1
    Membre averti

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 333
    Points : 411
    Points
    411
    Billets dans le blog
    15
    Par défaut pour soumettre un programme dans la section code sources
    Bonjour,

    je voudrais mettre un code source dans la section "codes sources" du site. Mais avant, je vous le soumet pour savoir si il pourrait être plus performant.
    Il s'agit d'une version unix2dos, à la manière d'un compilateur par descente récursive prédictive.

    le schéma de traduction dirigé par la syntaxe est le suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    fichier -> {ligne.h=""} ligne {fichierprim.h=ligne_s} fichierprim {fichier.s=fichierprim.s}
    fichierprim -> retourligne {ligne.h=""} ligne {fichierprim1.h=fichierprim.h+"\r\n"+ligne.s} fichierprim1 {fichierprim.s=fichierprim1.s}
                -> epsilon {fichierprim.s=fichierprim.h}
    ligne -> caractère {ligne1.h=ligne.h+caractère} ligne1 {ligne.s=ligne1.s}
          -> epsilon {ligne.s=ligne.h}

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // main.cpp
    #include <iostream>
    #include "syntaxique.hpp"
     
    int main(int argc, char *argv[]){
      if(argc!=3)
        std::cerr<<"usage:\nuix2dos fichierentrée fichiersortie"<<std::endl;
      else{
        syntaxique objetsyntaxique(argv[1],argv[2]);
        objetsyntaxique.fichier();
      }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #ifndef TERMINAUX_HPP
    #define TERMINAUX_HPP
     
    enum terminal{FDF,retourligne,caractere};
     
    #endif
    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
    18
    19
    20
    21
    22
    23
    #ifndef LEXICAL_HPP
    #define LEXICAL_HPP
     
    #include <string>
    #include <fstream>
     
    #include "terminaux.hpp"
     
    class lexical{
    public:
      lexical(char* fichierentree);
      void analex(terminal &retourvaleur,std::string &retourattribut,int &ligne);
    private:
      std::string texte;
      std::ifstream entree;
      size_t enavant,debutlex;
      std::string lexeme;
      std::string readFileIntoString(const char* path);
      bool obtenir_FDF();
      bool obtenir_retourligneoucaractere(int &ligne);
      std::string carsuiv();
    };
    #endif
    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
    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
    //lexical.cpp
    #include <iostream>
    #include <fstream>
    #include <string>
     
    #include "lexical.hpp"
    #include "terminaux.hpp"
     
    lexical::lexical(char *fichierentree):enavant(0),debutlex(0){
      entree.open(fichierentree);
      texte = readFileIntoString(fichierentree)+(char)EOF;
      enavant=0;
    }
     
    std::string lexical::readFileIntoString(const char* path) {
      if (!entree.is_open()){
        std::cerr << "Could not open the file - '" << path << "'" << std::endl;
        exit(1);
      }
      else{
        return std::string((std::istreambuf_iterator<char>(entree)),
    		       std::istreambuf_iterator<char>());
      }
    }
     
    void lexical::analex(terminal &retourvaleur,std::string &retourattribut,int &ligne){
      if(obtenir_FDF())
        retourvaleur=FDF;
      else if(obtenir_retourligneoucaractere(ligne))
        if(lexeme=="\n")
          retourvaleur=retourligne;
        else{
          retourattribut=lexeme;
          retourvaleur=caractere;
        }
    }
     
    bool lexical::obtenir_FDF(){
      debutlex=enavant;
      int etat=0;
      std::string c;
      while(true)
        switch(etat){
        case 0:
          c=carsuiv();
          if(c[0]==(char)EOF)
    	etat=1;
          else{//echec
    	enavant=debutlex;
    	return false;
          }
          break;
        case 1:
          return true;
        }
    }
     
     bool lexical::obtenir_retourligneoucaractere(int &ligne){
       debutlex=enavant;
       int etat=0;
       std::string c;
       while(true){
         switch(etat){
         case 0:
           c=carsuiv();
    	 if(c=="\n")
    	   ligne++;
           etat=1;
           break;
         case 1:
           lexeme=c;
           return true;
         }
       }
     }
     
     
    std::string lexical::carsuiv(){
      int taille;
      if((unsigned char)texte[enavant] >= (unsigned char)0 && texte[enavant] <= (unsigned char)127)
        taille=1;
      else if((unsigned char)texte[enavant] >= (unsigned char)0xC2 && (unsigned char)texte[enavant] <= (unsigned char)0xdf)
        taille=2;
      else if((unsigned char)texte[enavant] >= (unsigned char)0xe0 && (unsigned char)texte[enavant] <= (unsigned char)0xef)
        taille=3;
      else 
        taille=4;
      std::string c=texte.substr(enavant,taille);
      enavant+=taille;
      return c;
    }
    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
    18
    19
    20
    21
    22
    23
    #ifndef SYNTAXIQUE_HPP
    #define SYNTAXIQUE_HPP
    #include <string>
    #include <vector>
     
    #include "lexical.hpp"
    #include "terminaux.hpp"
     
    class syntaxique{
    public:
      syntaxique(char *fichierentree,char *fichiersortie);
      void fichier();
    private:
      void consommer(terminal const &attendu);
      std::string ligne(std::string ligne_h);
      std::ofstream sortie;
      std::string nomfichiersortie;
      terminal symbole;
      int numligne;
      lexical objetlexical;
      std::string lexeme;
    };
    #endif
    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
    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
    // syntaxique.cpp
    #include <string>
    #include <iostream>
    #include <fstream>
     
    #include "terminaux.hpp"
    #include "syntaxique.hpp"
    #include "lexical.hpp"
     
    /*
      fichier -> {ligne.h=""} ligne {fichierprim.h=ligne.s} fichierprim {fichier.s=fichierprim.s}
      fichierprim -> retourligne {ligne.h=fichierprim.h} ligne {fichierprim1.h=fichierprim.h+CR+LF+ligne.s} fichierprim1 {fichierprim.s=fichierprim1.s}
                  -> epsilon {fichier.s=fichier.h}
      ligne -> caractere {ligne1.h=ligne.h+caractere.s} ligne1 {ligne.s=ligne1.s}
            -> epsilon {ligne.s=ligne.h}
    */
     
    syntaxique::syntaxique(char *fichierentree,char *fichiersortie):nomfichiersortie(fichiersortie),numligne(1),objetlexical(fichierentree){
      objetlexical.analex(symbole,lexeme,numligne);
      nomfichiersortie=fichiersortie;
    }
     
    void syntaxique::consommer(terminal const &attendu){
      if(symbole==attendu && symbole!=FDF)
        objetlexical.analex(symbole,lexeme,numligne);
    }
     
    void syntaxique::fichier(){
      std::string ligne_h="";
      std::string fichierprim_h="";
      if(symbole==caractere){
        std::string ligne_s=ligne(ligne_h);
        fichierprim_h=ligne_s;
        while(symbole==retourligne){
          consommer(retourligne);
          ligne_h="";
          ligne_s=ligne(ligne_h);
          fichierprim_h+="\r\n"+ligne_s;
        }
      }
      else{
        while(symbole==retourligne){
          consommer(retourligne);
          ligne_h="";
          std::string ligne_s=ligne(ligne_h);
          fichierprim_h+="\r\n"+ligne_s;
        }
      }
      std::string fichierprim_s=fichierprim_h;
      std::string fichier_s=fichierprim_s;
      sortie.open(nomfichiersortie.c_str());
      sortie<<fichier_s;
    }
     
    std::string syntaxique::ligne(std::string ligne_h){
      while(symbole==caractere){
        std::string caractere_s=lexeme;
        consommer(caractere);
        ligne_h+=caractere_s;
      }
      std::string ligne_s=ligne_h;
      return ligne_s;
    }
    je suis ouvert à toute suggestion.

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 869
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 869
    Points : 219 087
    Points
    219 087
    Billets dans le blog
    121
    Par défaut
    Bonjour,

    Dur de savoir pour la performance, vous n'expliquez pas ce que c'est sensé faire. (Et) Il y a zéro commentaire.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
        switch(etat){
        case 0:
          c=carsuiv();
          if(c[0]==(char)EOF)
    	etat=1;
          else{//echec
    	enavant=debutlex;
    	return false;
          }
          break;
        case 1:
          return true;
        }
    Pas besoin d'un switch() ici.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 570
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 570
    Points : 7 679
    Points
    7 679
    Par défaut
    Bonjour,

    L'expression c[0]==(char)EOF met un doute sur la validité de ce code.
    EOF a une valeur qui est forcément distincte de tous les caractères possibles. Donc ou bien un caractère n'est jamais géré (par exemple \377 si EOF==-1 et les char sont signés) ou bien la fin n'est pas détectée.

  4. #4
    Membre averti

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 333
    Points : 411
    Points
    411
    Billets dans le blog
    15
    Par défaut
    Pourtant, ce code fonctionne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $ xxd test
    00000000: 6466 670a 686a 6b0a 6c6d 0a              dfg.hjk.lm.
    $ ./a.out test resultat
    $ xxd resultat 
    00000000: 6466 670d 0a68 6a6b 0d0a 6c6d 0d0a       dfg..hjk..lm..
    comme je l'ai indiqué, c'est une version de unix2dos, à la manière d'un parseur par descente récursive predictive

  5. #5
    Membre habitué
    Homme Profil pro
    Admin systèmes (Windows, Linux) et réseaux - Dev DB &Java IHM calcul scientifique
    Inscrit en
    Mai 2016
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Admin systèmes (Windows, Linux) et réseaux - Dev DB &Java IHM calcul scientifique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2016
    Messages : 73
    Points : 134
    Points
    134
    Par défaut
    Citation Envoyé par emmesse Voir le message
    Pourtant, ce code fonctionne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $ xxd test
    00000000: 6466 670a 686a 6b0a 6c6d 0a              dfg.hjk.lm.
    $ ./a.out test resultat
    $ xxd resultat 
    00000000: 6466 670d 0a68 6a6b 0d0a 6c6d 0d0a       dfg..hjk..lm..
    comme je l'ai indiqué, c'est une version de unix2dos, à la manière d'un parseur par descente récursive predictive
    Bonsoir,
    ça marche parce que tu appliques la conversion à un fichier ASCII 7 bits
    Cordialement

  6. #6
    Membre averti

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 333
    Points : 411
    Points
    411
    Billets dans le blog
    15
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    fichier test:
    é
    è
    ÿ
    à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $ xxd test
    00000000: c3a9 0ac3 a80a c3bf 0ac3 a00a 
    $ unix2dos test resultat
    $ xxd resultat
    00000000: c3a9 0d0a c3a8 0d0a c3bf 0d0a c3a0 0d0a  ................
    C[0] peut être négatif comme (char)EOF, qui est égal à -1
    les char sont codé sur 8 bits et peuvent donc être négatifs, comme (char)EOF, qui est égal à -1 (=FF)
    si c[0] vaut FF alors dans ce cas on a bien c[0]==(char)EOF;

  7. #7
    Membre habitué
    Homme Profil pro
    Admin systèmes (Windows, Linux) et réseaux - Dev DB &Java IHM calcul scientifique
    Inscrit en
    Mai 2016
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Admin systèmes (Windows, Linux) et réseaux - Dev DB &Java IHM calcul scientifique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2016
    Messages : 73
    Points : 134
    Points
    134
    Par défaut
    Citation Envoyé par emmesse Voir le message
    fichier test
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ unix2dos test resultat
    $ xxd resultat
    00000000: c3a9 0d0a c3a8 0d0a c3bf 0d0a c3a0 0d0a  ................
    C[0] peut être négatif comme (char)EOF, qui est égal à -1
    les char sont codé sur 8 bits et peuvent donc être négatifs, comme (char)EOF, qui est égal à -1 (=FF)
    si c[0] vaut FF alors dans ce cas on a bien c[0]==(char)EOF;

    EOF = -1 codé dans un int pas dans un char pour pouvoir justement le distinguer du caractère dont le code est 0xff.
    Et 0xff n'existe pas dans le code ASCII 7 bits (d'où ma remarque) mais par exemple dans ISO/CEI 8859-1 0xFF est le caractère ÿ

  8. #8
    Membre averti

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 333
    Points : 411
    Points
    411
    Billets dans le blog
    15
    Par défaut
    FF est utilisé par le système linux comme marqueur de fin de fichier
    https://fr.linux-console.net/?p=9700
    (il faut cliquer sur les url)

  9. #9
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    742
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 742
    Points : 3 641
    Points
    3 641
    Par défaut
    Citation Envoyé par emmesse Voir le message
    FF est utilisé par le système linux comme marqueur de fin de fichier
    Non, 0xFF ne représente pas la fin de fichier, mais un caractère plus ou moins valide selon l'encodage choisi. EOF vaut généralement 0xFFFFFFFF (en mémoire), simplement réduit à -1 parce que c'est signé.

    Si on prend le fichier et l'encodage proposé par kick54:

    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ cat utf-8.txt
    é
    è
    ÿ
    à
    $ iconv -f UTF-8 -t ISO-8859-1 -o iso-8859-1.txt utf-8.txt
    $ hexdump -C iso-8859-1.txt
    00000000  e9 0a e8 0a ff 0a e0 0a  0a                       |.........|
    00000009

    On voit que le fichier contient un 0xFF. Ton programme ne sera pas capable de lire plus.

  10. #10
    Membre averti

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 333
    Points : 411
    Points
    411
    Billets dans le blog
    15
    Par défaut
    oui c'est vrai, vous avez raison.
    que pensez-vous de ceci:
    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
    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
    //lexical.cpp
    #include <iostream>
    #include <fstream>
    #include <string>
     
    #include "lexical.hpp"
    #include "terminaux.hpp"
     
    lexical::lexical(char *fichierentree):enavant(0),debutlex(0),findefichier(false){
      entree.open(fichierentree);
      texte = readFileIntoString(fichierentree);
      enavant=0;
    }
     
    std::string lexical::readFileIntoString(const char* path) {
      if (!entree.is_open()){
        std::cerr << "Could not open the file - '" << path << "'" << std::endl;
        exit(1);
      }
      else{
        return std::string((std::istreambuf_iterator<char>(entree)),
    		       std::istreambuf_iterator<char>());
      }
    }
     
    void lexical::analex(terminal &retourvaleur,std::string &retourattribut,int &ligne){
      if(obtenir_retourligneoucaractere(ligne))
        if(lexeme=="\n")
          retourvaleur=retourligne;
        else{
          retourattribut=lexeme;
          retourvaleur=caractere;
        }
      else if(findefichier)
        retourvaleur=FDF;
    }
     
    bool lexical::obtenir_retourligneoucaractere(int &ligne){
      debutlex=enavant;
      int etat=0;
      std::string c;
      while(true){
        switch(etat){
        case 0:
          c=carsuiv();
          if(c=="\n"){
    	ligne++;
    	etat=1;
          }
          else if(!findefichier)
    	etat=1;
          else
    	etat=2;
          break;
        case 1:
          lexeme=c;
          return true;
        case 2:
          return false;
        }
      }
    }
     
     
    std::string lexical::carsuiv(){
      int taille;
      if(enavant>=texte.size())
        findefichier=true;
      else if((unsigned char)texte[enavant] >= (unsigned char)0 && texte[enavant] <= (unsigned char)127)
        taille=1;
      else if((unsigned char)texte[enavant] >= (unsigned char)0xC2 && (unsigned char)texte[enavant] <= (unsigned char)0xdf)
        taille=2;
      else if((unsigned char)texte[enavant] >= (unsigned char)0xe0 && (unsigned char)texte[enavant] <= (unsigned char)0xef)
        taille=3;
      else 
        taille=4;
      std::string c=texte.substr(enavant,taille);
      enavant+=taille;
      return c;
    }
    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
    18
    19
    20
    21
    22
    23
    #ifndef LEXICAL_HPP
    #define LEXICAL_HPP
     
    #include <string>
    #include <fstream>
     
    #include "terminaux.hpp"
     
    class lexical{
    public:
      lexical(char* fichierentree);
      void analex(terminal &retourvaleur,std::string &retourattribut,int &ligne);
    private:
      std::string texte;
      std::ifstream entree;
      size_t enavant,debutlex;
      std::string lexeme;
      std::string readFileIntoString(const char* path);
      bool findefichier;
      bool obtenir_retourligneoucaractere(int &ligne);
      std::string carsuiv();
    };
    #endif
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #ifndef TERMINAUX_HPP
    #define TERMINAUX_HPP
     
    enum terminal{FDF,retourligne,caractere};
     
    #endif
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     $ ./a.out iso-8859-1.txt resultat
    $ xxd resultat 
    00000000: e90d 0ae8 0d0a ff0d 0ae0 0d0a            ............

  11. #11
    Membre averti

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    333
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 333
    Points : 411
    Points
    411
    Billets dans le blog
    15
    Par défaut
    et si on utilisait '\0' comme sentinelle de fin?
    d'ailleur, le schéma de traduction dirigé par la syntaxe serait plutôt ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    fichier -> ligne {fichierprim.h = ligne.s} fichierprim {fichier.s=fichierprim.s } FDF
    fichierprim -> retourligne ligne {fichierprim1.h=fichierprim.h + "\r\n" + ligne.s} fichierprim1 {fichierprim.s=fichierprim1.s}
                -> epsilon {fichierprim.s = fichierprim.h}
    ligne -> caractere {ligneprim.h = caractere.s } ligneprim {ligne.s=ligneprim.s}
          -> epsilon {ligne.s=""}
    ligneprim -> caractere {ligneprim1.h = ligneprim.h + caractere.s} ligneprim1 {ligneprim.s = ligneprim1.s}
              -> epsilon { ligneprim.s = ligneprim.h }
    retourligne désigne '\n', FDF designe '\0' et caractère désigne [^\0\n]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #ifndef TERMINAUX_HPP
    #define TERMINAUX_HPP
     
    enum terminal{FDF,retourligne,caractere};
     
    #endif
    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
    18
    19
    20
    21
    #ifndef LEXICAL_HPP
    #define LEXICAL_HPP
     
    #include <string>
    #include <fstream>
     
    #include "terminaux.hpp"
     
    class lexical{
    public:
      lexical(std::string fichierentree);
      void analex(terminal &retourvaleur,std::string &retourattribut,int &ligne);
    private:
      std::string texte;
      std::ifstream entree;
      size_t enavant,debutlex,taille_caractere;
      std::string lexeme;
      std::string readFileIntoString(const char* path);
      std::string carsuiv();
    };
    #endif
    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
    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
    //lexical.cpp
    #include <iostream>
    #include <fstream>
    #include <string>
     
    #include "lexical.hpp"
    #include "terminaux.hpp"
     
    lexical::lexical(std::string fichierentree):enavant(0){
      entree.open(fichierentree.c_str());
      texte = readFileIntoString(fichierentree.c_str());
    }
     
    std::string lexical::readFileIntoString(const char* path) {
      if (!entree.is_open()){
        std::cerr << "Could not open the file - '" << path << "'" << std::endl;
        exit(1);
      }
      else{
        return std::string((std::istreambuf_iterator<char>(entree)),
    		       std::istreambuf_iterator<char>());
      }
    }
     
    void lexical::analex(terminal &retourvaleur,std::string &retourattribut,int &ligne){
      int etat=0;//état courrant du diagramme de transition
      debutlex=enavant;//debutlex est l'indice du premier caractère du lexème suivant
      std::string c;
      bool continuer=true;
      while(continuer)
        switch(etat){
        case 0:
          c=carsuiv();//caractere suivant dans le texte d'entrée
          if(c[0]=='\n'){
    	ligne++;
    	etat=1;
          }
          else if(c[0]=='\0')
    	etat=2;
          else
    	etat=3;
          break;
        case 1:
          retourvaleur=retourligne;//unité lexicale retourligne
          continuer=false;
          break;
        case 2:
          retourvaleur=FDF;//unite lexicale FDF
          continuer=false;
          break;
        case 3:
          retourvaleur=caractere; //unité lexicale caractere
          retourattribut=c; //l'attribut de l'unité lexicale caractere
          continuer=false;
        }
    }
     
     
     
    std::string lexical::carsuiv(){
      if((unsigned char)texte[enavant] >= (unsigned char)0 && texte[enavant] <= (unsigned char)127)
        taille_caractere=1;
      else if((unsigned char)texte[enavant] >= (unsigned char)0xC2 && (unsigned char)texte[enavant] <= (unsigned char)0xdf)
        taille_caractere=2;
      else if((unsigned char)texte[enavant] >= (unsigned char)0xe0 && (unsigned char)texte[enavant] <= (unsigned char)0xef)
        taille_caractere=3;
      else 
        taille_caractere=4;
      std::string c=texte.substr(enavant,taille_caractere);
      enavant+=taille_caractere;
      return c;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // main.cpp
    #include <iostream>
    #include "syntaxique.hpp"
     
    int main(int argc, char *argv[]){
      if(argc!=3)
        std::cerr<<"usage:\nuix2dos fichierentrée fichiersortie"<<std::endl;
      else{
        syntaxique objetsyntaxique(argv[1],argv[2]);
        objetsyntaxique.fichier();
      }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #ifndef TERMINAUX_HPP
    #define TERMINAUX_HPP
     
    enum terminal{FDF,retourligne,caractere};
     
    #endif
    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
    18
    19
    20
    21
    22
    23
    #ifndef SYNTAXIQUE_HPP
    #define SYNTAXIQUE_HPP
    #include <string>
    #include <vector>
     
    #include "lexical.hpp"
    #include "terminaux.hpp"
     
    class syntaxique{
    public:
      syntaxique(char *fichierentree,char *fichiersortie);
      void fichier();
    private:
      void consommer(terminal const &attendu);  
      std::string ligne();
      std::ofstream sortie;
      std::string nomfichiersortie;
      terminal symbole;
      int numligne;
      lexical objetlexical;
      std::string lexeme;
    };
    #endif
    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
    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
    // syntaxique.cpp
    #include <string>
    #include <iostream>
    #include <fstream>
     
    #include "terminaux.hpp"
    #include "syntaxique.hpp"
    #include "lexical.hpp"
     
    syntaxique::syntaxique(char *fichierentree,char *fichiersortie):nomfichiersortie(fichiersortie),numligne(1),objetlexical(fichierentree){
      objetlexical.analex(symbole,lexeme,numligne);
    }
     
    void syntaxique::consommer(terminal const &attendu){
      if(symbole==attendu)
        if(attendu != FDF)
          objetlexical.analex(symbole,lexeme,numligne);
    }
     
    /*
    fichier -> ligne {fichierprim.h = ligne.s} fichierprim {fichier.s=fichierprim.s } FDF
    fichierprim -> retourligne ligne {fichierprim1.h=fichierprim.h + "\r\n" + ligne.s} fichierprim1 {fichierprim.s=fichierprim1.s}
                -> epsilon {fichierprim.s = fichierprim.h}
    */
     
    void syntaxique::fichier(){
      std::string fichier_s;
      if(symbole==caractere||symbole==retourligne){
        std::string ligne_h="";//attribut hérité du non-terminal ligne
        std::string ligne_s=ligne();//ligne_s est l'attribut synthétisé du non terminal ligne
        std::string fichierprim_h=ligne_s; //fichierprim_h est l'attribut hérité du non-terminal fichierprim
        while(symbole==retourligne){
          consommer(retourligne);
          ligne_s=ligne();
          fichierprim_h+="\r\n"+ligne_s;
        }
        std::string fichierprim_s=fichierprim_h; // fichierprim -> epsilon {fichierprim.s=fichierprim.h}
        fichier_s=fichierprim_s;
      }
      sortie.open(nomfichiersortie.c_str());
      sortie<<fichier_s;
      consommer(FDF);
    }
     
    /*
    ligne -> caractere {ligneprim.h = caractere.s } ligneprim {ligne.s=ligneprim.s}
          -> epsilon {ligne.s=""}
    ligneprim -> caractere {ligneprim1.h = ligneprim.h + caractere.s} ligneprim1 {ligneprim.s = ligneprim1.s}
              -> epsilon { ligneprim.s = ligneprim.h }
    */
     
    std::string syntaxique::ligne(){
      std::string ligne_s;
      if(symbole==caractere){
        std::string caractere_s=lexeme;
        consommer(caractere);
        std::string ligneprim_h=caractere_s;
        while(symbole==caractere){
          caractere_s=lexeme;
          consommer(caractere);
          ligneprim_h+=caractere_s;
        }
        std::string ligneprim_s=ligneprim_h;
        ligne_s=ligneprim_s;
      }
      else
        ligne_s="";
      return ligne_s;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $ xxd iso-8859-1.txt 
    00000000: e90a e80a ff0a e00a
    $ ./a.out iso-8859-1.txt resultat
    $ xxd resultat
    00000000: e90d 0ae8 0d0a ff0d 0ae0 0d0a

Discussions similaires

  1. Réponses: 0
    Dernier message: 24/09/2022, 18h23
  2. Réponses: 3
    Dernier message: 10/01/2014, 11h18
  3. idée pour un programme qui lit le code source
    Par snoopo dans le forum Langage
    Réponses: 3
    Dernier message: 20/07/2010, 10h24

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