使用 flex 和 bison 的计算器
calculator using flex and bison
我是 flex 和 bison 的新手,我正在尝试使用 flex 和 bison 制作一个计算器。我的 flex 正在编译,但我的 bison 文件中出现错误。
下面是我的 flex 文件:
%{
#include <stdio.h>
#include <stdlib.h>
#include "calc.tab.h"
%}
digit ([0-9])
characters ([a-z])
smallcasedigit ([a-z0-9])
identifier ([a-z])(a-z0-9])*
%option yylineno
%%
"main()" { return(TOK_MAIN);}
"{" { return(TOK_OPEN_CURLY);}
"}" { return(TOK_CLOSE_CURLY);}
"printvar" { return(TOK_PRINTVAR);}
"println" { return(TOK_PRINTLN);}
"int" { return(TOK_INT_KEYWORD);}
"float" { return(TOK_FLOAT_KEYWORD);}
{digit}+ { yylval.int_val=atoi(yytext);
printf(" TOK_NUM_INT \n");
return TOK_NUM_INT;}
{digit}+[.]{digit}+ { yylval.float_val=atof(yytext);
printf(" TOK_NUM_FLOAT \n");
return TOK_NUM_FLOAT;}
{identifier} { yylval.string=strdup(yytext);
printf(" TOK_IDENTIFIER %s\n",yytext);
return(TOK_IDENTIFIER); }
";" { return(TOK_SEMICOLON);}
"+" { return(TOK_ADD);}
"-" { return(TOK_SUB);}
"*" { return(TOK_MUL);}
"/" { return(TOK_DIV);}
"=" { reurn(TOK_EQUAL);}
[ \n] { }
. { printf("Invalid character '%c', ignored\n", yytext[0]); }
%%
/*int main(){ yylex();
printf(" lexical Analysisfinished ");return 0;}*/
这是我的野牛文件:
%{
#include <stdio.h>
extern int yylineno;
typedef struct sym_node * smt;
typedef struct sym_node
{
smt *smt;
int type;
char *id_name;
/* data */
}sm_node;
%}
%token TOK_MAIN_BRACKET TOK_OPEN_CURLY TOK_CLOSE_CURLY TOK_PRINTVAR TOK_PRINTLN TOK_INT_KEYWORD TOK_FLOAT_KEYWORD TOK_NUM_INT TOK_NUM_FLOAT TOK_IDENTIFIER TOK_SEMICOLON TOK_ADD
TOK_SUB TOK_MUL TOK_DIV TOK_NUM TOK_EQUAL
%union{
int int_val;
float float_val;
char *string;
struct s_expr
{
int type;
int ival;
float fval;
}struct_expr;
}
%type <int_val> TOK_NUM_INT
%type <float_val> TOK_NUM_FLOAT
%type <string> TOK_IDENTIFIER
%type <struct_expr> expr
%left TOK_ADD TOK_SUB
%left TOK_MUL TOK_DIV
%%
prog: TOK_MAIN TOK_OPEN_CURLY stmts TOK_CLOSE_CURLY
;
stmts:
| stmt TOK_SEMICOLON stmts
;
stmt:
TOK_INT_KEYWORD TOK_IDENTIFIER
| TOK_FLOAT_KEYWORD TOK_IDENTIFIER
| TOK_IDENTIFIER TOK_EQUAL expr
| TOK_PRINTVAR TOK_IDENTIFIER
;
expr:
expr TOK_ADD expr
{
// $$ = + ;
}
| expr TOK_MUL expr
{
// $$ = * ;
}
| TOK_NUM_INT
{
// $$ = ;
}
| TOK_NUM_FLOAT
{
// $$ = ;
}
;
%%
int yyerror(char *s)
{
printf("\nsyntax error on line no %d\n",yylineno);
return 0;
}
int main()
{
yyparse();
return 0;
}
现在我收到一个错误:
symbol TOK_MAIN is used, but is not defined as a token and has no
rules prog: TOK_MAIN TOK_OPEN_CURLY stmts TOK_CLOSE_CURLY
错误消息告诉您正在使用名为 TOK_MAIN
的令牌,但您从未使用该名称定义令牌。果然,如果您查看 %token
行,它包含一个名为 TOK_MAIN_BRACKET
的标记,但不包含 TOK_MAIN
.
所以你应该在你的 %token
定义中将它重命名为 TOK_MAIN
或者用 TOK_MAIN_BRACKET
替换 TOK_MAIN
的使用(在这种情况下你应该改变你的词法分析器相应地也是如此)。
PS:将 lex main()
作为单个标记有点不寻常。 main
、(
和 )
各自作为自己的标记会更常见。
我是 flex 和 bison 的新手,我正在尝试使用 flex 和 bison 制作一个计算器。我的 flex 正在编译,但我的 bison 文件中出现错误。
下面是我的 flex 文件:
%{
#include <stdio.h>
#include <stdlib.h>
#include "calc.tab.h"
%}
digit ([0-9])
characters ([a-z])
smallcasedigit ([a-z0-9])
identifier ([a-z])(a-z0-9])*
%option yylineno
%%
"main()" { return(TOK_MAIN);}
"{" { return(TOK_OPEN_CURLY);}
"}" { return(TOK_CLOSE_CURLY);}
"printvar" { return(TOK_PRINTVAR);}
"println" { return(TOK_PRINTLN);}
"int" { return(TOK_INT_KEYWORD);}
"float" { return(TOK_FLOAT_KEYWORD);}
{digit}+ { yylval.int_val=atoi(yytext);
printf(" TOK_NUM_INT \n");
return TOK_NUM_INT;}
{digit}+[.]{digit}+ { yylval.float_val=atof(yytext);
printf(" TOK_NUM_FLOAT \n");
return TOK_NUM_FLOAT;}
{identifier} { yylval.string=strdup(yytext);
printf(" TOK_IDENTIFIER %s\n",yytext);
return(TOK_IDENTIFIER); }
";" { return(TOK_SEMICOLON);}
"+" { return(TOK_ADD);}
"-" { return(TOK_SUB);}
"*" { return(TOK_MUL);}
"/" { return(TOK_DIV);}
"=" { reurn(TOK_EQUAL);}
[ \n] { }
. { printf("Invalid character '%c', ignored\n", yytext[0]); }
%%
/*int main(){ yylex();
printf(" lexical Analysisfinished ");return 0;}*/
这是我的野牛文件:
%{
#include <stdio.h>
extern int yylineno;
typedef struct sym_node * smt;
typedef struct sym_node
{
smt *smt;
int type;
char *id_name;
/* data */
}sm_node;
%}
%token TOK_MAIN_BRACKET TOK_OPEN_CURLY TOK_CLOSE_CURLY TOK_PRINTVAR TOK_PRINTLN TOK_INT_KEYWORD TOK_FLOAT_KEYWORD TOK_NUM_INT TOK_NUM_FLOAT TOK_IDENTIFIER TOK_SEMICOLON TOK_ADD
TOK_SUB TOK_MUL TOK_DIV TOK_NUM TOK_EQUAL
%union{
int int_val;
float float_val;
char *string;
struct s_expr
{
int type;
int ival;
float fval;
}struct_expr;
}
%type <int_val> TOK_NUM_INT
%type <float_val> TOK_NUM_FLOAT
%type <string> TOK_IDENTIFIER
%type <struct_expr> expr
%left TOK_ADD TOK_SUB
%left TOK_MUL TOK_DIV
%%
prog: TOK_MAIN TOK_OPEN_CURLY stmts TOK_CLOSE_CURLY
;
stmts:
| stmt TOK_SEMICOLON stmts
;
stmt:
TOK_INT_KEYWORD TOK_IDENTIFIER
| TOK_FLOAT_KEYWORD TOK_IDENTIFIER
| TOK_IDENTIFIER TOK_EQUAL expr
| TOK_PRINTVAR TOK_IDENTIFIER
;
expr:
expr TOK_ADD expr
{
// $$ = + ;
}
| expr TOK_MUL expr
{
// $$ = * ;
}
| TOK_NUM_INT
{
// $$ = ;
}
| TOK_NUM_FLOAT
{
// $$ = ;
}
;
%%
int yyerror(char *s)
{
printf("\nsyntax error on line no %d\n",yylineno);
return 0;
}
int main()
{
yyparse();
return 0;
}
现在我收到一个错误:
symbol TOK_MAIN is used, but is not defined as a token and has no rules prog: TOK_MAIN TOK_OPEN_CURLY stmts TOK_CLOSE_CURLY
错误消息告诉您正在使用名为 TOK_MAIN
的令牌,但您从未使用该名称定义令牌。果然,如果您查看 %token
行,它包含一个名为 TOK_MAIN_BRACKET
的标记,但不包含 TOK_MAIN
.
所以你应该在你的 %token
定义中将它重命名为 TOK_MAIN
或者用 TOK_MAIN_BRACKET
替换 TOK_MAIN
的使用(在这种情况下你应该改变你的词法分析器相应地也是如此)。
PS:将 lex main()
作为单个标记有点不寻常。 main
、(
和 )
各自作为自己的标记会更常见。