flex et bison: g++ erreur de compilation
Je suis en train de compiler les scanner et de l'analyseur pour le jouet de la langue à l'aide de g++. Voici le code pour chaque fichier que j'utilise (si vous le souhaitez, je peux poster à pastebin
ou n'importe où ailleurs).
caesar.ll
/* Simple scanner for a Caesar language */
%{
#include "caesar.tab.h"
#include <iostream>
#include <string>
int chars = 0;
int words = 0;
int lines = 0;
%}
/* Define constants */
OWS [" "\t]*
COMMA {OWS}","{OWS}
ID [A-Za-z_][A-Za-z0-9_]*
INT ([0-9]+)|("0x"[A-Ha-h0-9]+)
FLOAT [0-9]+"."[0-9]+
BSTREAM b[\'\"].*[\'\"]
USTREAM u?[\'\"].*[\'\"]
ARRAY {LBRACE}({INT}|{FLOAT})({COMMA}({INT}|{FLOAT})){RBRACE}
LIST {LBRACKET}.*({COMMA}.*){RBRACKET}
RANGE {LBRACE}{INT}":"{INT}(":"{INT})?{RBRACE}
ARGS {ID}({COMMA}{ID})*
LPARENTHESIS "("{OWS}
RPARENTHESIS {OWS}")"
LBRACE "{"{OWS}
RBRACE {OWS}"}"
LBRACKET "["{OWS}
RBRACKET {OWS}"]"
%%
%{
/*============================================================================*/
/* Define types */
/*============================================================================*/
%}
{INT} {
cout << "int: " << yytext << endl;
yylval = atoi(yytext);
return INT;
} /* int type */
{FLOAT} {
cout << "float: " << yytext << endl;
yylval = atof(yytext);
return FLOAT;
} /* float type */
{BSTREAM} {
cout << "bstream: " << yytext << endl;
return BSTREAM;
} /* bstream type */
{USTREAM} {
cout << "ustream: " << yytext << endl;
return USTREAM;
} /* ustream type */
%{
/*============================================================================*/
/* Define operators */
/*============================================================================*/
%}
"+" { return ADD; }
"-" { return SUB; }
"*" { return MUL; }
"/" { return DIV; }
"//" { return FDIV; }
"|" { return ABS; }
"\n" { return EOL; }
%{
/*============================================================================*/
/* Define statements */
/*============================================================================*/
%}
{RANGE} {
cout << "range: " << yytext << endl;
return RANGE;
} /* range function */
%%
caesar.yy
/* Simple parser for a Caesar language */
%{
#include <iostream>
using namespace std;
%}
/* Define built-in types */
%token INT FLOAT BSTREAM USTREAM
%token ADD SUB MUL DIV FDIV ABS
%token EOL
%%
calclist: /* nothing */
| calclist exp EOL {
cout << $2 << endl;
}
| calclist EOL {
cout << ">>> ";
}
;
exp: factor
| exp ADD exp { $$ = $1 + $3; }
| exp SUB factor { $$ = $1 - $3; }
| exp ABS factor { $$ = $1 | $3; }
;
factor: term
| factor MUL term { $$ = $1 * $3; }
| factor DIV term { $$ = $1 / $3; }
;
term: INT
| ABS term { $$ = $2 >= 0? $2 : - $2; }
;
%%
main()
{
cout << ">>> ";
yyparse();
}
yyerror(char *error)
{
cerr << error;
}
Makefile
caesar: caesar.ll caesar.yy
bison -d caesar.yy
flex caesar.ll
g++ -o $@ caesar.tab.cc lex.yy.c -lfl
Quand j'essaie de le compiler en utilisant make
, je vois quelques erreurs:
bison -d caesar.yy
caesar.yy: conflicts: 3 shift/reduce
flex caesar.ll
g++ -o caesar caesar.tab.cc lex.yy.c -lfl
caesar.tab.cc: In function 'int yyparse()':
caesar.tab.cc:1281:16: error: 'yylex' was not declared in this scope
caesar.tab.cc:1470:35: error: 'yyerror' was not declared in this scope
caesar.tab.cc:1612:35: error: 'yyerror' was not declared in this scope
caesar.yy: At global scope:
caesar.yy:46:20: error: ISO C++ forbids declaration of 'yyerror' with no type [-fpermissive]
caesar.ll:3:24: fatal error: caesar.tab.h: No such file or directory
compilation terminated.
make: *** [caesar] Error 1
Pourriez-vous m'aider, s'il vous plaît? Merci!
Mise à JOUR: j'ai déjà correction d'une erreur avec les mauvais type de fonction.
- Ne même pas essayer d'y faire il compile en C++. Le C et le C++ sont deux langues distinctes.
Vous devez vous connecter pour publier un commentaire.
D'abord corriger les erreurs évidentes -- ajoutez des déclarations au sommet de césar.aa:
et types de retour pour
main
etyyerror
(remarque: j'ai aussi ajoutéconst
à l'argument de yyerror au silence des avertissements sur les littéraux de chaîne étant passé).Vous avez besoin similaire triviale à césar.ll:
Maintenant, vous pouvez voir les erreurs:
D'abord à la deuxième -- votre scanner est d'essayer de retourner un jeton de GAMME qui n'est pas défini.
Vous pouvez ajouter
%token RANGE
àcaesaer.yy
à définir, même si, comme vous ne l'utilisez pas (ou diverses autres marques commeBSTREAM
ouUSTREAM
) en grammaire, il va juste provoquer une erreur de syntaxe.Qui nous amène à la grammaire des conflits. Ce ne sont pas vraiment des erreurs (plus des mises en garde), mais vous ne voulez pas faire attention à eux. Ajouter un drapeau-v pour la
bison
commande dans leMakefile
et vous obtiendrez uncaesaer.output
fichier avec des infos sur les conflits.Le 3 conflits proviennent tous de l'état de 16, vous pouvez le voir dans le .fichier de sortie:
C'est vous dire que tous les 3 des conflits à partir de votre
exp: exp ADD exp
règle. Avoir une règle qui est à la fois de gauche et de droite récursive est toujours ambigu, mais dans ce cas, la solution est évidente -- changer deexp: exp ADD factor
, correspondant au reste de vos règles.extern "C" {int yylex(void);}
àcaesar.l
fichier etextern "C" {int yyparse(void); int yylex(void); int yywrap() { return 1; }}
àcaesar.y
fichier. Il semble que vous êtes un peu en retard, mais je pense que c'est la meilleure réponse ici. Merci pour cette explication!extern "C"
choses, mais il ne fait pas de mal (aussi longtemps que vous le faire de manière cohérente dans tous les fichiers source). flex déjà déclarerextern "C" yywrap
pour voushttp://dinosaur.compilertools.net/flex/flex_19.html Lire ceci sur la façon d'utiliser
g++
avecflex
. Le problème ici c'est que vous l'utilisez dansC
mode et il génèreC
lexers. Utilisationflex
avec-+
commutateur.%option c++
. Mais il y a encore des erreurs commeerror: 'yylex' was not declared in this scope
. Ne peut pas comprendre comment les corriger. Que diriez -shift/reduce
avertissement? Je pense que ça peut faire de ce jouet langue d'une poubelle.YYLex
etc-+
option génère un C++ scanner classe qui a une toute interface différente de celle attendue par les bisons. Vous pouvez le faire fonctionner, mais c'est beaucoup de travail. Le code de base que flex génère pas d'autre choix est parfaitement bien pour compiler comme code C++.FWIW, il est inutile de instrument votre code à la main pour voir ce que les règles sont appariés. Flex et Bison le faire pour vous, gratuitement. Voir http://westes.github.io/flex/manual/Debugging-Options.html pour le Flex, et http://www.gnu.org/software/bison/manual/bison.html#Tracing pour le Bison.