使用flex和bison的计算器

使用flex和bison的计算器,bison,flex-lexer,Bison,Flex Lexer,我是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

我是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;}*/
%{
#包括
#包括
#包括“计算表h”
%}
数字([0-9])
字符([a-z])
小案例数字([a-z0-9])
标识符([a-z])(a-z0-9])*
%选项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_关键字);}
“float”{return(TOK_float_关键字);}
{digit}+{yylval.int_val=atoi(yytext);
printf(“TOK_NUM_INT\n”);
返回TOK_NUM_INT;}
{digit}+[.]{digit}+{yylval.float_val=atof(yytext);
printf(“TOK_NUM_FLOAT\n”);
返回TOK_NUM_FLOAT;}
{identifier}{yylval.string=strdup(yytext);
printf(“TOK_标识符%s\n”,yytext);
返回(TOK_标识符);}
“;”{返回(TOK_分号);}
“+”{return(TOK_ADD);}
“-”{return(TOK_SUB);}
“*”{return(TOK_MUL);}
“/”{return(TOK_DIV);}
“=”{reurn(TOK_EQUAL);}
[\n]{}
.                       {printf(“无效字符“%c”,已忽略,\n”,yytext[0]);}
%%
/*int main(){yylex();
printf(“词法分析完成”);返回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;
}
%{
#包括
外部内部yylineno;
类型定义结构符号节点*smt;
类型定义结构符号节点
{
smt*smt;
int型;
字符*id\u名称;
/*资料*/
}sm_节点;
%}
%token TOK_MAIN TOK_括号TOK_OPEN TOK_CURLY TOK_CLOSE TOK_CURLY TOK_PRINTVAR TOK_PRINTLN TOK_INT TOK_关键字TOK_FLOAT_关键字TOK_NUM_INT TOK_NUM_FLOAT TOK_标识符TOK_分号TOK_ADD
TOK_SUB TOK_MUL TOK_DIV TOK_NUM TOK_EQUAL
%联合{
国际价值;
浮动值;
字符*字符串;
结构s_expr
{
int型;
国际竞争力;
浮动fval;
}结构表达式;
}
%输入TOK_NUM_INT
%类型TOK_NUM_FLOAT
%类型TOK_标识符
%类型表达式
%左TOK_添加TOK_接头
%左托库木尔托库分区
%%
程序:TOK_主TOK_打开_卷曲stmts TOK_关闭_卷曲
;
STMT:
|stmt TOK_分号stmts
;
stmt:
TOK_INT_关键字TOK_标识符
|TOK_FLOAT_关键字TOK_标识符
|TOK_标识符TOK_相等表达式
|TOK_打印变量TOK_标识符
;
表达式:
expr TOK_添加expr
{
//  $$ = $1 + $3;     
}
|expr TOK_MUL expr
{
//  $$ = $1 * $3;
}
|TOK_NUM_INT
{     
//  $$ = $1;
}
|浮点数
{
//      $$ = $1;
}
;
%%
int yyerror(字符*s)
{
printf(“\n第%d行出现语法错误”,yylineno);
返回0;
}
int main()
{
yyparse();
返回0;
}
现在我得到一个错误:

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


错误消息告诉您正在使用名为
TOK_MAIN
的令牌,但您从未使用该名称定义令牌。当然,如果您查看
%token
行,它包含一个名为
TOK_MAIN_BRACKET
,但不是
TOK_MAIN

因此,您应该在您的
%TOK_MAIN
定义中将其重命名为
TOK_MAIN
,或者将
TOK_MAIN
替换为
TOK_MAIN_括号
(在这种情况下,您也应该相应地更改lexer)


PS:将lex
main()
作为一个令牌有点不寻常。将
main
作为各自的代币会更常见。

谢谢,这很有效。我已将main,(and)作为单独的标记写入。但在执行时,它仍然显示错误消息:意外标记附近的语法错误“(@shubham)您是否已调整语法,以在
main
标记之后使用
?是的。这就是我所做的:“main”{return(TOK_main);}({return return(TOK_main_OPEN)}”){return(TOK_main_CLOSE)}”@shubham不,我的意思是在解析器中。括号需要在
prog
中的
TOK_MAIN
之后提到。顺便说一句:您可以使用字符文本来表示单字符标记。然后您可以在lexer中使用
return'(';
return');
在解析器中使用
prog:TOK_MAIN'('''stmnts'
(假设您对卷曲进行相同的更改)。是的,我确实在解析器中提到了括号。prog:TOK_MAIN TOK_MAIN TOK_OPEN TOK_MAIN TOK_CLOSE TOK_OPEN_CURLY stmts TOK_CLOSE_CURLY但我仍然收到相同的错误消息