2
votes

I'm using bison and flex to create (somewhere in the future) an abstract syntaxt tree (AST). For now, I want to have only an arithmetic expression (with + for instance), something like expression->expression '+' expression | constant, but I want the expression to have two attributes: the code (that is a string with the value of the first element in the right hand side of the rule (RHS), a + and the value of the second expression).

I created the following structure:

%union {
    struct{
        char* code;
        char* varn;
    } attributes;

    int intval;
}

which will hold both of them as strings (for now, I just want to print them). The tokens and items along with the grammar are defined in the following way:

%token <intval> CONST
%type <attributes> expr

%%
expr:
    expr '+' expr 
    {
        printf("%s ",$1.val);
        printf("%s \n",$3.val);
        printf("code: %s %s\n",$1.code,$3.code);
    }
expr:
    CONST 
    {
        int source=$1;
        char temp[100];
        sprintf(temp, "%d", source);
        $$.val=strcat(temp,"1");
        $$.code=temp;
        printf("val for %d is %s; code is %s\n",$1,$$.val,$$.code);
    }

%%

In flex, I set the value (intval) of the CONST to the element itself (so the val of 4 will be 4). When the second rule is applied, the program prints the value correctly. However, when the first one is applied (when the whole thing is printed), both expressions have the same val.

varn for 4 is 41; code is 41
varn for 5 is 51; code is 51
51 51 
code: 51 51

(That 1 was added just to test something, it's not part of the plan)

I can't figure out why exactly. If I change the expr to be of type int

%type <intval> expr

it works correctly.

1
$$.code=temp looks very suspect - what is the scope for temp? it possibly that means every $$.code is pointing at the same value?Chris Turner
I'm trying to convert the int value of $1 to a string, so that I can assign it to $$.code, which is char*. I also thought it's all because of some pointers, but I haven't worked with C in a long time and this was the only way I could do that conversion. Temp was used as a temporary variable to store the converted value from int to string (I got an error if I tried using $$.code directly in sprintf)tudors5
you probably want $$.code=strdup(temp); and then remember to free the memory allocated at the appropriate pointsChris Turner
It worked, thank you so much! I really need to refresh my C pointers skills!tudors5

1 Answers

0
votes

What your code is doing is not too dissimilar to the follow:

char temp[100];

strcpy(temp,"hello");
char *str1=temp;

strcpy(temp,"world");
char *str2=temp;

printf("%s %s\n",str1,str2);

both str1 and str2 are pointing at the same point in memory so you'll get the output "world world". You need to allocate memory for each string so they have their own place in memory.

And then in the "expr '+' expr" pattern, you'd free each string and create new ones to pass up the parse chain.