I have two rules in my large grammar:
indexed_component
: name '(' val_list ')'
;
val_list
: val
| val_list ',' val
;
How can access the value of 'name' within val_list ?
I know I can use a global variable, but this is highly recursive so I would have to use a stack and I want to avoid the bother.
What you want is what is called an inherited attribute, which, unfortunately, yacc and bison don't really support. You can "hack" it by accessing attributes with negative indexes, but that is error prone.
If you want to try using btyacc, it has some syntactic sugar to help with this (allowing them to be typechecked, at least). You would write this as
indexed_component : name '(' val_list($1) ')' ;
val_list($name) : val
| val_list($name) ',' val ;
and then in the actions on val_list
you could access $name
. With a %union
you would need to declare this properly with %type
:
%union {
char *str;
struct list *list;
}
%type <str> name // name gives a string
%type <list> val_list(<str>) // val_list takes a string and gives a list
as I mentioned, this is just syntactic sugar in btyacc -- it ends up getting converted into inline actions with accesses to $0. So it will get converted to:
indexed_component : name '(' { $<str>$ = $1; } val_list ')' ;
val_list : val
| val_list ',' val ;
and uses of $name
in the val_list actions would become $<str>0
;
The way this works is that $0
ends up being whatever is left on top of the yacc stack when the val_list
rule is reduced and the values for the RHS of the rule are (notionally) popped -- it is the value for the last thing immediately before val_list
on the RHS of whatever rule val_list
appears on the RHS of.