使用 flex 和 bison 制作一个简单的计算器

Make a simple calculator using flex and bison

我正在尝试使用 flex 和 bison 生成器制作一个非常简单的计算器。 它只适用于整数。 我正确地编译了词法分析器文件,没有错误;但是当我编译解析器文件时,它显示了一些警告:

  • warning: 1 nonterminal useless in grammar
  • warning: 2 rules useless in grammar
  • 21.1-4: warning: nonterminal useless in grammar: Line
  • 21.9-1: warning: rule useless in grammar: Line: NWL
  • 22.9-55: warning: 1 nonterminal useless in grammar: Exp NWL

显示这些警告后生成输出文件。
我用 gcc 编译了输出文件;它制作了一个 .exe 文件。
当我 运行 .exe 文件并尝试计算时,它向我显示此错误:

  • syntax error

请帮助我。

我的代码:
词法分析器文件

%option noyywrap
%{
#define YYSTYPE double
#include <stdio.h>
#include "x.tab.h"
%}
DIG         [0-9]
%%
{DIG}+      { yylval = atoi(yytext); return NUM; }
"+"                             { return PLS; }
"-"                             { return MNS; }
"*"                             { return MUL; }
"/"                             { return DIV; }
"\n"                                { return NWL; }
"("                             { return LFT; }
")"                             { return RIT; }
%%

解析器文件

%{
#include <stdio.h>
#define YYSTYPE double
int yyerror (char const *s);
extern int yylex (void);
%}
%token  PLS MNS
%token  MUL DIV
%token  NWL
%token  NUM
%token  LFT RIT
%left   PLS MNS
%left   MUL DIV
%%
Exp:    NUM             { $$ = ; };
Exp:    Exp PLS Exp     { $$ =  + ; };
Exp:    Exp MNS Exp     { $$ =  - ; };
Exp:    Exp MUL Exp     { $$ =  * ; };
Exp:    Exp DIV Exp     { $$ =  / ; };
Exp:    LFT Exp RIT     { $$ = ; };
Line:   NWL;
Line:   Exp NWL         { printf("%f\n", ); };
;
%%
int yyerror(char const *s) {
  printf("%s\n", s);
}
int main(){
    int ret = yyparse();
    if (ret){
    fprintf(stderr, "%d error found.\n",ret);
    }
    return 0;
}

你语法的起始符号是Exp,不是Line。要么将 Line 规则放在首位,要么使用 %start Line 声明。 %start 声明应位于 %% 之前,与 %token 声明位于同一部分。

这应该会让您的程序能够处理第一行,例如 3 + 4 ;-)

如果您希望它处理多行,您应该添加另一条规则 -- *.y 文件的固定语法部分的示例,以 Seq(行的序列)作为开始符号:

Seq:    /* empty */
|       Seq Line
Exp:    NUM             { $$ = ; };
Exp:    Exp PLS Exp     { $$ =  + ; };
Exp:    Exp MNS Exp     { $$ =  - ; };
Exp:    Exp MUL Exp     { $$ =  * ; };
Exp:    Exp DIV Exp     { $$ =  / ; };
Exp:    LFT Exp RIT     { $$ = ; };
Line:   NWL
Line:   Exp NWL         { printf("%f\n", ); };