Search code examples
c++bisonflex-lexer

yyparse() not declared in Bison/Flex C++ project only for some version of gcc/bison/flex


First of all I'm pretty new to Bison and Flex. I know those tools were designed to be used in C and I have a feeling all of my problem comes from using them in C++. I'm not sure I've done it the right way.

The code compiles fine on my computer but doesn't on my university server. I've isolated the issue to post here.

At my university:

$ (g++ --version; bison --version; flex --version)|grep '[0-9]\.'
g++ (Debian 4.4.5-8) 4.4.5
bison (GNU Bison) 2.4.1
flex 2.5.35

At home:

HOME $ (g++ --version; bison --version; flex --version)|grep '[0-9]\.'
g++ (GCC) 4.7.1 20120721 (prerelease)
bison (GNU Bison) 2.6.2
flex 2.5.37

I use the following command to compile: bison -d parse.y && flex lex.l && g++ main.cpp lex.yy.c parse.tab.c -lfl

As I already said, it compiles fine (no warnings) on my computer but I get this on the server:

main.cpp: In function 'int main()':
main.cpp:28: error: 'yyparse' was not declared in this scope

Since SO has some problem with brackets, I've also uploaded a tarball.

lex.l

%{
#include 
#include "dict.hpp"
#include "parse.tab.h"
%}

%%

[0-9]+  yylval.num = atoi(yytext); return NUM;
[a-z]+  yylval.id = dict.id(yytext); return ID;
[:space:]   ;

parse.y

%{
#include 
#include "dict.hpp"
void yyerror (const char* e) {
    puts(e);
}
int yylex ();
%}

%union{
    uint id;
    int num;    
}

%token ID;
%token NUM;

%%

S : ID NUM S {
        dict.set($1, $2);
    }
|;

dict.hpp

#ifndef _DICT_HPP_
#define _DICT_HPP_
#include 
#include 

typedef std::pair dpair;
typedef unsigned int uint;

class Dict {
    std::vector tab;
public:
    uint id(char* s);
    void set(uint i, int v);
    void print();
};

extern Dict dict;

#endif /* _DICT_HPP_ */

main.cpp

#include <vector>
#include <string>
#include <cstdio>
#include "dict.hpp"
#include "parse.tab.h"

Dict dict;

uint Dict::id (char* s) {
    for(uint i = 0; i < tab.size(); i++)
        if(tab[i].first == s)
            return i;
    tab.push_back(dpair(std::string(s), tab.size()));
    return tab.size()-1;
}

void Dict::set (uint i, int v) {
    tab[i].second = v;
}

void Dict::print () {
    for(uint i = 0; i < tab.size(); i++)
        printf("%20s = %d\n", tab[i].first.c_str(), tab[i].second);
}

int main ()
{
    yyparse();
    dict.print();
}

OFFTOPIC: flex is not a GNU software.


Solution

  • You could add

     extern "C" int yyparse (void);
    

    in your main.cpp file (and perhaps also in parser.y) or in some common #include-d header file.

    And you really should use g++ -Wall -Wextra -g to compile your code (or the parser generated C++ code).

    Consider also using other C++ compatible open source parser generators, like bisonc++ or carburetta or ANTLR.