Partage
  • Partager sur Facebook
  • Partager sur Twitter

Flex problème

    2 novembre 2020 à 16:57:52

    Bonjour,

    Je crée mon language de programmation avec Flex.

    Mon fichier .lex est comme ceci :

    /*
    
    En Flex, on commence par les eventuelles declarations C que l'on met entre les balises %{ et %}.
    Entre ces balises, j'ai inclus la stdlib et la stdio de C. J'ai aussi declare 1 variable de type int.
    La variable lineno correspond au numero de ligne.
    La variable error est un booleen. Il est a true si une erreur est detectee.
    Il existe la variable globale yylineno dans Flex que l'on peut ajouter en option. C'est cense gerer le numero de ligne tout seul mais pour des raisons inexpliquees, elle ne s'incremente pas chez moi.
    Je prefere donc gerer le mecanisme de numero de ligne moi-meme.
    
    */
    
    %{
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <stdbool.h>
    void lexeme(void);
    unsigned int lineno=1;
    bool error=false;
    
    %}
    
    /*
    
    Juste apres on declare les eventuelles variables Flex. Ce sont nos terminaux associes reconnus par des expressions regulieres.
    
    */
    
    /* [[:digit:]] equivaut a [0-9] */
    
    nombre 0|[1-9][[:digit:]]*
    
    /* [[:alpha:]] equivaut a [a-zA-Z] (tout les caracteres de l'alphabet majuscules et minuscules) et [[:alnum:]] equivaut a [a-zA-Z0-9] (tout les caracteres alphanumeriques) */
    
    variable [[:alpha:]][[:alnum:]]*
    
    /*
    
    Entre les %% on ecrit toutes les actions a chaque fois que l'analyseur detectera des lexemes (terminaux) de Simple.
    On ecrit donc l'ensemble des terminaux de Simple.
    
    */
    
    %%
    
    {nombre} {
            printf("\tNombre trouve a la ligne %d. Il s'agit du nombre %s et comporte %d chiffre(s)\n",lineno,yytext,yyleng);
    }
    
    "afficher"      {lexeme();}
    
    "="             {lexeme();}
    
    "+"             {lexeme();}
    
    "-"             {lexeme();}
    
    "*"             {lexeme();}
    
    "/"             {lexeme();}
    
    "("             {lexeme();}
    
    ")"             {lexeme();}
    
    "et"            {lexeme();}
    
    "ou"            {lexeme();}
    
    "non"           {lexeme();}
    
    ";"             {lexeme();printf("\n");}
    
    "vrai"          {lexeme();}
    
    "faux"          {lexeme();}
    
    "\n"            {lineno++;}
    
     /* Si j'avais defini l'action de variable au debut, l'analyseur ne verrait plus les lexemes comme afficher ou supprimer mais comme des variables portant ce nom. L'ordre de definition des regles pour chaque lexemes n'est donc pas sans logique en Flex */
    
    {variable} {
            printf("\tVariable trouvee a la ligne %d. Il s'agit de %s et comporte %d lettre(s)\n",lineno,yytext,yyleng);
    }
    
     /* L'analyseur ne fait rien pour les espaces et tabulations */
    
    " "|"\t" {}
    
     /* Le point est tout le reste qui n'a pas ete defini precedemment. Il est donc a mettre en dernier. */
    
    . {
            fprintf(stderr,"\tERREUR : Lexeme inconnu a la ligne %d. Il s'agit de %s et comporte %d lettre(s)\n",lineno,yytext,yyleng);
            error=true;
    }
    
    
    %%
    
    /*
    
    J'ecris ici mes fonctions C apres le %%
    Ma fonction main appellera la fonction de parsing yylex() qui sera construite a la compilation de la source Flex. C'est une fonction qui parse et detecte les lexemes (non terminaux) que nous avons defini dans notre programme Flex.
    Le main n'est pas obligatoire. On peut utiliser la fonction main par defaut de Flex (qui ne fait qu'appeler yylex() seulement), il faut dans ce cas specifier main en option.
    
    */
    
    int main(){
            printf("Debut de l'analyse lexicale :\n");
            yylex();
            printf("Fin de l'analyse !\n");
            printf("Resultat :\n");
            if(error){
                    printf("\t-- Echec : Certains lexemes ne font pas partie du lexique du langage ! --\n");
            }
            else{
                    printf("\t-- Succes ! --\n");
            }
            return EXIT_SUCCESS;
    }
    
    /*
    
    La variable globale yytext contient le lexeme courant lu par l'analyseur.
    
    */
    
    void lexeme(){
            printf("\tLexeme '%s' trouve a la ligne %d\n",yytext,lineno);
    }
    
    /*
    
    La fonction yywrap() est appelee des que l'analyseur lexicale detecte le caractere EOF (End Of File). Elle doit retourner 1 pour mettre fin a l'analyse.
    Cette fonction n'est pas obligatoire. On peut utiliser la fonction yywrap() par defaut de Flex (qui ne fait que retourner 1 juste), il faut dans ce cas specifier noyywrap en option.
    
    */
    
    int yywrap(){
            printf("\tFin de fichier detecte !\n");
            return 1;
    }
    

    J'ai fait ce fichier .simple, le simple étant mon language : 

    68 afficher;
    france japon usa = 85;
    ecrire 78 et 49
    japon = 118 et afficher japon;
    vrai+faux=19;

    Je fais : flex -o lexique_simple.c lexique_simple.lex 

    Puis : gcc -o lexique_simple lexique_simple.c

    Et enfin : ./lexique_simple < programme.simple

    Ma sortie est : Debut de l'analyse lexicale :

            Nombre trouve a la ligne 1. Il s'agit du nombre 68 et comporte 2 chiffre(s)

            Lexeme 'afficher' trouve a la ligne 1

            Lexeme ';' trouve a la ligne 1

     et comporte 1 lettre(s)inconnu a la ligne 1. Il s'agit de

            Variable trouvee a la ligne 2. Il s'agit de france et comporte 6 lettre(s)

            Variable trouvee a la ligne 2. Il s'agit de japon et comporte 5 lettre(s)

            Variable trouvee a la ligne 2. Il s'agit de usa et comporte 3 lettre(s)

            Lexeme '=' trouve a la ligne 2

            Nombre trouve a la ligne 2. Il s'agit du nombre 85 et comporte 2 chiffre(s)

            Lexeme ';' trouve a la ligne 2

     et comporte 1 lettre(s)inconnu a la ligne 2. Il s'agit de

            Variable trouvee a la ligne 3. Il s'agit de ecrire et comporte 6 lettre(s)

            Nombre trouve a la ligne 3. Il s'agit du nombre 78 et comporte 2 chiffre(s)

            Lexeme 'et' trouve a la ligne 3

            Nombre trouve a la ligne 3. Il s'agit du nombre 49 et comporte 2 chiffre(s)

     et comporte 1 lettre(s)inconnu a la ligne 3. Il s'agit de

            Variable trouvee a la ligne 4. Il s'agit de japon et comporte 5 lettre(s)

            Lexeme '=' trouve a la ligne 4

            Nombre trouve a la ligne 4. Il s'agit du nombre 118 et comporte 3 chiffre(s)

            Lexeme 'et' trouve a la ligne 4

            Lexeme 'afficher' trouve a la ligne 4

            Variable trouvee a la ligne 4. Il s'agit de japon et comporte 5 lettre(s)

            Lexeme ';' trouve a la ligne 4

     et comporte 1 lettre(s)inconnu a la ligne 4. Il s'agit de

            Lexeme 'vrai' trouve a la ligne 5

            Lexeme '+' trouve a la ligne 5

            Lexeme 'faux' trouve a la ligne 5

            Lexeme '=' trouve a la ligne 5

            Nombre trouve a la ligne 5. Il s'agit du nombre 19 et comporte 2 chiffre(s)

            Lexeme ';' trouve a la ligne 5

            Fin de fichier detecte !

    Fin de l'analyse !

    Resultat :

            -- Echec : Certains lexemes ne font pas partie du lexique du langage ! --

    Je ne comprends pas...

    Merci !




    • Partager sur Facebook
    • Partager sur Twitter
      25 novembre 2020 à 13:12:50

      Tu es sous windows et tu as créé un fichier texte qui contient de \r\n pour les fins de lignes ? du coup le \r te fait revenir en début de ligne et c'est pour ça que la ligne affichée est incompréhensible …

      • Partager sur Facebook
      • Partager sur Twitter
        25 novembre 2020 à 13:38:10

        Heuuu j'ai pas compris là ? Concrétement, comment faire ?
        • Partager sur Facebook
        • Partager sur Twitter
          25 novembre 2020 à 13:42:21

          Le problème c'est apparemment les fins de lignes.

          Windows dans un fichier texte met les caractères \r\n (cr lf) comme fin de ligne, le reste des os (ou presque) met juste un \n (lf).

          du coup le plus simple est d'ignorer les caractères \r comme tu le fais pour les espaces et les tabs… ou de t'assurer qu'il n'y en a pas dans le fichier.

          • Partager sur Facebook
          • Partager sur Twitter
            25 novembre 2020 à 14:11:02

            En gros de supprimer tous les /r et /n dans le fichier c'est ça ?
            • Partager sur Facebook
            • Partager sur Twitter
              25 novembre 2020 à 14:17:37

              pas c'est plus simple de ne pas les prendre en compte lors de l'analyse, c'est important de conserver les \n car tu veux pouvoir compter le numéro de ligne

              ça tu gardes :

              "\n"            {lineno++;}


              et ça 

               /* L'analyseur ne fait rien pour les espaces et tabulations */
               
              " "|"\t" {}

              tu le modifies en 

               /* L'analyseur ne fait rien pour les espaces et tabulations et les cariage return */
               
              " "|"\t"|"\r" {}




              • Partager sur Facebook
              • Partager sur Twitter

              Flex problème

              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
              • Editeur
              • Markdown