Bonjour,

Je suis débutant dans l'utilisation des outils Bison et Flex et je rencontre certaines erreurs. Je souhaiterais donc que vous puissiez m'aider à les résoudre. Alors, j'ai suivi quelques tutoriels pour essayer de comprendre comment on utilisait ces outils. J'ai lu la documentation. Malgré ça, je rencontre toujours des problèmes. Je vais fournir le code pour une meilleur compréhension de mon problème.
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
 
#ifndef LEXICAL_ANALYSOR_H
 #define LEXICAL_ANALYSOR_H
 #include "parserstate.h"
 
 // Flex expects the signature of yylex to be defined in the macro YY_DECL, and
 // the C++ parser expects it to be declared. We can factor both as follows.
 
 #ifndef YY_DECL
 
 #define YY_DECL                                        \
     yy:GnouParser::Parser::token_type                     \
     yy::GnouParser::Scanner::lex(                          \
     yy::GnouParser::Parser::semantic_type* yylval,         \
     yy::GnouParser::Parser::location_type* yylloc          \
     )
 #endif
 /* Scanner is a derived class to add some extra function to the scanner
 * class. Flex itself creates a class named yyFlexLexer, which is renamed using
 * macros to ExampleFlexLexer. However we change the context of the generated
 * yylex() function to be contained within the Scanner class. This is required
 * because the yylex() defined in ExampleFlexLexer has no parameters.*/
 
class Scanner : public yyFlexLexer
 {
    public:
     /* Create a new scanner object. The streams arg_yyin and arg_yyout default
      * to cin and cout, but that assignment is only made when initializing in
      * yylex().*/
 
      Scanner(std::istream* arg_yyin = 0, std::ostream* arg_yyout = 0);
      /* Required for virtual functions*/
       virtual ~Scanner(); 
 
		/* This is the main lexing function. It is generated by flex according to
		* the macro declaration YY_DECL above. The generated bison parser then
		* calls this virtual function to fetch new tokens.*/
       virtual yy::GnouParser::token_type lex( yy::GnouParser::semantic_type* yylval, yy::GnouParser::location_type* yylloc);
      /* Enable debug output (via arg_yyout) if compiled into the scanner.*/
       void set_debug(bool b);
 };
 
 
#endif // LEXICAL_ANALYSOR_H
Voilà, le .h du lexer.

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
 
#ifndef __GRAMMAIRE_H__
 #define __GRAMMAIRE_H__
 
 #include "filemanagement.h"
 #include "parserstate.h"
 #include "component.h"
 #include <iostream>
 #include <fstream>
 #include <string>
 
 int yylex_init(void **);
 int yylex_destroy(void *);
 void yyset_extra(FileManagement*, void *);
 int yylex(void *lvalp, void *llocp,ParserState*);
 int yyparse(ParserState*);
 
 int file_validation(FileManagement *, void *);
 
#endif
Voilà, le .h du "parser".

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
 
%{
  #include <stdio.h>
  #include <ctype.h>
  #include <string.h>
  #include <math.h>
 
  #include "grammaire.tab.hpp"
  #include "grammaire.h"
  #include "lexical_analysor.h"
 
  /* Those warnings are because of flex... not our realm... */
  #pragma GCC diagnostic ignored "-Wunused-parameter"
 
  typedef yy::GnouParser::token token;
%}
 
%{
  #define YY_USER_ACTION yylloc->first_line=yylloc->last_line=yylineno;
  #define YY_USER_INIT yyout =
  #define YY_INPUT(buf, result, max_size) \
      result = yy_input_proc(buf, max_size, yyscanner)
 
  #define YY_EXTRA_TYPE FILE*
  FILE *yyget_extra(void * scanner);
 
 // #define YY_DECL int yylex(yy::GnouParser::semantic_type* yylval, \
  //yy::GnouParser::location_type* yylloc);
 
  int yy_input_proc(char *buf, int size, void * yyscanner)
  {
      FILE *infile = yyget_extra(yyscanner);
      if (infile == NULL)
          return 0;
      return fread(buf, 1, size, (FILE *) infile);
  }
 
%}
 
%option yylineno
%option noyywrap nounput noinput
%option batch
 
%x COMMENT expect
 
%%
 
"//"                             { BEGIN (COMMENT); }
<COMMENT>.                     {                                        };
<COMMENT>[\n]                  { BEGIN (INITIAL); return yytext[0];     }
 
[_a-zA-Z][_0-9a-zA-Z]*         { yylval->text = (char *) strdup(yytext) ;
                                   return PARAMETER;                    }
 
"\new_component"............... return COMPONENT_TAG;
 
expect-floats                   BEGIN (expect) ;
<expect>[0-9]+"."[0-9]+        { yyval->activity = atof(yytext);
                                  return VALUE;                         }
<expect>[\n,' ']               { BEGIN (INITIAL) ;                      }
 
[ \t]*                         { /* Space are ignored */                };
 
<<EOF>>                         return (0);
 
.                              { fprintf(stderr, "Error!\n") ; abort() ;}
 
%%
 
namespace GnouParser
{
 
    Scanner::Scanner(std::istream* in, std::ostream* out) : ExampleFlexLexer(in, out)
    {
    }
 
    Scanner::~Scanner()
    {
    }
 
    void Scanner::set_debug(bool b)
    {
       yy_flex_debug = b;
    }
 
}
 
/* This implementation of ExampleFlexLexer::yylex() is required to fill the
 * vtable of the class ExampleFlexLexer. We define the scanner's main yylex
 * function via YY_DECL to reside in the Scanner class instead. */
 
#ifdef yylex
#undef yylex
#endif
 
int yyFlexLexer::yylex()
{
    std::cerr << "in yyFlexLexer::yylex() !" << std::endl;
    return 0;
}
 
/* When the scanner receives an end-of-file indication from YY_INPUT, it then
 * checks the yywrap() function. If yywrap() returns false (zero), then it is
 * assumed that the function has gone ahead and set up `yyin' to point to
 * another input file, and scanning continues. If it returns true (non-zero),
 * then the scanner terminates, returning 0 to its caller. */
 
int yyFlexLexer::yywrap()
{
    return 1;
}
Voilà, le .l du lexer.

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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
 
%language "C++"
%defines
%locations
 
%define parser_class_name "GnouParser"
 
%code requires
{
    #include "aggregate.h"
    #include "component.h"
    #include "couple.h"
    #include "filemanagement.h"
    #include "parserstate.h"
    #include "transition.h"
    #include "componentterm.h"
}
 
%{
   #include "grammaire.h"
   #include <iostream>
 
   struct YYLTYPE;
   int yyerror(FileManagement *f, struct YYLTYPE *loc, const std::string message);
 
%}
 
%error-verbose
 
%union 
{
   double activity;
   char* variable_name;
   char* component_tag;
}
 
%token <activity> VALUE
%token <variable_name> PARAMETER
%token <component_tag> COMPONENT_TAG
 
%parse-param { ParserState *p }
%parse-param { std::list<std::string> string_list }
%parse-param { std::list<ComponentTerm> component_term }
%parse-param { Transition *transition }
%parse-param { Couple *couple }
 
%initial-action
{
    string_list = std::list<std::string>();
    component_term = std::list<ComponentTerm>();
    transition = new Transition();
    couple = new Couple();
    p = new ParserState();
}
 
%{
    extern int yylex(yy::GnouParser::semantic_type* yylval,
       yy::GnouParser::location_type* yylloc);
 
%}
 
%%
 
input:
        /* empty */
        | input line
     ;
 
line:   '\n'
        | expression '\n'
        | equation '\n'
        | tag_field '\n'
        | error '\n'                  { yyerrok;                               }
     ;
 
expression:
        PARAMETER '=' VALUE ';'       { p->get_activity_list()[$1] = $3;  }
        | PARAMETER '=' type ';'      { component_term.clear();
        transition = new Transition($1, component_term) ;
        p->get_component_list().end()->add_transition(*transition);}
     ;
 
type:
        couple'.'PARAMETER            {
                         component_term.push_back(ComponentTerm(*couple, $3)); }
        | type '+' couple'.'PARAMETER {
                         component_term.push_back(ComponentTerm(*couple, $5)); }
     ;
 
couple:
        '(' PARAMETER ',' PARAMETER ')' { string_list.clear();
              string_list.push_back($4) ; couple = new Couple($2,string_list); }
        | '(' PARAMETER ',' product ')' { string_list.clear();
                                          couple = new Couple($2,string_list); }
     ;
 
product:
        PARAMETER '*' PARAMETER       { string_list.clear();
                         string_list.push_back($1); string_list.push_back($3); }
     ;
 
tag_field:
        COMPONENT_TAG                 {
                         p->get_component_list().push_back(Component()) ; }
     ;
 
equation: 
        term_1 aggregat term_2      {           /* Nothing to do */            }
        | PARAMETER                 {           /* Nothing to do */            }
     ;
 
term_1:
        '(' equation_term_1 ')'     {           /* Nothing to do */            }
        | PARAMETER                 {           /* Nothing to do */            }
     ;
 
term_2:
        '(' equation_term_2 ')'     {           /* Nothing to do */            }
        | PARAMETER                 {           /* Nothing to do */            }
     ;
 
equation_term_1:
        term_1 aggregat term_2 {  }
        | PARAMETER                 {           /* Nothing to do */            }
     ;
 
equation_term_2:
        term_1 aggregat term_2 {  }
        | PARAMETER                 {           /* Nothing to do */            }
     ;
 
aggregat:
        '<' word_list '>'           {           /* Nothing to do */            }
     ;
 
word_list:
        /* empty */                 {                                          }
        | PARAMETER                 {           /* Nothing to do */            }
        | PARAMETER ',' word_list_resume {        /* Nothing to do */          }
     ;
 
word_list_resume:
        PARAMETER ',' word_list_resume  {         /* Nothing to do */          }
        | PARAMETER                 {           /* Nothing to do */            }
     ;
 
%%
 
int file_validation(FileManagement *f,ParserState *p)
{
    int res;
    void* yyscanner = p->get_scanner();
    yylex_init(&yyscanner);
    yyset_extra(f, yyscanner);
    res = yyparse(p);
    yylex_destroy(yyscanner);
 
    return (!res);
}
 
 
namespace yy
{
    void GnouParser::error(const location& loc, const std::string& message)
    {
        std::cerr << "Error at " << loc << ": " << message << std::endl;
    }
}
Voilà, le y de la grammaire.

J'explique mon problème, alors la compilation avec bison et flex. Aucun problème n'apparait. Cependant, lors de l'édition de liens, donc lorsque j'utilise "grammaire.ypp" et "lexical_analysor.yy.cpp" j'ai ces erreurs qui apparaissent.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
 
bison -d -v grammaire.ypp
flex -o lexical_analysor.yy.cpp lexical_analysor.l
cc -o -Wall -W -pedantic -O0  -g grammaire.tab.cpp test.cpp lexical_analysor.yy.cpp componentterm.cpp component.cpp couple.cpp filemanagement.cpp parserstate.cpp aggregate.cpp transition.cpp
In file included from lexical_analysor.l:9:
lexical_analysor.h:24: error: expected class-name before ‘{’ token
lexical_analysor.yy.cpp:748: error: expected constructor, destructor, or type conversion before ‘:’ token
make: *** [Projet_PEPA] Erreur 1
Pour essayer de résoudre le problème, j'ai essayé de changer le langage de sortie et donc, j'ai refais le parser pour que ça sortie soit en C. Une erreur est aussi survenue... Voici le code :

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
 
%{
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
 
#include "builds.h"
#include "parser.tab.h"
 
/* Those warnings are because of flex... not our realm... */
#pragma GCC diagnostic ignored "-Wunused-parameter"
%}
 
%{
#define YY_USER_ACTION yylloc->first_line=yylloc->last_line=yylineno;
 
#define YY_INPUT(buf, result, max_size) \
      result = yy_input_proc(buf, max_size, yyscanner)
 
#define YY_EXTRA_TYPE FILE*
FILE *yyget_extra(yyscan_t scanner);
 
int yy_input_proc(char *buf, int size, yyscan_t yyscanner)
{
    FILE *infile = yyget_extra(yyscanner);
    if (infile == NULL)
        return 0;
    return fread(buf, 1, size, (FILE *) infile);
}
 
%}
 
%option reentrant
%option yylineno
%option noyywrap nounput noinput
%option bison-bridge bison-locations
 
%x COMMENT expect
 
%%
 
"//"                             { BEGIN (COMMENT); }
<COMMENT>.                     {                                        };
<COMMENT>[\n]                  { BEGIN (INITIAL); return yytext[0];     }
 
[_a-zA-Z][_0-9a-zA-Z]*         { yylval->variable_name = string_duplicate(yytext);
                                   return PARAMETER;                    }
 
"\new_component"............... return COMPONENT_TAG;
 
expect-floats                   BEGIN (expect) ;
<expect>[0-9]+"."[0-9]+        { yylval->activity = atof(yytext);
                                  return VALUE;                         }
<expect>[\n,' ']               { BEGIN (INITIAL) ;                      }
 
[ \t]*                         { /* Space are ignored */                };
 
<<EOF>>                         return (0);
 
.                              { fprintf(stderr, "Error!\n") ; abort() ;}
 
%%
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
 
#ifndef __PARSER_H__
 #define __PARSER_H__
 
 #include "builds.h"
 
 #define YYLEX_PARAM (parser)->yyscanner
 typedef struct ParserState
 {
    void *yyscanner;
    ComponentList* component_list;
    PairList* pair_list;
 } ParserState;
 
 
 int yylex_init(void **);
 int yylex_destroy(void *);
 void yyset_extra(FILE *, void *);
 int yylex(void *lvalp, void *llocp, ParserState *);
 
 int parser_parse(FILE *infile, ParserState *parser);
 void parser_push_component(ParserState *parser);
 
 /*int yyparse(ParserState *parser); */
#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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
 
%code requires
{
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
#include "parser.h"
#include "builds.h"
 
struct YYLTYPE;
int yyerror(struct YYLTYPE *llocp, ParserState *parser, const char *msg);
 
#define YY_DECL int yylex(void *lvalp, void *llocp, ParserState *);
 
extern StringList* string_list ;
extern ComponentTermList* component_term ;
extern ComponentTermList* temp_c ;
extern TransitionParser transition ;
extern CoupleParser couple ;
}
 
%error-verbose
%locations
%pure-parser
%debug
 
%union 
{
   double activity;
   char* variable_name;
   char* component_tag;
}
 
%token <activity> VALUE
%token <variable_name> PARAMETER
%token <component_tag> COMPONENT_TAG
 
%parse-param { ParserState *parser }
 
%%
 
input:
        /* empty */
        | input line
     ;
 
line:   '\n'
        | expression '\n'
        | equation '\n'
        | tag_field '\n'
        | error '\n'                  { yyerrok;                               }
     ;
 
expression:
        PARAMETER '=' VALUE ';'       { 
                    parser->pair_list = add_element_pair(parser->pair_list, $1, $3);}
        | PARAMETER '=' type ';'      { transition.name = $1;
        temp_c = component_term;
        while(temp_c != NULL)
        {
            transition.component_term_list = add_element_component_term(transition.component_term_list, temp_c->value);
            temp_c = temp_c->next;
        }
        parser->component_list->value.transition_list = 
        add_element_transition(parser->component_list->value.transition_list, transition);
        component_term = empty_list_component_term(component_term);
                                      }
     ;
 
type:
        couple'.'PARAMETER            {
                    ComponentTermParser t; t.transition_name = $3;
                    equalCouple(&t.couple, couple);
                    component_term = add_element_component_term(component_term, t);}
        | type '+' couple'.'PARAMETER {
                    ComponentTermParser t; t.transition_name = $5;
                    equalCouple(&t.couple, couple);
                    component_term = add_element_component_term(component_term, t); }
     ;
 
couple:
        '(' PARAMETER ',' PARAMETER ')' { couple.action = $2; 
                                          couple.activity[0] = $4; }
        | '(' PARAMETER ',' product ')' { couple.action = $2;
                                couple.activity[0] = string_list->value;
                        couple.activity[1] = string_list->next->value;  }
     ;
 
product:
        PARAMETER '*' PARAMETER       { string_list = empty_list_string(string_list);
                         string_list = add_element_string(string_list, $1); 
                         string_list = add_element_string(string_list, $3); }
     ;
 
tag_field:
        COMPONENT_TAG                 { }
     ;
 
equation: 
        term_1 aggregat term_2      {           /* Nothing to do */            }
        | PARAMETER                 {           /* Nothing to do */            }
     ;
 
term_1:
        '(' equation_term_1 ')'     {           /* Nothing to do */            }
        | PARAMETER                 {           /* Nothing to do */            }
     ;
 
term_2:
        '(' equation_term_2 ')'     {           /* Nothing to do */            }
        | PARAMETER                 {           /* Nothing to do */            }
     ;
 
equation_term_1:
        term_1 aggregat term_2 {  }
        | PARAMETER                 {           /* Nothing to do */            }
     ;
 
equation_term_2:
        term_1 aggregat term_2 {  }
        | PARAMETER                 {           /* Nothing to do */            }
     ;
 
aggregat:
        '<' word_list '>'           {           /* Nothing to do */            }
     ;
 
word_list:
        /* empty */                 {                                          }
        | PARAMETER                 {           /* Nothing to do */            }
        | PARAMETER ',' word_list_resume {        /* Nothing to do */          }
     ;
 
word_list_resume:
        PARAMETER ',' word_list_resume  {         /* Nothing to do */          }
        | PARAMETER                 {           /* Nothing to do */            }
     ;
 
%%
 
int yyerror(struct YYLTYPE *loc, ParserState *state, const char *s)
{
    (void) state;
    fprintf (stderr, "Error:%d:%d %s\n", loc->first_line, loc->first_column, s);
    return 0;
}
 
int parser_parse(FILE *infile, ParserState *parser)
{
    int res;
 
    yylex_init(&parser->yyscanner);
    yyset_extra(infile, parser->yyscanner);
    res = yyparse(parser);
    yylex_destroy(parser->yyscanner);
 
    return res;
}
Et le code d'erreur est :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
 
cc -o -std=c99 -Wall -W -pedantic -D_POSIX_C_SOURCE=200809L -O0 -g parser.tab.c lexer.yy.c parser_main.c
lexer.yy.c:780: error: expected identifier or(’ before ‘{’ token
make: *** [Parser] Erreur 1
J'ai fais des essais pour corriger pour le parser en C ou en C++ mais sans succès.
En espèrant que vous pourrez m'aider. Merci d'avance.