I was trying to write a logical expression evaluation tool with flex and bison. I've gone over the code many times but when I run the executable it just ignores my input and prints Syntax error
after several inputs. My flex file lexer.l
is
%{
#include "parser.tab.h"
%}
%%
"&&" { return AND; }
"||" { return OR; }
"!" { return NOT; }
"==" { return EQ; }
"!=" { return NEQ; }
"<=" { return LEQ; }
">=" { return GEQ; }
"<" { return LT; }
">" { return GT; }
"(" { return LPAREN; }
")" { return RPAREN; }
[0-9]+ { yylval = atoi(yytext); return NUM; }
"true" { return TRUE; }
"false" { return FALSE; }
[ \t\n]+ { /* Skip whitespace */ }
. { return yytext[0]; }
%%
int yywrap() {
return 1;
}
And my bison file parser.y
is
%{
#include <stdio.h>
int comparisons = 0;
int actual_comparisons = 0;
void yyerror(const char *s);
int yylex(void);
%}
%token AND OR NOT EQ NEQ LEQ GEQ LT GT LPAREN RPAREN NUM TRUE FALSE
%left OR
%left AND
%right NOT
%nonassoc EQ NEQ LEQ LT GT GEQ
%%
input: input expr '\n' { printf("%s, %d, %d", $2 ? "TRUE" : "FALSE", comparisons, actual_comparisons);}
| /* empty */ { /*empty*/ }
;
expr: expr OR expr { $$ = $1 || $3; comparisons += 1; actual_comparisons += ($1 ? 0 : 1); }
| expr AND expr { $$ = $1 && $3; comparisons += 1; actual_comparisons += ($1 ? 1 : 0); }
| NOT expr { $$ = !$2; }
| expr EQ expr { $$ = $1 == $3; comparisons += 1; actual_comparisons += 1; }
| expr NEQ expr { $$ = $1 != $3; comparisons += 1; actual_comparisons += 1; }
| expr LEQ expr { $$ = $1 <= $3; comparisons += 1; actual_comparisons += 1; }
| expr GEQ expr { $$ = $1 >= $3; comparisons += 1; actual_comparisons += 1; }
| expr LT expr { $$ = $1 < $3; comparisons += 1; actual_comparisons += 1; }
| expr GT expr { $$ = $1 > $3; comparisons += 1; actual_comparisons += 1; }
| LPAREN expr RPAREN { $$ = $2; }
| NUM { $$ = $1; }
| TRUE { $$ = 1; }
| FALSE { $$ = 0; }
;
%%
void yyerror(const char *s) {
fprintf(stderr, "Error: %s\n", s);
}
int main(void) {
return yyparse();
}
%%
void yyerror(const char *s) {
fprintf(stderr, "Error: %s\n", s);
}
int main() {
return yyparse();
}
I then did
bison -d parser.y
flex lexer.l
gcc parser.tab.c lex.yy.c -o logic_eval -lm
./logic_eval
But the executable doesn't print any information after \n
.
I have examined the operator priority, associativity and the productions over and over, but did not find anything suspicious. Any help would be appreciated!
The most obvious problem is that your parser is expecting newline ('\n'
) tokens, but your lexer never generates them -- it treats a newline as whitespace and skips it.
Remove \n
from your whitespace lexer rule and add an explicit newline rule:
[ \t\r]+ { /* Skip whitespace */ }
[\n] { return *yytext; }
Adding CR to your whitespace rule will also skip that, so your parser can handle DOS formatted files transparently.