1
votes

In order to handle the grammar rule:

type            : ARRAY '[' integer_constant RANGE integer_constant ']' OF stype { $$ = $8 }
                | stype { $$ = $1 }
                ;

I need to pass up the type attribute (as I'm doing now) but I also need to pass up the range of the array in order to check array bounds. I've tried all kinds of ways to use a struct in order to achieve something like:

type            : ARRAY '[' integer_constant RANGE integer_constant ']' OF stype { $$.type = $8; $$.range[0] = $3; $$.range[1] = $5; }
                | stype { $$.type = $1 }
                ;

But everything leads to errors and segfaults and I'm having a tough time finding the correct way to handle this

Can anyone point me in the right direction? Thanks in advance.

parse.y: http://pastebin.com/XUUqG35s

2

2 Answers

2
votes

type and stype are declared to be the attr member of the union, which is of type node*. Consequently, in the context of an action for either of these non-terminals, $$ will be replaced with something like x.attr (that's just an illustration, don't take it too literally.). Similarly in the first action, $8 will be replaced with something like yystack[top-8].attr, because $8 also has the tag attr, being an stype.

So $$.type (or, indeed, $$.<anything>) must be a syntax error. attr is a pointer so it could be that $$-><something> is correct but I can't tell without seeing the definition of node.

Also, in the stype rules, you set, eg., $$ = "INT", but $$ is of type node*, not char* (unless, of course, node is a typedef for char, but that seems wrong.) It seems likely that eventually that will result in a segfault, when you later treat the value as a pointer to a node.

It's really not clear to me what you think $$.range might mean. Maybe you need to show more of your headers.

1
votes

In addition to rici's answer and more directly answering the question in your title, multiple attributes are typically passed through a struct, so if you'd change the value associated with the type non-terminal to for example ctype (%type <ctype> type) and stype to type (%type <type> stype) (which I think was your intention) and then add the following to your %union

struct { int is_array, low, high; char * type; } ctype;

then you can change the definition of the type non-terminal to

type
:    ARRAY '[' integer_constant RANGE integer_constant ']' OF stype
     { $$.is_array = 1; $$.low = $3; $$.high = $5; $$.type = $8; }
|    stype
     { $$.is_array = 0; $$.low = $$.high = -1; $$.type = $1; }
;

Of course more changes have to be made to correctly handle the new ctype, but this is typically the way to propagate multiple attributes up the parser stack.