Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I'm in the process of creating a compiler for a relatively simple language using Flex and Bison on Windows. However the compiler is telling me thatthe functions yyerror and yyparse weren't declared in the right scope. After some reading I found out that the problem is apparently conflicting C and C++ linkage (I'm using g++ as I'm trying to build an abstract syntax tree). Code excerpts below.

monty.y:

extern "C" { int yyparse(); int yylex(void); void yyerror(char *s){} int yywrap(void){return 1;} #include <stdio.h> #include <string.h> #include "ast\ast.h" using namespace std; Program* root; //extern int yyparse(); main() { yyparse();

monty.l:

#include <stdlib.h> #include "ast/ast.h" #include "y.tab.h" "do" { puts("DO"); return DO; } "else" { puts("ELSE"); return ELSE; } "end" { puts("END"); return END; } "if" { puts("IF"); return IF; } etc... int main(void) yyparse(); return 0;

Any help or enlightenment as to the source of these errors would be greatly appreciated :)

The code in a .y file that's enclosed in %{ ... }% is copied verbatim to the top of the generated parser file before the definitions of the autogenerated functions like yyparse . As a result, the code that you've written, including the definition of main and the call to yyparse , appear before any of those functions are declared or defined. This may be the source of your error.

Remember that the generated parser file doesn't have to contain main . In fact, you might want to consider creating a separate C++ source file that contains main . You'd then have that file include the autogenerated header so that it sees the declaration of yyparse .

Additionally, if you are trying to write C++ code for this program, note that the main function you declared in the bison source file is not valid C++ because it doesn't have a return type declared. All C++ main functions must explicitly return an int .

Also notice that you have two main functions, one in the lexer file and one in the parser file, which will cause problems for you going forward. Factoring out your main function into its own separate file that then includes the lexer and parser header files will resolve this issue.

Finally, note that if you are indeed generating C++ code, there's no need to put void in the parameter list to main . C++ assumes that an empty parameter list means "takes no parameters" and there's no need to state otherwise.

As a follow-up, what do you mean by the lexer and parser header files? As far as my understanding goes I have monty.l and monty.y - are you saying that I should also write, for example, lexer.h and parser.h? What would these even contain? user6290240 Jul 3, 2016 at 5:51

There is no need to declare yyerror and yyparse as extern "C" if you compile your flex file as C++.

In fact, there is no need to declare yyerror and yyparse as extern "C" unless you refer to them from a different module . You do refer to yyparse in the main() in your flex file, but you also have a main() in your bison file, and you only need one main() . There is no indication that you call yyerror() from your flex file, and in general it is not a good idea IMHO. But if you do call yyerror and yyparse from your flex file, you will need to declare them in that file. And if you are compiling the flex-generated scanner as C++, then the declaration in your bison file as extern "C" will actually create a problem rather than solving one.

In short:

  • extern "C" is rarely the correct solution to any bison/flex problem.

  • flex-generated scanners can be compiled with a C++ compiler even if they are generated as C files. The same is true of bison-generated parsers, although there are more use cases in which generating a C++ parser is useful.

  • You will make your life easier if you compile both your scanner and your parser with the same language.

  • Sorry, but all attempts to do that fail. I get the same error 'yylex()' undefined at compile time. I have tried many bison options, all fail. Nothing defines yylex() and yet it is used. Doug Royer Jan 28, 2022 at 1:19 If that doesn't work, and you can't find a relevant answered question, please do not hesitate to ask a new question, with a minimal reproducible example . rici Jan 28, 2022 at 2:06 Undefined external symbols (as opposed to undeclared symbols) are flagged by the linker, not the compiler. Make sure your link command includes both the parser and the lexer. Other than that, name mangling can be an issue; I stand by the advice here that it is easiest if you compile everything in the same language and avoid extern "C" rici Jan 28, 2022 at 2:16 Well, as you can tell from the actual quoted text, it is from the COMPILER. Confused as to why "undefined at compile time" would make you think linker. Doug Royer Mar 12, 2022 at 1:54 @doug: I don't see any quoted text in your comment, and I don't know of a C compiler which issues the error message func() undefined at compiler time , so I assumed that you were paraphrasing some error message you saw. It's pretty common for people to confuse linker and compiler error messages, so I added that comment in case it was relevant. If you asked an actual question and included actual details in the form of an minimal reproducible example , it would be much easier to construct an answer without guesswork, and I would be happy to try. rici Mar 12, 2022 at 2:26

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question . Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers .