}
return 1;
}
-static inline decl_arg *locate_decl_var_arg(decl_var *var, decl_args *args, decl_arg *func) {
+static inline decl_arg *locate_decl_arg(decl_args *args, const char *name) {
size_t i;
if (args) for (i = 0; i < args->count; ++i) {
decl_arg *arg = args->args[i];
- if (!strcmp(var->name, arg->var->name)) {
- ZEND_ASSERT(!var->arg || var->arg == arg);
- return var->arg = arg;
+ if (!strcmp(name, arg->var->name)) {
+ return arg;
}
}
+
+ return NULL;
+}
+static inline decl_arg *locate_decl_var_arg(decl_var *var, decl_args *args, decl_arg *func) {
+ decl_arg *arg = locate_decl_arg(args, var->name);
+
+ if (arg) {
+ ZEND_ASSERT(!var->arg || var->arg == arg);
+ return var->arg = arg;
+ }
+
if (func && !strcmp(var->name, func->var->name)) {
return var->arg = func;
}
return NULL;
}
-static inline int validate_let_func(struct psi_data *data, let_func *func, impl *impl) {
- if (impl->func->args) {
- if (!locate_impl_var_arg(func->var, impl->func->args)) {
- data->error(data, func->var->token, PSI_WARNING,
- "Unknown variable '$%s' of `let` statement"
- " for cast '%s' of implementation '%s'",
- func->var->name, func->name, impl->func->name);
+static inline int validate_let_val(struct psi_data *data, let_val *val, decl_var *let_var, impl *impl);
+
+static inline const char *locate_let_val_varname(let_val *val) {
+ if (val) {
+ switch (val->kind) {
+ case PSI_LET_CALLBACK:
+ return &val->data.callback->func->var->name[1];
+ case PSI_LET_FUNC:
+ return &val->data.func->var->name[1];
+ default:
+ break;
+ }
+ }
+ return NULL;
+}
+
+static inline int validate_let_func(struct psi_data *data, let_func *func, decl_var *let_var, impl *impl) {
+ if (func->outer) {
+ decl_type *var_typ = real_decl_type(let_var->arg->type);
+
+ switch (var_typ->type) {
+ case PSI_T_STRUCT:
+ func->ref = locate_decl_arg(var_typ->real.strct->args, &func->var->name[1]);
+ break;
+ case PSI_T_UNION:
+ func->ref = locate_decl_arg(var_typ->real.unn->args, &func->var->name[1]);
+ break;
+ default:
+ data->error(data, let_var->token, PSI_WARNING,
+ "Inner let statement's values must refer to a structure type, got '%s' for '%s'",
+ real_decl_type(let_var->arg->type)->name, let_var->name);
return 0;
}
}
+ if (impl->func->args) {
+ locate_impl_var_arg(func->var, impl->func->args);
+ }
+ if (!func->var->arg && !func->ref) {
+ data->error(data, func->var->token, PSI_WARNING,
+ "Unknown variable '$%s' of `let` statement"
+ " for cast '%s' of implementation '%s'",
+ func->var->name, func->name, impl->func->name);
+ return 0;
+ }
switch (func->type) {
case PSI_T_BOOLVAL: func->handler = psi_let_boolval; break;
case PSI_T_INTVAL: func->handler = psi_let_intval; break;
case PSI_T_ARRVAL: func->handler = psi_let_arrval; break;
case PSI_T_OBJVAL: func->handler = psi_let_objval; break;
case PSI_T_ZVAL: func->handler = psi_let_zval; break;
+ case PSI_T_VOID: func->handler = psi_let_void; break;
EMPTY_SWITCH_DEFAULT_CASE();
}
+
+ if (func->inner && func->ref) {
+ size_t i;
+ decl_type *var_typ = real_decl_type(let_var->arg->type);
+
+ switch (var_typ->type) {
+ case PSI_T_STRUCT:
+ case PSI_T_UNION:
+ break;
+ default:
+ data->error(data, let_var->token, PSI_WARNING,
+ "Inner let statement's values must refer to a structure type, got '%s' for '%s'",
+ real_decl_type(let_var->arg->type)->name, let_var->name);
+ return 0;
+ }
+
+ for (i = 0; i < func->inner->count; ++i) {
+ let_val *inner = func->inner->vals[i];
+ let_val *outer = func->outer;
+ const char *name = locate_let_val_varname(inner);
+ decl_arg *sub_arg;
+
+ if (name) {
+ sub_arg = locate_decl_arg(var_typ->real.strct->args, name);
+ }
+ if (!name || !sub_arg) {
+ data->error(data, let_var->token, PSI_WARNING,
+ "Unknown variable '%s' of '%s'",
+ name,
+ var_typ->real.strct->name);
+ return 0;
+ }
+ if (!validate_let_val(data, inner, sub_arg->var, impl)) {
+ return 0;
+ }
+ }
+ }
return 1;
}
decl *cb_func;
decl_type *cb_type = real_decl_type(cb_var->arg->type);
- if (!validate_let_func(data, cb->func, impl)) {
+ if (!validate_let_func(data, cb->func, cb_var, impl)) {
return 0;
}
return 1;
}
+static inline int validate_let_val(struct psi_data *data, let_val *val, decl_var *let_var, impl *impl) {
+
+ switch (val->kind) {
+ case PSI_LET_NULL:
+ break;
+ case PSI_LET_TMP:
+ if (!let_var) {
+ data->error(data, NULL, PSI_WARNING,
+ "Ivalid let statement value of implementation '%s'",
+ impl->func->name);
+ return 0;
+ }
+ /* e.g. let bar = &strval($bar); // decl_arg(char **bar) */
+ /* e.g. let foo = *bar; */
+ let_var->pointer_level = val->data.var->pointer_level;
+ let_var->arg = init_decl_arg(
+ init_decl_type(
+ real_decl_type(val->data.var->arg->type)->type,
+ real_decl_type(val->data.var->arg->type)->name),
+ init_decl_var(
+ let_var->name,
+ let_var->pointer_level,
+ let_var->array_size));
+ break;
+ case PSI_LET_NUMEXP:
+ if (!validate_num_exp(data, val->data.num, impl->decl->args, impl->decl->func, NULL)) {
+ return 0;
+ }
+ break;
+ case PSI_LET_CALLOC:
+ if (!validate_num_exp(data, val->data.alloc->nmemb, impl->decl->args, impl->decl->func, NULL)) {
+ return 0;
+ }
+ if (!validate_num_exp(data, val->data.alloc->size, impl->decl->args, impl->decl->func, NULL)) {
+ return 0;
+ }
+ break;
+ case PSI_LET_CALLBACK:
+ if (!let_var) {
+ data->error(data, NULL, PSI_WARNING,
+ "Ivalid let statement value of implementation '%s'",
+ impl->func->name);
+ return 0;
+ }
+ if (val->data.callback->func->inner) {
+ size_t i;
+
+ for (i = 0; i < val->data.callback->func->inner->count; ++i) {
+ let_val *inner = val->data.callback->func->inner->vals[i];
+ switch (inner->kind) {
+ case PSI_LET_FUNC:
+ inner->data.func->outer = val;
+ break;
+ case PSI_LET_CALLBACK:
+ inner->data.callback->func->outer = val;
+ break;
+ }
+ }
+ }
+ if (!validate_let_callback(data, let_var, val->data.callback, impl)) {
+ return 0;
+ }
+ break;
+ case PSI_LET_FUNC:
+ if (val->data.func->inner) {
+ size_t i;
+
+ for (i = 0; i < val->data.func->inner->count; ++i) {
+ let_val *inner = val->data.func->inner->vals[i];
+ switch (inner->kind) {
+ case PSI_LET_FUNC:
+ inner->data.func->outer = val;
+ break;
+ case PSI_LET_CALLBACK:
+ inner->data.callback->func->outer = val;
+ break;
+ }
+ }
+ }
+
+ if (!validate_let_func(data, val->data.func, let_var, impl)) {
+ return 0;
+ }
+ break;
+ }
+
+ return 1;
+}
+
static inline int validate_impl_let_stmts(struct psi_data *data, impl *impl) {
size_t i, j;
/* we can have multiple let stmts */
return 0;
}
- switch (let->val->kind) {
- case PSI_LET_NULL:
- break;
- case PSI_LET_TMP:
- /* e.g. let bar = &strval($bar); // decl_arg(char **bar) */
- /* e.g. let foo = *bar; */
- let->var->pointer_level = let->val->data.var->pointer_level;
- let->var->arg = init_decl_arg(
- init_decl_type(
- real_decl_type(let->val->data.var->arg->type)->type,
- real_decl_type(let->val->data.var->arg->type)->name),
- init_decl_var(
- let->var->name,
- let->var->pointer_level,
- let->var->array_size));
- break;
- case PSI_LET_NUMEXP:
- if (!validate_num_exp(data, let->val->data.num, impl->decl->args, impl->decl->func, NULL)) {
- return 0;
- }
- break;
- case PSI_LET_CALLOC:
- if (!validate_num_exp(data, let->val->data.alloc->nmemb, impl->decl->args, impl->decl->func, NULL)) {
- return 0;
- }
- if (!validate_num_exp(data, let->val->data.alloc->size, impl->decl->args, impl->decl->func, NULL)) {
- return 0;
- }
- break;
- case PSI_LET_CALLBACK:
- if (!validate_let_callback(data, let->var, let->val->data.callback, impl)) {
- return 0;
- }
- break;
- case PSI_LET_FUNC:
- if (!validate_let_func(data, let->val->data.func, impl)) {
- return 0;
- }
- break;
+ if (!validate_let_val(data, let->val, let->var, impl)) {
+ return 0;
}
}
-
/* check that we have a let stmt for every decl arg */
if (impl->decl->args) for (i = 0; i < impl->decl->args->count; ++i) {
decl_arg *darg = impl->decl->args->args[i];
decl_structs *check_structs = P->structs;
decl_unions *check_unions = P->unions;
decl_enums *check_enums = P->enums;
- unsigned silent = C->flags & PSI_PARSER_SILENT;
+ unsigned flags = C->flags;
C->data = realloc(C->data, C->count * sizeof(*C->data));
D = psi_data_exchange(&C->data[count], PSI_DATA(P));
#define CHECK_TOTAL (CHECK_COUNT(defs) + CHECK_COUNT(structs) + CHECK_COUNT(enums))
#define CHECK_COUNT(of) (check_ ##of ? check_ ##of->count : 0)
- if (!silent) {
+ if (!(flags & PSI_PARSER_SILENT)) {
/* no warnings on first round */
C->flags |= PSI_PARSER_SILENT;
}
REVALIDATE(unions);
REVALIDATE(enums);
- if (check_round == 0 && !silent) {
- C->flags &= ~PSI_PARSER_SILENT;
+ if (check_round == 0 && !(flags & PSI_PARSER_SILENT)) {
+ C->flags ^= PSI_PARSER_SILENT;
}
}
+ C->flags = flags;
if (D->consts) {
for (i = 0; i < D->consts->count; ++i) {
#include "parser.h"
}
-%include { void psi_error(int, const char *, int, const char *, ...); }
+%include {void psi_error(int, const char *, int, const char *, ...);}
+
+
+
%name psi_parser_proc_
%token_prefix PSI_T_
%token_type {struct psi_token *}
%token_destructor {free($$);}
%default_destructor {(void)P;}
%extra_argument {struct psi_parser *P}
-%syntax_error { ++P->errors; if (TOKEN && TOKEN->type != PSI_T_EOF) { psi_error(PSI_WARNING, TOKEN->file, TOKEN->line, "PSI syntax error: Unexpected token '%s'", TOKEN->text); } else { psi_error(PSI_WARNING, P->psi.file.fn, P->line, "PSI syntax error: Unexpected end of input"); } }
+
+
+%syntax_error { ++P->errors; if (TOKEN && TOKEN->type != PSI_T_EOF) { psi_error(PSI_WARNING, TOKEN->file, TOKEN->line, "PSI syntax error: Unexpected token '%s' at pos %u", TOKEN->text, TOKEN->col); } else { psi_error(PSI_WARNING, P->psi.file.fn, P->line, "PSI syntax error: Unexpected end of input"); }}
%nonassoc NAME.
%left PLUS MINUS.
%left SLASH ASTERISK.
%fallback NAME TEMP FREE SET LET RETURN CALLOC CALLBACK ZVAL LIB STRING.
+
%token_class const_type_token BOOL INT FLOAT STRING.
%token_class decl_type_token FLOAT DOUBLE INT8 UINT8 INT16 UINT16 INT32 UINT32 INT64 UINT64 NAME.
%token_class impl_def_val_token NULL NUMBER TRUE FALSE QUOTED_STRING.
%token_class let_func_token ZVAL OBJVAL ARRVAL PATHVAL STRLEN STRVAL FLOATVAL INTVAL BOOLVAL.
%token_class set_func_token TO_OBJECT TO_ARRAY TO_STRING TO_INT TO_FLOAT TO_BOOL ZVAL VOID.
%token_class impl_type_token VOID MIXED BOOL INT FLOAT STRING ARRAY OBJECT CALLABLE.
+
%type decl_enum {decl_enum *}
%destructor decl_enum {free_decl_enum($$);}
%type decl_enum_items {decl_enum_items*}
%destructor callback_args {free_set_values($$);}
%type let_val {let_val*}
%destructor let_val {free_let_val($$);}
+%type let_vals {let_vals*}
+%destructor let_vals {free_let_vals($$);}
%type set_stmt {set_stmt*}
%destructor set_stmt {free_set_stmt($$);}
%type set_value {set_value*}
%type reference {char}
%type indirection {unsigned}
%type pointers {unsigned}
+
file ::= blocks.
blocks ::= block.
blocks ::= blocks block.
+
block ::= EOF.
block ::= EOS.
+
block ::= LIB(token) QUOTED_STRING(libname) EOS. {
if (P->psi.file.ln) {
P->error(P, token, PSI_WARNING, "Extra 'lib %s' statement has no effect", libname->text);
block ::= decl(decl). {
P->decls = add_decl(P->decls, decl);
}
+
block ::= impl(impl). {
P->impls = add_impl(P->impls, impl);
}
+
block ::= decl_typedef(def). {
P->defs = add_decl_typedef(P->defs, def);
switch (def->type->type) {
break;
}
}
+
block ::= constant(constant). {
P->consts = add_constant(P->consts, constant);
}
+
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->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->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->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)
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->type->token = psi_token_copy(func_->token);
def->type->real.func = init_decl(init_decl_abi("default"), func_, args);
}
+
decl_abi(abi) ::= NAME(T). {
+
abi = init_decl_abi(T->text);
abi->token = T;
}
+
decl_var(var) ::= indirection(p) NAME(T). {
+
+
var = init_decl_var(T->text, p, 0);
var->token = T;
}
decl_var(var) ::= indirection(p) NAME(T) LBRACKET NUMBER(D) RBRACKET. {
+
+
+
+
+
var = init_decl_var(T->text, p+1, atol(D->text));
var->token = T;
free(D);
}
+
decl_vars(vars) ::= decl_var(var). {
+
vars = init_decl_vars(var);
}
decl_vars(vars) ::= decl_vars(vars_) COMMA decl_var(var). {
+
+
+
vars = add_decl_var(vars_, var);
}
+
decl_arg(arg_) ::= const_decl_type(type) decl_var(var). {
+
+
arg_ = init_decl_arg(type, var);
}
decl_typedef_body(def) ::= const_decl_type(type_) indirection(decl_i) LPAREN indirection(type_i) NAME(N) RPAREN decl_typedef_body_fn_args(args). {
+
+
+
+
+
+
+
decl_arg *func_ = init_decl_arg(
type_,
init_decl_var(N->text, decl_i, 0)
);
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->type->token = psi_token_copy(func_->token);
def->type->real.func = init_decl(init_decl_abi("default"), func_, args);
}
+
+
decl_arg(arg_) ::= VOID(T) pointers(p) NAME(N). {
+
+
+
arg_ = init_decl_arg(
init_decl_type(T->type, T->text),
init_decl_var(N->text, p, 0)
arg_->token = N;
}
decl_arg(arg_) ::= CONST VOID(T) pointers(p) NAME(N). {
+
+
+
+
arg_ = init_decl_arg(
init_decl_type(T->type, T->text),
init_decl_var(N->text, p, 0)
arg_->var->token = N;
arg_->token = N;
}
+
decl_args ::= .
decl_args ::= VOID.
decl_args(args) ::= decl_arg(arg). {
+
args = init_decl_args(arg);
}
decl_args(args) ::= decl_args(args_) COMMA decl_arg(arg). {
+
+
+
args = add_decl_arg(args_, arg);
}
decl_args(args) ::= decl_args(args_) COMMA ELLIPSIS. {
+
+
+
args = args_;
args->varargs = 1;
}
+
struct_args(args) ::= struct_arg(arg). {
+
args = init_decl_args(arg);
}
struct_args(args) ::= struct_args(args_) struct_arg(arg). {
+
+
args = add_decl_arg(args_, arg);
}
+
struct_arg(arg_) ::= decl_typedef_body_ex(def) EOS. {
+
+
arg_ = def;
switch (def->type->type) {
case PSI_T_STRUCT:
}
}
struct_arg(arg) ::= decl_arg(arg_) struct_layout(layout_) EOS. {
+
+
+
arg_->layout = layout_;
arg = arg_;
}
+
struct_layout(layout) ::= . {
layout = NULL;
}
struct_layout(layout) ::= COLON COLON LPAREN NUMBER(POS) COMMA NUMBER(SIZ) RPAREN. {
+
+
+
+
+
+
+
layout = init_decl_struct_layout(atol(POS->text), atol(SIZ->text));
free(POS);
free(SIZ);
}
+
+
decl_scalar_type(type_) ::= CHAR(C). {
+
type_ = C;
}
decl_scalar_type(type_) ::= SHORT(S) decl_scalar_type_short(s). {
+
+
if (s) {
type_ = psi_token_cat(2, S, s);
free(S);
decl_scalar_type_short(s) ::= . {
s = NULL;
}
+
decl_scalar_type_short(s) ::= INT(I). {
+
s = I;
}
decl_scalar_type(type_) ::= INT(I). {
+
type_ = I;
}
decl_scalar_type(type_) ::= LONG(L) decl_scalar_type_long(l). {
+
+
if (l) {
type_ = psi_token_cat(2, L, l);
free(L);
l = NULL;
}
decl_scalar_type_long(l) ::= DOUBLE(D). {
+
l = D;
}
decl_scalar_type_long(l) ::= LONG(L) decl_scalar_type_long_long(ll). {
+
+
if (ll) {
l = psi_token_cat(2, L, ll);
free(L);
ll = NULL;
}
decl_scalar_type_long_long(ll) ::= INT(I). {
+
ll = I;
}
decl_type(type_) ::= UNSIGNED(U) decl_scalar_type(N). {
+
+
struct psi_token *T = psi_token_cat(2, U, N);
type_ = init_decl_type(T->type, T->text);
type_->token = T;
free(N);
}
decl_type(type_) ::= SIGNED(S) decl_scalar_type(N). {
+
+
struct psi_token *T = psi_token_cat(2, S, N);
type_ = init_decl_type(T->type, T->text);
type_->token = T;
free(N);
}
decl_type(type_) ::= UNSIGNED(U). {
+
type_ = init_decl_type(PSI_T_NAME, U->text);
type_->token = U;
}
decl_type(type_) ::= SIGNED(S). {
+
type_ = init_decl_type(PSI_T_NAME, S->text);
type_->token = S;
}
decl_type(type_) ::= decl_scalar_type(N). {
+
type_ = init_decl_type(N->type, N->text);
type_->token = N;
}
+
decl_type(type_) ::= STRUCT(S) NAME(T). {
+
+
type_ = init_decl_type(S->type, T->text);
type_->token = T;
free(S);
}
decl_type(type_) ::= UNION(U) NAME(T). {
+
+
type_ = init_decl_type(U->type, T->text);
type_->token = T;
free(U);
}
decl_type(type_) ::= ENUM(E) NAME(T). {
+
+
type_ = init_decl_type(E->type, T->text);
type_->token = T;
free(E);
}
decl_type(type_) ::= decl_type_token(T). {
+
type_ = init_decl_type(T->type, T->text);
type_->token = T;
}
+
+
const_decl_type(type) ::= decl_type(type_). {
+
type = type_;
}
const_decl_type(type) ::= CONST decl_type(type_). {
+
+
type = type_;
}
+
impl(impl) ::= impl_func(func) LBRACE impl_stmts(stmts) RBRACE. {
+
+
+
+
impl = init_impl(func, stmts);
}
+
impl_func(func) ::= FUNCTION reference(r) NSNAME(NAME) impl_args(args) COLON impl_type(type). {
+
+
+
+
+
+
func = init_impl_func(NAME->text, args, type, r);
func->token = NAME;
}
+
impl_def_val(def) ::= impl_def_val_token(T). {
+
def = init_impl_def_val(T->type, T->text);
free(T);
}
+
impl_var(var) ::= reference(r) DOLLAR_NAME(T). {
+
+
var = init_impl_var(T->text, r);
var->token = T;
}
+
impl_arg(arg) ::= impl_type(type) impl_var(var). {
+
+
arg = init_impl_arg(type, var, NULL);
}
impl_arg(arg) ::= impl_type(type) impl_var(var) EQUALS impl_def_val(def). {
+
+
+
+
arg = init_impl_arg(type, var, def);
}
+
impl_args(args) ::= LPAREN RPAREN. {
+
+
args = NULL;
}
impl_args(args) ::= LPAREN impl_arg_list(args_) RPAREN. {
+
+
+
args = args_;
}
impl_args(args) ::= LPAREN impl_arg_list(args_) COMMA impl_vararg(va) RPAREN. {
+
+
+
+
+
args = args_;
args->vararg.name = va;
}
+
impl_vararg(va) ::= impl_type(type) reference(r) ELLIPSIS DOLLAR_NAME(T). {
+
+
+
+
va = init_impl_arg(type, init_impl_var(T->text, r), NULL);
free(T);
}
+
impl_arg_list(args) ::= impl_arg(arg). {
+
args = init_impl_args(arg);
}
impl_arg_list(args) ::= impl_arg_list(args_) COMMA impl_arg(arg). {
+
+
+
args = add_impl_arg(args_, arg);
}
+
impl_stmts(stmts) ::= impl_stmt(stmt). {
+
stmts = init_impl_stmts(stmt);
}
impl_stmts(stmts) ::= impl_stmts(stmts_) impl_stmt(stmt). {
+
+
stmts = add_impl_stmt(stmts_, stmt);
}
+
impl_stmt(stmt) ::= let_stmt(let). {
+
stmt = init_impl_stmt(PSI_T_LET, let);
}
impl_stmt(stmt) ::= set_stmt(set). {
+
stmt = init_impl_stmt(PSI_T_SET, set);
}
impl_stmt(stmt) ::= return_stmt(ret). {
+
stmt = init_impl_stmt(PSI_T_RETURN, ret);
}
impl_stmt(stmt) ::= free_stmt(free). {
+
stmt = init_impl_stmt(PSI_T_FREE, free);
}
+
num_exp(exp) ::= num_exp_token(tok). {
+
exp = init_num_exp(tok->type, tok->text);
exp->token = tok;
}
num_exp(exp) ::= decl_var(var). {
+
exp = init_num_exp(PSI_T_NAME, var);
exp->token = psi_token_copy(var->token);
}
num_exp(exp) ::= num_exp(exp_) num_exp_op_token(operator_) num_exp(operand_). {
+
+
+
exp_->operator = operator_->type;
exp_->operand = operand_;
exp = exp_;
free(operator_);
}
+
let_stmt(let) ::= LET decl_var(var) EOS. {
+
+
+
let = init_let_stmt(var, init_let_val(PSI_LET_NULL, NULL));
}
let_stmt(let) ::= LET decl_var(var) EQUALS reference(r) let_val(val) EOS. {
+
+
+
+
+
+
val->flags.one.is_reference = r ? 1 : 0;
let = init_let_stmt(var, val);
}
let_stmt(let) ::= TEMP decl_var(var) EQUALS decl_var(val) EOS. {
+
+
+
+
+
let = init_let_stmt(var, init_let_val(PSI_LET_TMP, val));
}
+
let_calloc(alloc) ::= num_exp(nmemb) COMMA num_exp(size). {
+
+
+
alloc = init_let_calloc(nmemb, size);
}
+
let_func(func) ::= let_func_token(T) LPAREN impl_var(var) RPAREN. {
+
+
+
+
func = init_let_func(T->type, T->text, var);
free(T);
}
+
+let_vals(vals) ::= let_val(val). {
+
+ vals = init_let_vals(val);
+}
+let_vals(vals) ::= let_vals(vals_) COMMA let_val(val). {
+
+
+
+ vals = add_let_val(vals_, val);
+}
+
+let_func(func) ::= let_func_token(T) LPAREN impl_var(var) COMMA let_vals(vals) RPAREN. {
+
+
+
+
+
+
+ func = init_let_func(T->type, T->text, var);
+ func->inner = vals;
+ free(T);
+}
+
callback_arg_list ::= .
callback_arg_list(args) ::= callback_args(args_). {
+
args = args_;
}
+
callback_args(args) ::= set_value(val). {
+
args = init_set_values(val);
}
callback_args(args) ::= callback_args(args_) COMMA set_value(val). {
+
+
+
args = add_set_value(args_, val);
}
+callback_rval(rval) ::= let_func_token(F). {
+
+ rval = F;
+}
+callback_rval(rval) ::= VOID(V). {
+
+ rval = V;
+}
+
let_val(val) ::= NULL. {
+
val = init_let_val(PSI_LET_NULL, NULL);
}
let_val(val) ::= num_exp(exp). {
+
val = init_let_val(PSI_LET_NUMEXP, exp);
}
let_val(val) ::= CALLOC LPAREN let_calloc(alloc) RPAREN. {
+
+
+
+
val = init_let_val(PSI_LET_CALLOC, alloc);
}
-let_val(val) ::= let_func(func). {
- val = init_let_val(PSI_LET_FUNC, func);
+let_val(val) ::= let_func(func_). {
+
+ val = init_let_val(PSI_LET_FUNC, func_);
}
-let_val(val) ::= CALLBACK let_func_token(F) LPAREN impl_var(var) LPAREN callback_arg_list(args_) RPAREN RPAREN. {
+let_val(val) ::= CALLBACK callback_rval(F) LPAREN impl_var(var) LPAREN callback_arg_list(args_) RPAREN RPAREN. {
val = init_let_val(PSI_LET_CALLBACK, init_let_callback(
init_let_func(F->type, F->text, var), args_));
free(F);
}
+
set_stmt(set) ::= SET impl_var(var) EQUALS set_value(val) EOS. {
+
+
+
+
+
set = init_set_stmt(var, val);
}
+
set_value(val) ::= set_func(func) LPAREN decl_var(var) RPAREN. {
+
+
+
+
val = init_set_value(func, init_decl_vars(var));
}
set_value(val) ::= set_func(func) LPAREN decl_var(var) COMMA num_exp(num_) RPAREN. {
+
+
+
+
+
+
val = init_set_value(func, init_decl_vars(var));
val->num = num_;
}
set_value(val) ::= set_func(func_) LPAREN decl_var(var) COMMA ELLIPSIS(T) RPAREN. {
+
+
+
+
+
+
free_set_func(func_);
val = init_set_value(init_set_func(T->type, T->text), init_decl_vars(var));
val->func->token = T;
}
set_value(val) ::= set_func(func_) LPAREN decl_var(var) COMMA set_vals(vals) RPAREN. {
+
+
+
+
+
+
val = vals;
val->func = func_;
val->vars = init_decl_vars(var);
val->num = num_;
val->vars = init_decl_vars(var);
}
+
set_vals(vals) ::= set_value(val). {
+
vals = add_inner_set_value(init_set_value(NULL, NULL), val);
}
set_vals(vals) ::= set_vals(vals_) COMMA set_value(val). {
+
+
+
vals = add_inner_set_value(vals_, val);
}
+
set_func(func) ::= set_func_token(T). {
+
func = init_set_func(T->type, T->text);
func->token = T;
}
+
return_stmt(ret) ::= RETURN(T) set_value(val) EOS. {
+
+
+
ret = init_return_stmt(val);
ret->token = T;
}
+
free_stmt(free) ::= FREE free_calls(calls) EOS. {
+
+
+
free = init_free_stmt(calls);
}
+
free_calls(calls) ::= free_call(call). {
+
calls = init_free_calls(call);
}
free_calls(calls) ::= free_calls(calls_) COMMA free_call(call). {
+
+
+
calls = add_free_call(calls_, call);
}
+
free_call(call) ::= NAME(F) LPAREN decl_vars(vars) RPAREN. {
+
+
+
+
call = init_free_call(F->text, vars);
call->token = F;
}
+
impl_type(type_) ::= impl_type_token(T). {
+
type_ = init_impl_type(T->type, T->text);
free(T);
}
+
reference(r) ::= . {
r = 0;
}
reference(r) ::= AMPERSAND. {
+
r = 1;
}
+
indirection(i) ::= .{
i = 0;
}
indirection(i) ::= pointers(p). {
+
i = p;
}
+
pointers(p) ::= ASTERISK. {
+
p = 1;
}
pointers(p) ::= pointers(p_) ASTERISK. {
+
+
p = p_+1;
}