使用 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() 各自作为自己的标记会更常见。