|
Invité de passage
Inscription : juin 2012 Messages : 1 Détails du profil  Informations forums : Inscription : juin 2012 Messages : 1 Points : 0 Points : 0
|
[Flex/Bison] Aide pour l'utilisation des outils Bison et Flex
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 :
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 :
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 :
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 :
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 :
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 :
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 :
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 :
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 :
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.
|