I'm learning flex/bison. I wrote the following program but getting errors.
%{
#include <stdio.h>
typedef struct node
{
struct node *left;
struct node *right;
char *token;
}node;
node *mknode( node *left, node *right, char *token);
void printtree(node *tree);
#define YYSTYPE struct node *
%}
%union
{
char* str;
int num;
}
%start lines
%token <str> WORD
%token <str> PLUS MINUS TIMES DIVIDE POWER
%token <str> LEFT_PARENTHESIS RIGHT_PARENTHESIS
%token <str> END
%left PLUS MINUS
%left TIMES DIVIDE
%right POWER
%type <str> exp term factor line lines
%%
lines: /* empty */
| lines line;
line: exp END { printtree($1); printf("\n");}
;
exp: term {$$=$1; }
| exp PLUS term { $$=mknode($1,$3,"+"); }
| exp MINUS term { $$=mknode($1,$3,"-"); }
;
term: factor { $$=$1; }
|term TIMES factor { $$=mknode($1,$3,"*"); }
;
factor: WORD { $$=mknode(0,0, (char*)yylval); }
|LEFT_PARENTHESIS exp RIGHT_PARENTHESIS
{ $$=$2; }
;
%%
int main(void)
{
return yyparse();
}
node *mknode(node *left, node *right, char *token)
{
/* malloc the node */
node *newnode = (node *)malloc(sizeof(node));
char *newstr = (char *)malloc(strlen(token)+1);
strcpy(newstr, token);
newnode->left = left;
newnode->right = right;
newnode->token = newstr;
return(newnode);
}
void printtree(node *tree)
{
int i;
if (tree->left || tree->right)
printf("(");
printf(" %s ", tree->token);
if (tree->left)
printtree(tree->left);
if (tree->right)
printtree(tree->right);
if (tree->left || tree->right)
printf(")");
}
int yyerror(char *s )
{
fprintf (stderr, "%s\n", s);
}
flex:
%{
#include <stdlib.h>
#include "y.tab.h"
%}
%%
[a-zA-Z0-9]+ { yylval.str = strdup( yytext ); return WORD; }
/* cast pointer to int for compiler warning */
[ \t] ;
"+" return(PLUS);
"-" return(MINUS);
"*" return(TIMES);
"/" return(DIVIDE);
"^" return(POWER);
"(" return(LEFT_PARENTHESIS);
")" return(RIGHT_PARENTHESIS);
\n return(END);
%%
int yywrap (void) {return 1;}
The error I'm getting:
C:\flexbison>recomp example2
example2.y:40.6: warning: empty rule for typed nonterminal, and no action
conflicts: 5 reduce/reduce
example2.y:43: error: request for member `str' in something not a structure or union
example2.y:46: error: request for member `str' in something not a structure or union
example2.y:46: error: request for member `str' in something not a structure or union
example2.y:47: error: request for member `str' in something not a structure or union
example2.y:47: error: request for member `str' in something not a structure or union
example2.y:47: error: request for member `str' in something not a structure or union
example2.y:48: error: request for member `str' in something not a structure or union
example2.y:48: error: request for member `str' in something not a structure or union
example2.y:48: error: request for member `str' in something not a structure or union
example2.y:51: error: request for member `str' in something not a structure or union
example2.y:51: error: request for member `str' in something not a structure or union
example2.y:52: error: request for member `str' in something not a structure or union
example2.y:52: error: request for member `str' in something not a structure or union
example2.y:52: error: request for member `str' in something not a structure or union
example2.y:55: error: request for member `str' in something not a structure or union
example2.y:56: error: request for member `str' in something not a structure or union
example2.y:58: error: request for member `str' in something not a structure or union
example2.y:58: error: request for member `str' in something not a structure or union
Any idea why I'm getting this error?
The first glaring problem is that you should not be defining
YYSTYPE
if you are using yacc. Yacc definesYYSTYPE
from your%union
. You need to defineYYSTYPE
if you're usinglex
, but not usingyacc
.Your
%union
parse stack item type only containsint
andstr
members. Example: you have defined theexp
grammar symbol as having typestr
, and then you have this production:The
mknode
function returnsnode *
, but the type of the$$
symbol ischar *
because it stands for theexp
on the left hand side, which you typed as astr
, and thestr
member of the%union
ischar *
.The arguments to
mknode
must also benode *
. But$1
and$3
do not have that type.