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

Générateurs de compilateur Discussion :

Lex et Yacc soucis de recuperation de valeur


Sujet :

Générateurs de compilateur

  1. #1
    Membre du Club
    Lex et Yacc soucis de recuperation de valeur
    Bonjour,

    Je suis en train de concevoir un d'analyseur lexical devant accepter l’équivalent de l’opérateur IN en SQL. Ainsi une phrase doit avoir la syntaxe suivante :
    1. "un_mot.un_mot IN " ou "un_mot IN"
    2. Suivi d'une parenthèse ouvrante et fermante comprenant une liste de mot entre guillemet séparé par une virgule

    Ceci correpond a la ligne 25 du fichier sql.y
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    CHAMP_NAME IN PARENTHESEG LISTE_IN PARENTHESED


    Mon analyseur détecte bien les bonnes des mauvaises phrases, cependant il "bug" toujours de la même manière : si pour CHAMP_NAME je précise une valeur sans point alors c est le contenu des parenthèse qui m'est retourné quand je fait $1 (ligne 26 et 27)

    voici mes 2 phrase de test :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    mot1.mot2 in ("aa", "bb", "cc")
    mot1 in ("aa", "bb", "cc")


    Voici intégralité de mes 2 fichiers

    sql.l
    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
    %option noyywrap
    %{
     
    #include "sql.h"
    #include <stdlib.h>
     
    %}
     
    chiffre   [0-9]
    entier    {chiffre}+
    exposant  [eE][+-]?{entier}
    valeur    {entier}("."{entier})?{exposant}?
     
    variable  [a-zA-Z_0-9]+
     
     
    %%
    [ \t\n]
     
    ("in"|"IN")				return IN;
    "."	return POINT;
    ("\""|"'")		return GUILLEMET;
    "("			return PARENTHESEG;
    ")"			return PARENTHESED;
    ","			return COMMA;
     
    {valeur}    {
    	yylval.var=(char*)_strdup(yytext);
        //printf("Valeur found: %s\n", yylval.var);
    	return(VALEUR);
        }
     
    {variable}    {
    	yylval.var=(char*)_strdup(yytext);
        //printf("Variable found: %s\n", yylval.var);
    	return(VARIABLE);
        }


    sql.y
    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
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    %{
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    %} 
     
    %union { 
        double val;
        char* var;
    }
    // ce que transmet lex
    %token  <var> VALEUR
    %token  <var> VARIABLE IN POINT GUILLEMET
    %token  <var> PARENTHESEG PARENTHESED COMMA
     
    // combinaison de plusieur %token
    %type  <var> CHAMP_NAME
    %type  <var> LISTE_IN
     
    %start PHRASE;
    %%
     
    PHRASE:
    CHAMP_NAME IN PARENTHESEG LISTE_IN PARENTHESED{
        printf("CHAMP_NAME = %s\n", $1);
        printf("LISTE_IN   = %s\n\n", $4);
    };
     
    CHAMP_NAME:
            VARIABLE
            {
                strcpy($$, $1);
            }          
     
        |   VARIABLE POINT VARIABLE
            {
                strcpy($$, $1);
                strcat($$, ".");
                strcat($$, $3);
            }
            ;
     
    LISTE_IN :
            GUILLEMET VARIABLE GUILLEMET
            {
                strcpy($$, "\"");
                strcat($$, $2);
                strcat($$, "\"");
            }
        |   VALEUR
            {
                strcpy($$, $1);
            }
     
        |   LISTE_IN COMMA GUILLEMET VARIABLE GUILLEMET
            {
                strcpy($$, $1);
                strcat($$, ", ");
                strcat($$, "\"");
                strcat($$, $4);
                strcat($$, "\"");
            }
        |   LISTE_IN COMMA VALEUR
            {
                strcpy($$, $1);
                strcat($$, ", ");
                strcat($$, $3);
            }        
        ;
    %%
     
    int yyerror(char *s) {
        printf("%s\n",s);
        system("pause");
    }
     
    int main(void) {
     
        int choix = 0;
     
        printf("\n1 : saisies au clavier\n");
        printf("2 : Analyser le fichier req.txt\n\n");
        printf("Votre choix : ");
     
        scanf("%d",&choix);
        printf("\n\n");
     
        if (choix == 2)
        {
            FILE *file_IN;
            char ligne[512];         
            file_IN = fopen ("req.txt", "r");
     
            if( file_IN != NULL)
            {
                while(fgets(ligne, 512, file_IN) != NULL)
                    if(strlen(ligne) > 3) // saute les ligne vide exemple : \n\r\0
                    {
                        yy_scan_string(ligne);
                        yyparse () ;
                    }
                fclose(file_IN);
            }
        }
     
        else if (choix == 1)
            yyparse();
        else
            printf("\nChoix incorrect\n");
     
        system("pause");
    }


    mon bat pour compiler
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    bison --defines=sql.h sql.y -o sql.y.c
    flex --outfile=sql.lex.c sql.l
    gcc -c sql.lex.c -o sql.lex.o
    gcc -c sql.y.c -o sql.y.o
    gcc -o sql sql.lex.o sql.y.o
     
    pause
     
    del sql.h
    del sql.lex.c
    del sql.lex.o
    del sql.y.c
    del sql.y.o


    J'ai retourné mon code dans tout les sens et je ne trouve pas d’où vient mon erreur. Auriez vous une idée pour corriger ce programme ?

  2. #2
    Membre actif
    proposition
    => c'est du code (f)lex\Bison n'est ce pas ?
    => Quand je regarde ta grammaire(j'ai construit un automate avec ta grammaire qui reconnait ton expression en sql) et ton analyse lexicale me paraissent bonnes ,ce que je te conseille c'est de verifier s'il n'y a pas un problème de syntaxe :
    => regarde si c'est un problème de syntaxe sinon
    =>formalise ta grammaire analytiquement et construit une table d'analyse SLR(1) pour voir si l'analyseur reconnait ta grammaire

  3. #3
    Membre du Club
    Oui c est bien du flex / bison, il détecte les bonnes des mauvaises phrases, mais quand je souhaite afficher un morceau de la phrase il ne m affiche pas toujours ce qu il devrait et je ne comprend pas pourquoi

  4. #4
    Expert éminent sénior
    Euh, il est alloué quand, le var, pour les combinaisons de tokens?

    Je vois bien où il est alloué quand on crée un token, mais pour CHAMP_NAME, où est-il alloué?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

###raw>template_hook.ano_emploi###