1
votes

I am developing a small project using Lex and Yacc and I have to deal with mathematical expressions.

In my file syntax.y, I have these two types of production rules:

%union {
   char* lexeme;            
   double value;
   }

%token <lexeme>  NUM
%type <lexeme> expr
%type <value> comp_expr

expr  : expr "+" expr { $$ = strcat($1,"+"); $$ = strcat($$,$3); }
      | NUM 
      ;

comp_expr: comp_expr "+" comp_expr { $$ = $1 + $3; }
         | NUM 
         ;

I use "expr" in order to return the expression as a string and I use "comp_expr" in order to return the expression as a computed expression, in this case a sum.

Basing on the other parts in syntax.y (that I did not include, because here are irrelevant) I have a system that recognize properly when to use "expr" and when to use "comp_expr".

But I have an error when I use "comp_expr", because the Token NUM is declared as a lexeme, thus a string, and the production "comp_expr" has a value, thus a double, as type.

How can I assign both lexeme and value to the Token NUM? Or how can I change the value of NUM basing on production that I am using?

In addition, I post also the way I save the NUM in the file lexic.l:

{NUM}   { yylval.lexeme = strdup(yytext); return NUM; }

Thanks in advance for the attention.

1

1 Answers

1
votes

At the risk of stating the obvious, I'd suggest you convert the NUM to a double when you need it to be a double. Unit productions are perfect for such conversions and you happen to have one handy:

comp_expr: NUM { $$ = strtod($1, NULL); }

You could do more careful error checking with the call to strtod but it may be reasonable to assume that the lexeme has already been validated by the lexical scanner.


By the way, there's a huge problem with:

expr  : expr "+" expr { $$ = strcat($1,"+"); $$ = strcat($$,$3); }

$1 is, presumably, the return value of a call to strdup in the lexical scanner. In that case, it is exactly long enough to hold the lexeme and no longer. So concatenating more stuff at the end is a buffer overflow; you will overwrite memory which doesn't belong to you. That will get you into trouble very quickly.

You need to allocate a new string of the correct length for the expr; asprintf is very handy for this purpose, as well as being more readable than a series of strcats.

You probably should also think about the memory leak resulting from not freeing the strduped lexemes after you concatenate them.