+block ::= decl_struct(strct). {
+ P->structs = add_decl_struct(P->structs, strct);
+}
+
+block ::= decl_union(u). {
+ P->unions = add_decl_union(P->unions, u);
+}
+
+block ::= decl_enum(e). {
+ P->enums = add_decl_enum(P->enums, e);
+}
+
+optional_name(n) ::= . {
+ n = NULL;
+}
+
+optional_name(n) ::= NAME(N). {
+
+ n = N;
+}
+
+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), " ", "@");
+ }
+}
+
+decl_enum(e) ::= enum_name(N) LBRACE decl_enum_items(list) RBRACE. {
+
+
+
+
+ e = init_decl_enum(N->text, list);
+ e->token = N;
+}
+
+decl_enum_items(l) ::= decl_enum_item(i). {
+
+ l = init_decl_enum_items(i);
+}
+decl_enum_items(l) ::= decl_enum_items(l_) COMMA decl_enum_item(i). {
+
+
+
+ l = add_decl_enum_item(l_, i);
+}
+
+decl_enum_item(i) ::= NAME(N) EQUALS num_exp(num). {
+
+
+
+ i = init_decl_enum_item(N->text, num);
+ i->token = N;
+}
+decl_enum_item(i) ::= NAME(N). {
+
+ i = init_decl_enum_item(N->text, NULL);
+ i->token = N;
+}
+
+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), " ", "@");
+ }
+}
+
+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), " ", "@");
+ }
+}
+
+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_ = init_decl_args(NULL);
+}
+
+decl_struct(strct) ::= STRUCT NAME(N) align_and_size(as) decl_struct_args(args). {
+
+
+
+
+ strct = init_decl_struct(N->text, args);
+ strct->align = as.pos;
+ strct->size = as.len;
+ strct->token = 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);
+}
+
+decl_union(u) ::= UNION NAME(N) align_and_size(as) decl_struct_args(args). {
+
+
+
+
+ u = init_decl_union(N->text, args);
+ u->align = as.pos;
+ u->size = as.len;
+ u->token = N;
+}
+
+const_type(type_) ::= const_type_token(T). {
+
+ type_ = init_const_type(T->type, T->text);
+ free(T);
+}
+
+constant(constant) ::= CONST const_type(type) NSNAME(T) EQUALS impl_def_val(val) EOS. {
+
+
+
+
+
+
+ constant = init_constant(type, T->text, val);
+ free(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 = init_decl_arg(init_decl_type(PSI_T_STRUCT, N->text), var);
+ def->type->token = psi_token_copy(N);
+ def->type->real.strct = init_decl_struct(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 = init_decl_arg(init_decl_type(PSI_T_UNION, N->text), var);
+ def->type->token = psi_token_copy(N);
+ def->type->real.unn = init_decl_union(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 = init_decl_arg(init_decl_type(PSI_T_ENUM, e->name), init_decl_var(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 = init_decl_arg(init_decl_type(PSI_T_FUNCTION, func_->var->name), copy_decl_var(func_->var));
+ def->type->token = psi_token_copy(func_->token);
+ def->type->real.func = init_decl(init_decl_abi("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 = init_decl(abi, func, args);
+}
+
+decl_func(func) ::= decl_arg(arg). {
+
+ func = arg;
+}
+
+decl_func(func) ::= VOID(T) NAME(N). {
+
+
+ func = init_decl_arg(
+ init_decl_type(T->type, T->text),
+ init_decl_var(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). {
+
+
+
+
+
+
+
+ decl_arg *func_ = init_decl_arg(
+ init_decl_type(T->type, T->text),
+ init_decl_var(N->text, decl_i, 0)
+ );
+ func_->type->token = T;
+ func_->var->token = N;
+ func_->token = N;
+
+ def = init_decl_arg(
+ init_decl_type(PSI_T_FUNCTION, func_->var->name),
+ copy_decl_var(func_->var)
+ );
+ def->var->pointer_level = type_i;
+ def->type->token = psi_token_copy(func_->token);
+ def->type->real.func = init_decl(init_decl_abi("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). {
+ decl_arg *func_ = init_decl_arg(
+ init_decl_type(T->type, T->text),
+ init_decl_var(N->text, decl_i, 0)
+ );
+ func_->type->token = T;
+ func_->var->token = N;
+ func_->token = N;
+
+ def = init_decl_arg(
+ init_decl_type(PSI_T_FUNCTION, func_->var->name),
+ copy_decl_var(func_->var)
+ );
+ def->var->pointer_level = type_i;
+ def->type->token = psi_token_copy(func_->token);
+ def->type->real.func = init_decl(init_decl_abi("default"), func_, args);