I'm trying to make a very simple calculator with flex and bison generators. It just work on integer numbers. I compiled the lexer file properly with no errors; but when I compile the parser file, it shows me some warnings:
- 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
It make the output file after showing these warnings.
I compiled the output files by gcc; it made an .exe file.
When I run the .exe file and try to calculate, it shows me this error:
- syntax error
Please help me.
My codes:
lexer file
%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; }
%%
parser file
%{
#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 { $$ = $1; };
Exp: Exp PLS Exp { $$ = $1 + $3; };
Exp: Exp MNS Exp { $$ = $1 - $3; };
Exp: Exp MUL Exp { $$ = $1 * $3; };
Exp: Exp DIV Exp { $$ = $1 / $3; };
Exp: LFT Exp RIT { $$ = $2; };
Line: NWL;
Line: Exp NWL { printf("%f\n", $1); };
;
%%
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;
}
The start symbol of your grammar is Exp
, not Line
. Either put the Line
rule first or use a %start Line
declaration. The %start
declaration should go before the %%
, in the same section with the %token
declarations.
That should get you at the point where your program could handle a first line like 3 + 4
;-)
If you want it to handle multiple lines, you should add another rule -- example of a fixed grammar section of your *.y
file, with Seq
(sequence of lines) being the start symbol:
Seq: /* empty */
| Seq Line
Exp: NUM { $$ = $1; };
Exp: Exp PLS Exp { $$ = $1 + $3; };
Exp: Exp MNS Exp { $$ = $1 - $3; };
Exp: Exp MUL Exp { $$ = $1 * $3; };
Exp: Exp DIV Exp { $$ = $1 / $3; };
Exp: LFT Exp RIT { $$ = $2; };
Line: NWL
Line: Exp NWL { printf("%f\n", $1); };