Hmm.
As far as I understand your grammer, you are at the very beginning of using yacc. For that, it is not bad, so I give you just some hints whow to proceed...
a. You are aware, that currently all your expressions can only be constant, because you are evaluating them at compile-time, e.g. you write in the plus-case {$$ = $1 + $3}
, and this expression is evaluated while yacc is running. If you want this to be evaluated at runtime, you need to emit the correct assembler instrutions like {emit ("add", allocReg(), $1, $3);}
where this to-be-written function emit
could at the beginning just expect register names in $1
and $3
.
b. Then if you would change the action in the number-case to load the number into a register (for which you need to do some housekeeping), that is, the action for a number would be
{reg=allocReg();
emit ("mov", reg, $$);
}
(of course you need to free all allocated Registers when they are no longer used, e.g. after they have been used in an add-operation as summands).
c. Before you can do your jump on conditions, you need so emit some compare instructions. to compare, e.g. cmp $1, $3
d. When using yacc, you transport data 'upwards' by assigning them to $$, and use $1...$n produced by other rules. This data can have different types, depending on the rules. So your idea of using a union for that is a way to do that (all goes somewhere in your grammar-file):
typedef union {
int number;
char singleChar;
VarName *var;
...
} dataVariant;
#undef YYSTYPE
#define YYSTYPE dataVariant
with this you can write in your grammar something like $$.number=$1.number. There is also a %union-construct inside yacc which is more comfortable, you can read something about it there: Lex and YACC primer