使用flex和bison的计算器

时间:2018-09-22 22:25:23

标签: bison flex-lexer

我是flex和bison的新手,我正在尝试使用flex和bison制作计算器。我的flex正在编译,但我的野牛文件中出现错误。

下面是我的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
      {
    //  $$ = $1 + $3;     
      }
    | expr TOK_MUL expr
      {
    //  $$ = $1 * $3;
      }
    | TOK_NUM_INT
      {     
    //  $$ = $1;
      }
        | TOK_NUM_FLOAT
          {
         //      $$ = $1;
          }
;
%%
int yyerror(char *s)
{
    printf("\nsyntax error on line no %d\n",yylineno);
    return 0;
}
int main()
{
   yyparse();
   return 0;
}

现在我遇到错误:

  

已使用符号TOK_MAIN,但未定义为令牌,并且没有   规则编:TOK_MAIN TOK_OPEN_CURLY stmts TOK_CLOSE_CURLY

1 个答案:

答案 0 :(得分:0)

The error message is telling you're using a token named TOK_MAIN, but you never defined a token with that name. And sure enough, if you look at your %token line, it includes a token named TOK_MAIN_BRACKET, but not TOK_MAIN.

So you should either rename it to TOK_MAIN in your %token definition or replace the use of TOK_MAIN with TOK_MAIN_BRACKET (in which case you should change your lexer accordingly as well).

PS: It is somewhat unusual to lex main() as a single token. It'd be more common to have main, ( and ) each be their own token.