+cpp_macro_sig(sig) ::= NO_WHITESPACE LPAREN cpp_macro_sig_args(args) RPAREN. {
+ sig = args;
+}
+cpp_macro_sig_args(args) ::= . {
+ args = NULL;
+}
+cpp_macro_sig_args(args) ::= NAME(arg). {
+ args = psi_plist_add(psi_plist_init((void (*)(void *)) psi_token_free), &arg);
+}
+cpp_macro_sig_args(args) ::= cpp_macro_sig_args(args_) COMMA NAME(arg). {
+ args = psi_plist_add(args_, &arg);
+}
+cpp_macro_decl(macro) ::= cpp_macro_decl_tokens(tokens). {
+ macro = psi_cpp_macro_decl_init(NULL, tokens, NULL);
+}
+cpp_macro_decl_tokens(tokens) ::= ANY(T). {
+ tokens = psi_plist_add(psi_plist_init((void (*)(void *)) psi_token_free), &T);
+}
+cpp_macro_decl_tokens(tokens) ::= cpp_macro_decl_tokens(tokens_) ANY(T). {
+ tokens = psi_plist_add(tokens_, &T);
+}
+cpp_exp(exp) ::= IF(T) cpp_macro_exp(macro). {
+ exp = psi_cpp_exp_init(T->type, macro);
+ exp->token = T;
+}
+cpp_exp(exp) ::= ELIF(T) cpp_macro_exp(macro). {
+ exp = psi_cpp_exp_init(T->type, macro);
+ exp->token = T;
+}
+cpp_macro_exp(exp) ::= LPAREN(L) cpp_macro_exp(exp_) RPAREN. {
+ exp = psi_num_exp_init_unary(L->type, exp_);
+ exp->token = L;
+}
+cpp_macro_exp(exp) ::= unary_op_token(OP) cpp_macro_exp(exp_). {
+ exp = psi_num_exp_init_unary(OP->type, exp_);
+ exp->token = OP;
+}
+cpp_macro_exp(exp) ::= cpp_macro_exp(lhs) binary_op_token(OP) cpp_macro_exp(rhs). {
+ exp = psi_num_exp_init_binary(OP->type, lhs, rhs);
+ exp->token = OP;
+}
+cpp_macro_exp(exp) ::= DEFINED NAME(N). {
+ {
+ uint8_t exists = zend_hash_str_exists(&P->cpp.defs, N->text, N->size);
+ exp = psi_num_exp_init_num(psi_number_init(PSI_T_UINT8, &exists));
+ exp->token = N;
+ }
+}
+cpp_macro_exp(exp) ::= DEFINED LPAREN NAME(N) RPAREN. {
+ {
+ uint8_t exists = zend_hash_str_exists(&P->cpp.defs, N->text, N->size);
+ exp = psi_num_exp_init_num(psi_number_init(PSI_T_UINT8, &exists));
+ exp->token = N;
+ }
+}
+cpp_macro_exp(exp) ::= number_token(tok). {
+ exp = psi_num_exp_init_num(psi_number_init(tok->type, tok->text));
+ exp->token = tok;
+ exp->data.n->token = psi_token_copy(tok);
+}
+cpp_macro_exp(exp) ::= NAME(N). {
+ exp = psi_num_exp_init_num(psi_number_init(PSI_T_DEFINE, N->text));
+ exp->token = N;
+ exp->data.n->token = psi_token_copy(N);
+}
+cpp_macro_exp(exp) ::= NAME(N) LPAREN cpp_macro_call_args(args) RPAREN. {
+ exp = psi_num_exp_init_num(psi_number_init(PSI_T_FUNCTION,
+ psi_cpp_macro_call_init(N->text, args)));
+ exp->token = N;
+}
+cpp_macro_call_args(args) ::= . {
+ args = NULL;
+}
+cpp_macro_call_args(args) ::= cpp_macro_exp(arg). {
+ args = psi_plist_add(psi_plist_init((void (*)(void *)) psi_num_exp_free), &arg);
+}
+cpp_macro_call_args(args) ::= cpp_macro_call_args(args_) COMMA cpp_macro_exp(arg). {
+ args = psi_plist_add(args_, &arg);
+}
+block ::= LIB(token) QUOTED_STRING(libname) EOS. {
+ if (P->file.ln) {
+ P->error(PSI_DATA(P), token, PSI_WARNING, "Extra 'lib %s' statement has no effect", libname->text);
+ } else {
+ P->file.ln = strndup(libname->text + 1, libname->size - 2);
+ }
+ free(libname);
+ free(token);
+}
+block ::= decl(decl). {
+ if (!P->decls) {
+ P->decls = psi_plist_init((psi_plist_dtor) psi_decl_free);
+ }
+ P->decls = psi_plist_add(P->decls, &decl);
+}
+block ::= impl(impl). {
+ if (!P->impls) {
+ P->impls = psi_plist_init((psi_plist_dtor) psi_impl_free);
+ }
+ P->impls = psi_plist_add(P->impls, &impl);
+}
+block ::= decl_typedef(def). {
+ 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_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_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_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);