我是flex和Bison的新手。以下bison文件无法编译生成.cpp和.h文件:
如果我删除代码以支持if语句,那么它可以工作。 |ifStmt{$$=$1;}
中的statement:
,规则ifStmt: TOKEN_IF expression TOKEN_DO statement TOKEN_ELSE TOKEN_DO statement{$$=makeIf($2, $3, $7);};
并通过删除TOKEN_IF
和TOKEN_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);
}
上面的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 */}
%%
我在这里做错了什么?
答案 0 :(得分:2)
您错过了%type
的{{1}}声明,因为来自bison的错误消息告诉您:
ifStmt
将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
添加到第23行的声明ifStmt
将修复前2个错误;可以使用%type<ast>
代替$4
修复第三个。