2
votes

I'm working with Flex and Bison in C++. I am learning to use these tools and the best way to start is by performing a simple calculator. Once generated the application (the executable) from my calc.y and calc.l files, I can run the .exe file and use it, but now I want to include it in a file c ++ to use it in my application but I can't. I think it's my fault because I'm including bad the generated file or generating bad code to import.

main.cpp

#include <iostream>

extern "C" {
    #include "y.tab.h"
}

int main ( int argc, char *argv[] ) {
    yyparse();
    printf(elementos);
    return 0;
}

calc.l

%{
#include "y.tab.h"
#include <stdlib.h>
void yyerror(char *);
%}

%%

[0-9]+  {
    yylval = atoi(yytext);
    return INTEGER;
}

[-+()\n]    {
    return *yytext;
}

[ \t]   ;

.       {
    yyerror("Invalid character.");
}

%%

int yywrap(void) {
    return 1;
}

calc.y

%{
    #include <stdio.h>
    int yylex(void);
    void yyerror(char *);
    int sym[26];
    int elementos = 0;
%}

%token INTEGER VARIABLE
%left '+' '-'
%left '*' '/'

%%

program:
        program expr '\n' { printf("%d\n", $2 ); }
    |
;

statement:
        expr                { printf("%d\n", $1); }
    |   VARIABLE '=' expr   { sym[$1] = $3; }
;

expr:
        INTEGER             { $$ = $1; }
    |   expr '+' expr       { $$ = $1 + $3; elementos = elementos + 1;}
    |   expr '-' expr       { $$ = $1 - $3; }
    |   expr '*' expr       { $$ = $1 * $3; }
    |   expr '/' expr       { $$ = $1 / $3; }
    |   '(' expr ')'        { $$ = $2; }
;

%%

void yyerror(char *s) {
    fprintf(stderr, "%s\n", s);
}


int main(void) {
    yyparse();
    return 0;
}

The y.tab.h is generated by bison. When I'm trying to compile main.cpp I'm getting an error:

command: gcc main.cpp -o main.exe

result: main.cpp: In function 'int main(int, char**)': main.cpp:8:10: error: 'yyparse' was not declared in this scope main.cpp:9:9: error: 'elementos' was not declared in this scope

How can I fix it?

I'm using gcc version 4.7.2, bison 2.4.1 and 2.5.4 on windows 8.1.

Thanks!

EDIT:

The y.tab.h file is:

/* Tokens.  */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
   /* Put the tokens into the symbol table, so that GDB and other debuggers
      know about them.  */
   enum yytokentype {
     INTEGER = 258,
     VARIABLE = 259
   };
#endif
/* Tokens.  */
#define INTEGER 258
#define VARIABLE 259




#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef int YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
#endif

extern YYSTYPE yylval;

There's not a "elementos" variable, but looking in the generated y.tab.c file, I found that there is defined!

1
You can also generate a c++ parser with bison. - Iharob Al Asimi
Why don't you post the y.tab.h file? - Iharob Al Asimi
IIRC, for lex&yacc, you need to generate some *.c from your lex and yacc files, and compile it with your main file. Do you use flex and bison to parse your *.l and *.y and got the corresponding *.c files for parsing? yyparse and elementos will defined in these auto-generated c files. - Yan An

1 Answers

2
votes

You have a number of problems:

  1. Bison and Flex generate C code, which you then need to compile and link with your program. Your question shows no indication that you have done this.

  2. If you want to be able to use the elementos variable in your main.cpp file, then you need to declare it. It may be defined somewhere else, but the compiler doesn't know that when it compiles main.cpp. Add this line inside the extern "C" part: extern int elementos;

  3. You have two different main functions.

  4. In main.cpp, you #include iostream, but then use printf from stdio.

  5. The call to printf is wrong. It needs a format string.

  6. Bison shows several warnings, which you probably need to read and do something about if you want your program to work.