+ if (!P->types) {
+ P->types = psi_plist_init((psi_plist_dtor) psi_decl_arg_free);
+ }
+ P->types = psi_plist_add(P->types, &def);
+ switch (def->type->type) {
+ case PSI_T_STRUCT:
+ if (def->type->real.strct) {
+ if (!P->structs) {
+ P->structs = psi_plist_init((psi_plist_dtor) psi_decl_struct_free);
+ }
+ P->structs = psi_plist_add(P->structs, &def->type->real.strct);
+ }
+ break;
+ case PSI_T_UNION:
+ if (def->type->real.unn) {
+ if (!P->unions) {
+ P->unions = psi_plist_init((psi_plist_dtor) psi_decl_union_free);
+ }
+ P->unions = psi_plist_add(P->unions, &def->type->real.unn);
+ }
+ break;
+ case PSI_T_ENUM:
+ if (def->type->real.enm) {
+ if (!P->enums) {
+ P->enums = psi_plist_init((psi_plist_dtor) psi_decl_enum_free);
+ }
+ P->enums = psi_plist_add(P->enums, &def->type->real.enm);
+ }
+ break;
+ }
+}
+block ::= constant(constant). {
+ if (!P->consts) {
+ P->consts = psi_plist_init((psi_plist_dtor) psi_const_free);
+ }
+ P->consts = psi_plist_add(P->consts, &constant);
+}
+block ::= decl_struct(strct). {
+ if (!P->structs) {
+ P->structs = psi_plist_init((psi_plist_dtor) psi_decl_struct_free);
+ }
+ P->structs = psi_plist_add(P->structs, &strct);
+}
+block ::= decl_union(u). {
+ if (!P->unions) {
+ P->unions = psi_plist_init((psi_plist_dtor) psi_decl_union_free);
+ }
+ P->unions = psi_plist_add(P->unions, &u);
+}
+block ::= decl_enum(e). {
+ if (!P->enums) {
+ P->enums = psi_plist_init((psi_plist_dtor) psi_decl_enum_free);
+ }
+ P->enums = psi_plist_add(P->enums, &e);
+}
+optional_name(n) ::= . {
+ n = NULL;
+}
+optional_name(n) ::= NAME(N). {
+ n = N;
+}
+align_and_size(as) ::= . {
+ as.pos = 0;
+ as.len = 0;
+}
+align_and_size(as) ::= COLON COLON LPAREN NUMBER(A) COMMA NUMBER(S) RPAREN. {
+ as.pos = atol(A->text);
+ as.len = atol(S->text);
+ free(A);
+ free(S);
+}
+enum_name(n) ::= ENUM(E) optional_name(N). {
+ if (N) {
+ n = N;
+ free(E);
+ } else {
+ char digest[17];
+ psi_token_hash(E, digest);
+ n = psi_token_translit(psi_token_append(E, 1, digest), " ", "@");
+ }
+}
+struct_name(n) ::= STRUCT(S) optional_name(N). {
+ if (N) {
+ n = N;
+ free(S);
+ } else {
+ char digest[17];
+ psi_token_hash(S, digest);
+ n = psi_token_translit(psi_token_append(S, 1, digest), " ", "@");
+ }
+}
+union_name(n) ::= UNION(U) optional_name(N). {
+ if (N) {
+ n = N;
+ free(U);
+ } else {
+ char digest[17];
+ psi_token_hash(U, digest);
+ n = psi_token_translit(psi_token_append(U, 1, digest), " ", "@");
+ }
+}
+decl_enum(e) ::= enum_name(N) LBRACE decl_enum_items(list) RBRACE. {
+ e = psi_decl_enum_init(N->text, list);
+ e->token = N;
+}
+decl_enum_items(l) ::= decl_enum_item(i). {
+ l = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_decl_enum_item_free),
+ &i);
+}
+decl_enum_items(l) ::= decl_enum_items(l_) COMMA decl_enum_item(i). {
+ l = psi_plist_add(l_, &i);
+}
+decl_enum_item(i) ::= NAME(N) EQUALS num_exp(num). {
+ i = psi_decl_enum_item_init(N->text, num);
+ i->token = N;
+}
+decl_enum_item(i) ::= NAME(N). {
+ i = psi_decl_enum_item_init(N->text, NULL);
+ i->token = N;
+}
+decl_struct_args_block(args_) ::= LBRACE struct_args(args) RBRACE. {
+ args_ = args;
+}
+decl_struct_args(args_) ::= decl_struct_args_block(args). {
+ args_ = args;
+}
+decl_struct_args(args_) ::= EOS. {
+ args_ = psi_plist_init((psi_plist_dtor) psi_decl_arg_free);
+}
+decl_struct(strct) ::= STRUCT NAME(N) align_and_size(as) decl_struct_args(args). {
+ strct = psi_decl_struct_init(N->text, args);
+ strct->align = as.pos;
+ strct->size = as.len;
+ strct->token = N;
+}
+decl_union(u) ::= UNION NAME(N) align_and_size(as) decl_struct_args(args). {
+ u = psi_decl_union_init(N->text, args);
+ u->align = as.pos;
+ u->size = as.len;
+ u->token = N;
+}
+const_type(type_) ::= const_type_token(T). {
+ type_ = psi_const_type_init(T->type, T->text);
+ free(T);
+}
+constant(constant) ::= CONST const_type(type) NSNAME(T) EQUALS impl_def_val(val) EOS. {
+ constant = psi_const_init(type, T->text, val);
+ constant->token = T;
+}
+decl_typedef(def) ::= TYPEDEF(T) decl_typedef_body(def_) EOS. {
+ def = def_;
+ def->token = T;
+}
+decl_typedef_body_ex(def) ::= struct_name(N) align_and_size(as) decl_struct_args_block(args) decl_var(var). {
+ def = psi_decl_arg_init(psi_decl_type_init(PSI_T_STRUCT, N->text), var);
+ def->type->token = psi_token_copy(N);
+ def->type->real.strct = psi_decl_struct_init(N->text, args);
+ def->type->real.strct->token = N;
+ def->type->real.strct->align = as.pos;
+ def->type->real.strct->size = as.len;
+}
+decl_typedef_body_ex(def) ::= union_name(N) align_and_size(as) decl_struct_args_block(args) decl_var(var). {
+ def = psi_decl_arg_init(psi_decl_type_init(PSI_T_UNION, N->text), var);
+ def->type->token = psi_token_copy(N);
+ def->type->real.unn = psi_decl_union_init(N->text, args);
+ def->type->real.unn->token = N;
+ def->type->real.unn->align = as.pos;
+ def->type->real.unn->size = as.len;
+}
+decl_typedef_body_ex(def) ::= decl_enum(e) NAME(ALIAS). {
+ def = psi_decl_arg_init(psi_decl_type_init(PSI_T_ENUM, e->name), psi_decl_var_init(ALIAS->text, 0, 0));
+ def->var->token = ALIAS;
+ def->type->token = psi_token_copy(e->token);
+ def->type->real.enm = e;
+}
+decl_typedef_body(def) ::= decl_typedef_body_ex(def_). {
+ def = def_;
+}
+decl_typedef_body_fn_args(args) ::= LPAREN decl_args(args_) RPAREN. {
+ args = args_;
+}
+decl_typedef_body(def) ::= decl_func(func_) decl_typedef_body_fn_args(args). {
+ def = psi_decl_arg_init(psi_decl_type_init(PSI_T_FUNCTION, func_->var->name), psi_decl_var_copy(func_->var));
+ def->type->token = psi_token_copy(func_->token);
+ def->type->real.func = psi_decl_init(psi_decl_abi_init("default"), func_, args);
+}
+decl_typedef_body(def) ::= decl_arg(arg). {
+ def = arg;
+}
+decl(decl) ::= decl_abi(abi) decl_func(func) LPAREN decl_args(args) RPAREN EOS. {
+ decl = psi_decl_init(abi, func, args);
+}
+decl(decl) ::= decl_abi(abi) decl_func(func) LPAREN decl_args(args) COMMA ELLIPSIS RPAREN EOS. {
+ decl = psi_decl_init(abi, func, args);
+ decl->varargs = 1;
+}
+decl_func(func) ::= decl_arg(arg). {
+ func = arg;
+}
+decl_func(func) ::= VOID(T) NAME(N). {
+ func = psi_decl_arg_init(
+ psi_decl_type_init(T->type, T->text),
+ psi_decl_var_init(N->text, 0, 0)
+ );
+ func->type->token = T;
+ func->var->token = N;
+ func->token = N;
+}
+decl_typedef_body(def) ::= VOID(T) indirection(decl_i) LPAREN indirection(type_i) NAME(N) RPAREN decl_typedef_body_fn_args(args). {
+ struct psi_decl_arg *func_ = psi_decl_arg_init(
+ psi_decl_type_init(T->type, T->text),
+ psi_decl_var_init(N->text, decl_i, 0)
+ );
+ func_->type->token = T;
+ func_->var->token = N;
+ func_->token = N;
+ def = psi_decl_arg_init(
+ psi_decl_type_init(PSI_T_FUNCTION, func_->var->name),
+ psi_decl_var_copy(func_->var)
+ );
+ def->var->pointer_level = type_i;
+ def->type->token = psi_token_copy(func_->token);
+ def->type->real.func = psi_decl_init(psi_decl_abi_init("default"), func_, args);
+}
+decl_typedef_body(def) ::= CONST VOID(T) pointers(decl_i) LPAREN indirection(type_i) NAME(N) RPAREN decl_typedef_body_fn_args(args). {
+ struct psi_decl_arg *func_ = psi_decl_arg_init(
+ psi_decl_type_init(T->type, T->text),
+ psi_decl_var_init(N->text, decl_i, 0)
+ );
+ func_->type->token = T;
+ func_->var->token = N;
+ func_->token = N;
+ def = psi_decl_arg_init(
+ psi_decl_type_init(PSI_T_FUNCTION, func_->var->name),
+ psi_decl_var_copy(func_->var)
+ );
+ def->var->pointer_level = type_i;
+ def->type->token = psi_token_copy(func_->token);
+ def->type->real.func = psi_decl_init(psi_decl_abi_init("default"), func_, args);