I am very new to Flex and bison, I am doing an application to compare number. If a > b it will return 0 and a < b will return 1 However, I got a problem when it come to &, |, == Here is an example of my output:
>> a = 5
5
>> b = 8
8
>> a < b & a < b
1
>> syntax error
I don't know how I can fix this problem. Here is some complain of the compiler:
[tpham14@linux5 ~/331] make -f mymake calc
bison -d -o y.tab.c -v calc.y
calc.y: warning: 16 shift/reduce conflicts [-Wconflicts-sr]
calc.y: warning: 6 reduce/reduce conflicts [-Wconflicts-rr]
cc -c -o y.tab.o y.tab.c
cc -c -o lex.yy.o lex.yy.c
cc -o calc y.tab.o lex.yy.o
Here is my calc.y file:
%{
#include "calc.h"
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
/************************************************************************
* Defines a yacc grammar for a simple calculator using infix
* notation. WHen executed, the calculator enters a loop in
* which it prints the prompt >>, reads a toplevel expression
* terminated by a newline, and prints its value. Operators
* include +, -, *, and = (assignment). Note that all
* expressions return values, even assignment. Parentheses
* can be used to override operator precedence and
* associativity rules. Based on zcalc by [email protected]
************************************************************************/
int yylex();
int yyparse();
%}
/*
Th union directive specifies the collection of tpes our grammar
deals with -- just doubles and pointers to symbol table entries.
*/
%union {
double dval;
struct symtab *symp;
}
/*
Declare the token types and any associated value types. We made
EQ a token in calc.l because otherwise '=' and '==' would clash.
*/
%token <symp> NAME
%token <dval> NUMBER
%token EQ
%token GT
%token LT
%token OR
%token AND
%token NOT
%token IF
%token ELSE
/* The folowing declarations specify the precidence and associativity
of our operators. The operators -, +, * and / to be left
associative, * and EQ to be right associative and UMINUS to be
non-associative (since it is a unary operator). The '=' operator
has the lowest precedence and UMINUS the highest.
*/
%right '=' /*lowest precedence*/
%right EQ GT LT
%left '-' '+'
%left '*' '/'
%left '&'
%nonassoc OR AND NOT
%nonassoc IF
%nonassoc ELSE
%nonassoc UMINUS /* highest precedence */
/*
Declare the type of expression to be a dval (double).
*/
%type <dval> expr
%type <dval> smallexprs
%%
/*
Here are our grammar rules. a session is a sequence of lines. A
toplevel is just an expr (print its value followed by two
newlines and the prompt >>) or a '? (print help) or a '.' (exit).
An expr can be a number, name, the sum of two exprs, ...
*/
session: /* empty */
|session toplevel '\n'
;
toplevel: expr { printf("%g\n\n>> ", $1); }
| /*empty*/
| '?' { printHelp(); printf("\n>> "); }
| '.' { printf("Exiting 331 calc\n"); exit(1); }
expr: smallexprs { $$ = $1; }
| NAME { $$ = $1->value; }
| NAME '=' expr { $1->value = $3; $$ = $3; }
| IF expr expr expr { if($2 == 1) $$ = $3; else $$ = $4; }
| smallexprs AND smallexprs { $$ = $1 && $3; }
| smallexprs OR smallexprs { $$ = $1 || $3; }
| smallexprs EQ smallexprs { $$ = $1 == $3; }
| expr GT expr { $$ = $1 > $3; }
| expr LT expr { $$ = $1 < $3; }
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr { $$ = $1 / $3; }
smallexprs: NUMBER { $$ = $1; }
| IF smallexprs smallexprs smallexprs { if($2 == 1) $$ = $3; else $$ = $4; }
| smallexprs EQ smallexprs { $$ = $1 == $3; }
| smallexprs GT smallexprs { $$ = $1 > $3; }
| smallexprs LT smallexprs { $$ = $1 < $3; }
| smallexprs '+' smallexprs { $$ = $1 + $3; }
| smallexprs '-' smallexprs { $$ = $1 - $3; }
| smallexprs '*' smallexprs { $$ = $1 * $3; }
| smallexprs '/' smallexprs { $$ = $1 / $3; }
| '~' smallexprs %prec UMINUS { $$ = -$2; }
| '(' smallexprs ')' { $$ = $2; }
%%
struct symtab *
symlook(s)
char *s;
{
char *p;
struct symtab *sp;
/* given the name of a symbol, scan the symbol table and
either return the entry with matching name or add it
to the next free cell in the symbol table. */
for(sp = symtab; sp < &symtab[SYMBOLTABLESIZE]; sp++) {
/* If the symbol table entry has a name and its equal
to the one we are looking for, return this entry */
if (sp->name && !strcmp(sp->name, s))
return sp;
/* If the name is empty then this entry is free, so the
symbol must not be in the table and we can add it here
and return this entry. */
if (!sp->name) {
sp->name = strdup(s);
return sp;
}
}
/* We searched the entire symbol table and neither found
the symbol or an unused entry. So the table must be
full. Sigh. */
yyerror("The symbol table is full, sorry...\n");
exit(1);
}
void printHelp()
{ /* print calculator help and return */
printf("Enter an expression in infix notation followed by a newline.\n");
printf("Operators include +, -, * and =. Defined functions include\n");
printf("sqrt, exp and log. You can assign a variable using the =\n");
printf("operator. Type . to exit. Syntax errors will terminate the\n");
printf("program, so be careful.\n");
}
/* If error prints error and Do not accept to signify bad syntax in
program */
void yyerror(char *msg) /* yacc error function */
{
printf("%s \n" , msg);
}
int yywrap(){return 1;}
int main()
{ /* print herald and call parser */
printf("331 Calculator\n(type ? for help and . to exit)\n\n>> ");
yyparse();
return 0;
}
Below will be my calc.l file:
%{
#include "y.tab.h"
#include "calc.h"
#include <math.h>
/************************************************************************
A lexical scanner to recognize numbers, symbols and the EQ
operator. When a NUMBER is found, its value is set is set to the
appropriate float. When a NAME is found, an entry in symbol table is
created (with initial value 0.0) and the token's value is a pointer to
this entry. If a '==' sequence is seen, it is returned as a token
EQ. Spaces and tabs are ignored. Any other characters, including
a newline, are passed on as their own tokens. Based on the zcalc
calculator by [email protected]
************************************************************************/
%}
D [0-9]
A [a-zA-Z]
AD [a-zA-Z0-9]
%%
({D}+|({D}*\.{D}+)([eE][-+]?{D}+)?) {yylval.dval = atof(yytext); return NUMBER;}
if {return IF;}
or {return OR;}
and {return AND;}
not {return NOT;}
{A}{AD}* {struct symtab *sp = symlook(yytext); yylval.symp = sp; return NAME;}
"==" {return EQ;}
">" {return GT;}
"<" {return LT;}
[ \t] ;
\n |
. return yytext[0];
%%
Below is my calc.h file:
#define SYMBOLTABLESIZE 30
/* An entry in the symbol table has a name, a pointer to a function,
and a numeric value. */
struct symtab {
char *name;
double (*funcptr)();
double value;
} symtab[SYMBOLTABLESIZE];
struct symtab *symlook();
void printHelp();
void yyerror();
&
being defined as the tokenAND
anywhere. I seeand
and I asume that is the character stringand
, but I don't see&
. – Paul Ogilviesmallexprs
– Paul Ogilviesmallexprs EQ smallexprs
is defined twice. Once inexpr
and once insmallexprs
. Some other rules too. This causes the shift/reduce conflicts. – Paul Ogilvie