struct_fields yacc_ids yacc_typematch
%type type_option stringseq
%%
start: /* empty */
| typedef_struct start
| externstatic start
| yacc_union start
;
typedef_struct: ENT_TYPEDEF_STRUCT options '{' struct_fields '}' ID
{
new_structure ($1->u.s.tag, UNION_P ($1), &lexer_line,
$4, $2);
do_typedef ($6, $1, &lexer_line);
lexer_toplevel_done = 1;
}
';'
{}
| ENT_STRUCT options '{' struct_fields '}'
{
new_structure ($1->u.s.tag, UNION_P ($1), &lexer_line,
$4, $2);
lexer_toplevel_done = 1;
}
';'
{}
;
externstatic: ENT_EXTERNSTATIC options lasttype ID semiequal
{
note_variable ($4, adjust_field_type ($3, $2), $2,
&lexer_line);
}
| ENT_EXTERNSTATIC options lasttype ID ARRAY semiequal
{
note_variable ($4, create_array ($3, $5),
$2, &lexer_line);
}
| ENT_EXTERNSTATIC options lasttype ID ARRAY ARRAY semiequal
{
note_variable ($4, create_array (create_array ($3, $6),
$5),
$2, &lexer_line);
}
;
lasttype: type
{
lexer_toplevel_done = 1;
$$ = $1;
}
;
semiequal: ';'
| '='
;
yacc_union: ENT_YACCUNION options struct_fields '}' yacc_typematch
PERCENTPERCENT
{
note_yacc_type ($2, $3, $5, &lexer_line);
}
;
yacc_typematch: /* empty */
{ $$ = NULL; }
| yacc_typematch PERCENT_ID yacc_ids
{
pair_p p;
for (p = $3; p->next != NULL; p = p->next)
{
p->name = NULL;
p->type = NULL;
}
p->name = NULL;
p->type = NULL;
p->next = $1;
$$ = $3;
}
| yacc_typematch PERCENT_ID '<' ID '>' yacc_ids
{
pair_p p;
type_p newtype = NULL;
if (strcmp ($2, "type") == 0)
newtype = (type_p) 1;
for (p = $6; p->next != NULL; p = p->next)
{
p->name = $4;
p->type = newtype;
}
p->name = $4;
p->next = $1;
p->type = newtype;
$$ = $6;
}
;
yacc_ids: /* empty */
{ $$ = NULL; }
| yacc_ids ID
{
pair_p p = XCNEW (struct pair);
p->next = $1;
p->line = lexer_line;
p->opt = XNEW (struct options);
p->opt->name = "tag";
p->opt->next = NULL;
p->opt->info = (char *)$2;
$$ = p;
}
| yacc_ids CHAR
{
pair_p p = XCNEW (struct pair);
p->next = $1;
p->line = lexer_line;
p->opt = XNEW (struct options);
p->opt->name = "tag";
p->opt->next = NULL;
p->opt->info = xasprintf ("'%s'", $2);
$$ = p;
}
;
struct_fields: { $$ = NULL; }
| type optionsopt ID bitfieldopt ';' struct_fields
{
pair_p p = XNEW (struct pair);
p->type = adjust_field_type ($1, $2);
p->opt = $2;
p->name = $3;
p->next = $6;
p->line = lexer_line;
$$ = p;
}
| type optionsopt ID ARRAY ';' struct_fields
{
pair_p p = XNEW (struct pair);
p->type = adjust_field_type (create_array ($1, $4), $2);
p->opt = $2;
p->name = $3;
p->next = $6;
p->line = lexer_line;
$$ = p;
}
| type optionsopt ID ARRAY ARRAY ';' struct_fields
{
pair_p p = XNEW (struct pair);
p->type = create_array (create_array ($1, $5), $4);
p->opt = $2;
p->name = $3;
p->next = $7;
p->line = lexer_line;
$$ = p;
}
| type ':' bitfieldlen ';' struct_fields
{ $$ = $5; }
;
bitfieldopt: /* empty */
| ':' bitfieldlen
;
bitfieldlen: NUM | ID
{ }
;
type: SCALAR
{ $$ = $1; }
| ID
{ $$ = resolve_typedef ($1, &lexer_line); }
| type '*'
{ $$ = create_pointer ($1); }
| STRUCT ID '{' struct_fields '}'
{ $$ = new_structure ($2, 0, &lexer_line, $4, NULL); }
| STRUCT ID
{ $$ = find_structure ($2, 0); }
| UNION ID '{' struct_fields '}'
{ $$ = new_structure ($2, 1, &lexer_line, $4, NULL); }
| UNION ID
{ $$ = find_structure ($2, 1); }
| ENUM ID
{ $$ = create_scalar_type ($2, strlen ($2)); }
| ENUM ID '{' enum_items '}'
{ $$ = create_scalar_type ($2, strlen ($2)); }
;
enum_items: /* empty */
| ID '=' NUM ',' enum_items
{ }
| ID ',' enum_items
{ }
| ID enum_items
{ }
;
optionsopt: { $$ = NULL; }
| options { $$ = $1; }
;
options: GTY_TOKEN '(' '(' optionseqopt ')' ')'
{ $$ = $4; }
;
type_option : ALIAS
{ $$ = "ptr_alias"; }
| PARAM_IS
{ $$ = $1; }
;
option: ID
{ $$ = create_option (NULL, $1, (void *)""); }
| ID '(' stringseq ')'
{ $$ = create_option (NULL, $1, (void *)$3); }
| type_option '(' type ')'
{ $$ = create_option (NULL, $1, adjust_field_type ($3, NULL)); }
| NESTED_PTR '(' type ',' stringseq ',' stringseq ')'
{
struct nested_ptr_data d;
d.type = adjust_field_type ($3, NULL);
d.convert_to = $5;
d.convert_from = $7;
$$ = create_option (NULL, "nested_ptr",
xmemdup (&d, sizeof (d), sizeof (d)));
}
;
optionseq: option
{
$1->next = NULL;
$$ = $1;
}
| optionseq ',' option
{
$3->next = $1;
$$ = $3;
}
;
optionseqopt: { $$ = NULL; }
| optionseq { $$ = $1; }
;
stringseq: STRING
{ $$ = $1; }
| stringseq STRING
{
size_t l1 = strlen ($1);
size_t l2 = strlen ($2);
char *s = XRESIZEVEC (char, $1, l1 + l2 + 1);
memcpy (s + l1, $2, l2 + 1);
XDELETE ($2);
$$ = s;
}
;
%%