C++ 简单Bison文件不编译

C++ 简单Bison文件不编译,c++,bison,lex,C++,Bison,Lex,我不熟悉flex和Bison。以下bison文件未编译生成.cpp和.h文件: 如果我删除了支持If语句的代码,那么它就可以工作了。语句:,规则ifStmt:TOKEN\u IF expression TOKEN\u DO statement TOKEN\u ELSE TOKEN\u DO语句{$$=makeIf($2,$3,$7);}中的ifStmt{$$=1;}并通过删除token\u IF和token\u ELSE %error-verbose /* instruct bison to g

我不熟悉flex和Bison。以下bison文件未编译生成.cpp和.h文件:

如果我删除了支持If语句的代码,那么它就可以工作了。
语句:
,规则
ifStmt:TOKEN\u IF expression TOKEN\u DO statement TOKEN\u ELSE TOKEN\u DO语句{$$=makeIf($2,$3,$7);}中的
ifStmt{$$=1;}
并通过删除
token\u IF
token\u ELSE

%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*. */
struct AstElement* 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_IF TOKEN_ELSE
%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';' { 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;}
    | ifStmt{$$=$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);};

ifStmt: TOKEN_IF expression TOKEN_DO statement TOKEN_ELSE TOKEN_DO statement{$$=makeIf($2, $4, $7);};

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);
}
%error verbose/*指示bison生成详细的错误消息*/
%{
#包括“astgen.h”
#定义调试1
/*因为解析器必须返回AST,所以它必须获得一个参数,其中
*可以存储AST。参数的类型将为void**/
结构元素*ASTEST;
extern int yylex();
%}
%联合{
int-val;
char op;
字符*名称;
struct AstElement*ast;/*这是存储ast元素的新成员*/
}
%令牌令牌\u开始令牌\u结束令牌\u而令牌\u执行令牌\u如果令牌\u其他
%令牌标识
%令牌号
%令牌运算符
%调用时键入程序块语句语句赋值表达式
%启动程序
%{
/*转发声明*/
无效错误(常量字符*常量消息);
%}
%%
程序:语句“;”{astDest=$1;};
block:TOKEN\u BEGIN语句TOKEN\u END{$$=$2;};
语句:{$$=0;}
|语句“;”{$$=makeStatement($1,$2);}
|语句块“;”{$$=makeStatement($1,$2);};
声明:
赋值{$$=$1;}
|而mt{$$=$1;}
|ifStmt{$$=$1;}
|块{$$=$1;}
|调用{$$=$1;}
赋值:TOKEN_ID'='表达式{$$=makeAssignment($1,$3);}
表达式:TOKEN_ID{$$=makeExpByName($1);}
|令牌号{$$=makeExpByNum($1);}
|表达式标记_运算符表达式{$$=makeExp($1,$3,$2);}
whilestm:TOKEN_WHILE表达式TOKEN_DO语句{$$=makeWhile($2,$4);};
ifStmt:TOKEN_IF表达式TOKEN_DO语句TOKEN_ELSE TOKEN_DO语句{$$=makeIf($2,$4,$7);};
call:TOKEN_ID'('expression'){$$=makeCall($1,$3);};
%%
#包括“astexec.h”
#包括
无效错误(常量字符*常量消息)
{
fprintf(stderr,“分析错误:%s\n”,消息);
出口(1);
}
上述文件的lex文件为:

%option noyywrap

%{
#include "parser.tab.h"
#include <stdlib.h>
%}

%option noyywrap

%%

"while" return TOKEN_WHILE;
"{" return TOKEN_BEGIN;
"}"   return TOKEN_END;
"do"    return TOKEN_DO;
"if"    return TOKEN_IF;
"else"  return TOKEN_ELSE;
"=="    {yylval.op = *yytext; return TOKEN_OPERATOR;}
"!="    {yylval.op = *yytext; return TOKEN_OPERATOR;}
[a-zA-Z_][a-zA-Z0-9_]* {yylval.name = _strdup(yytext); return TOKEN_ID;}
[-]?[0-9]+    {yylval.val = atoi(yytext); return TOKEN_NUMBER;}
[()=;]  {return *yytext;}
"<="    {yylval.op = *yytext; return TOKEN_OPERATOR;}
">="    {yylval.op = *yytext; return TOKEN_OPERATOR;}
[*/+-<>] {yylval.op = *yytext; return TOKEN_OPERATOR;}
[ \t\n] {/* suppress the output of the whitespaces from the input file to stdout */}
#.* {/* one-line comment */}

%%
%选项noyywrap
%{
#包括“parser.tab.h”
#包括
%}
%选项No yywrap
%%
“while”返回令牌\u while;
“{”返回令牌\u开始;
“}”返回令牌\u结束;
“do”返回TOKEN\u do;
“如果”返回令牌\u如果;
“else”返回令牌\u else;
“==”{yylval.op=*yytext;返回标记_运算符;}
“!=”{yylval.op=*yytext;返回标记_运算符;}
[a-zA-Z_][a-zA-Z0-9_]*{yylval.name=_strdup(yytext);返回令牌_ID;}
[-]?[0-9]+{yylval.val=atoi(yytext);返回令牌\u编号;}
[()=;]{return*yytext;}
“=”{yylval.op=*yytext;返回标记_运算符;}
[*/+-]{yylval.op=*yytext;返回标记_运算符;}
[\t\n]{/*禁止将空白从输入文件输出到stdout*/}
#.*{/*单行注释*/}
%%

我在这里做错了什么?

正如bison的错误消息告诉您的那样,您缺少了
ifStmt
%type
声明:

t.y:46.17-18: $1 of `statement' has no declared type
t.y:58.78-79: $$ of `ifStmt' has no declared type
t.y:58.92-93: $3 of `ifStmt' has no declared type

ifStmt
添加到第23行的声明
%type
,将修复前2个错误;第三个问题可以通过使用
$4
而不是
$3

来解决,也许编译失败会带来一些错误消息。也许阅读它们可以让我们对这个问题有所了解。@n.m.我使用的是在VS 2012平台上构建的winflexbison。它只是跳过了Bison文件的编译,并没有抛出任何错误;它们应该是
$$=makeIf($2,$4,$7)。如果您的工具链没有显示编译错误,则它不适合任何操作。先解决这个问题。使用命令行工具,或者正确配置IDE,等等。由于信息不足而关闭。@Aasmund Eldhuset感谢您指出,这是我在SO上发布的一个打字错误。如下面的解决方案中所述,通过更正
%type
的declation,已修复该错误。谢谢!这就解决了这个错误。