yyparse()的未解析外部符号 [英] unresolved external symbol for yyparse()

查看:238
本文介绍了yyparse()的未解析外部符号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的main.cpp看起来像这样:

My main.cpp looks like this:

#include <assert.h>
#include <fstream>
#include <iostream>
#include "astgen.h"
#include "astexec.h"

extern int yyparse();
extern FILE *yyin;

int main()
{
    //yydebug = 0;
    struct AstElement *a = 0;
    FILE *fp ;
    fopen_s(&fp,"example.txt","r");
    //std::cout<<fp;
    if (fp==NULL)
    {
        std::cout<<"error";
    }
    yyin=fp;
    yyparse();

    assert(a);
    struct ExecEnviron* e = createEnv();
    execAst(e, a);
    freeEnv(e);
    /* TODO: destroy the AST */
}

当我尝试编译它时,出现错误:main.obj:错误LNK2019: unresolved external symbol "int __cdecl yyparse(void)" (?yyparse@@YAHXZ) referenced in function _main

When I try to compile this, I get the error: main.obj : error LNK2019: unresolved external symbol "int __cdecl yyparse(void)" (?yyparse@@YAHXZ) referenced in function _main

我是flex/bison的新手.任何帮助,将不胜感激. 如果有用的话,这里是我的parser.y文件:

I am a newbie in flex/bison. Any help would be appreciated. If it helps here is my parser.y file:

%error-verbose /* instruct bison to generate verbose error messages*/
%{
#include "astgen.h"
#define YYDEBUG 1

/* Since the parser must return the AST, it must get a parameter where
 * the AST can be stored. The type of the parameter will be void*. */
#define YYPARSE_PARAM astDest
extern int yylex();
%}

%union {
    int val;
    char op;
    char* name;
    struct AstElement* ast; /* this is the new member to store AST elements */
}

%token TOKEN_BEGIN TOKEN_END TOKEN_WHILE TOKEN_DO
%token<name> TOKEN_ID
%token<val> TOKEN_NUMBER
%token<op> TOKEN_OPERATOR
%type<ast> program block statements statement assignment expression whileStmt call
%start program

%{
/* Forward declarations */
void yyerror(const char* const message);


%}

%%

program: statement';' { (*(struct AstElement**)astDest) = $1; };

block: TOKEN_BEGIN statements TOKEN_END{ $$ = $2; };

statements: {$$=0;}
    | statements statement ';' {$$=makeStatement($1, $2);}
    | statements block';' {$$=makeStatement($1, $2);};

statement: 
      assignment {$$=$1;}
    | whileStmt {$$=$1;}
    | block {$$=$1;}
    | call {$$=$1;}

assignment: TOKEN_ID '=' expression {$$=makeAssignment($1, $3);}

expression: TOKEN_ID {$$=makeExpByName($1);}
    | TOKEN_NUMBER {$$=makeExpByNum($1);}
    | expression TOKEN_OPERATOR expression {$$=makeExp($1, $3, $2);}

whileStmt: TOKEN_WHILE expression TOKEN_DO statement{$$=makeWhile($2, $4);};

call: TOKEN_ID '(' expression ')' {$$=makeCall($1, $3);};

%%

#include "astexec.h"
#include <stdlib.h>

void yyerror(const char* const message)
{
    fprintf(stderr, "Parse error:%s\n", message);
    exit(1);
}

我正在VS 2012环境中使用winflexbison生成解析器和词法分析器.构建过程非常简单.要做的就是在VS中将<appropriate>_custom_build.targets添加到项目构建自定义中,然后构建解决方案.可以在这里找到对文档的引用@ 用于Visual Studio的winflexbison .

EDIT 1: I am using winflexbison in VS 2012 environment to generate my parser and the lexer. The process for the build is rather simple. All that is required to be done is to add the <appropriate>_custom_build.targets to build customizations for the project in VS and just build solution. A reference to the documentation can be found here @ winflexbison for Visual studio.

我还要指出,我遵循相同的方法来构建示例flex和bison文件,然后将其集成到项目中.这对我来说很好.

I would also like to point out that I followed the same method to build a sample flex and bison file and later integrated in a project. That worked fine for me.

我在做什么错了?

推荐答案

您的野牛输入中包含注释清楚但已过时的定义[注释1]:

Your bison input includes a well-commented but obsolete definition [note 1]:

/* Since the parser must return the AST, it must get a parameter where
 * the AST can be stored. The type of the parameter will be void*. */
#define YYPARSE_PARAM astDest

如注释所示,这将导致yyparse的原型为:

As the comment indicates, this will cause the prototype for yyparse to be:

int yyparse(void* astDest);

但是,在您的main函数中,您已经声明了

However, in your main function, you've declared

extern int yyparse();

由于使用C ++进行编译,因此在main.cpp中声明并由main调用的yyparse与在parser.tab.h中声明并在parser.tab.cpp中定义的yyparse不同.因此,您会收到一个链接器错误.

Since you are compiling this with C++, the yyparse declared in main.cpp and invoked by main is not the same function as the yyparse declared in parser.tab.h and defined in parser.tab.cpp. Consequently, you get a linker error.

如果您将#include "parser.tab.h"放入main.cpp文件而不是手动声明yyparse,则可能会看到更容易理解的错误消息,尽管我不能保证VS 2012产生的错误消息.

Had you put #include "parser.tab.h" into your main.cpp file instead of manually declaring yyparse, you would probably have seen a more easily-understood error message, although I can't vouch for error messages produced by VS 2012.

注意:

  1. YYPARSE_PARAM自1.875年的野牛版以来就已不推荐使用,早在十多年前,它现在仅与yacc兼容的解析器一起使用.您应该使用%parse-param声明,该声明可与所有由野牛产生的解析器一起使用,并且允许您指定实际的参数类型,而不必放弃类型安全性.有关详细信息,请参见《野牛手册》 .
  1. YYPARSE_PARAM has been deprecated since bison version 1.875, well more than a decade ago, and it currently only works with yacc-compatible parsers. You should use the %parse-param declaration, which works with all bison-produced parsers, and which allows you to specify an actual parameter type rather than having to abandon type safety. See the bison manual for details.

这篇关于yyparse()的未解析外部符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆