#include "context.h"
-void psi_error(int type, const char *msg, ...);
+void psi_error_wrapper(PSI_Token *t, int type, const char *msg, ...);
+void psi_error(int type, const char *fn, unsigned ln, const char *msg, ...);
+void psi_verror(int type, const char *fn, unsigned ln, const char *msg, va_list argv);
static inline int psi_check_env(const char *var) {
char *set = getenv(var);
let format = strval($fmt);
return to_int(printf);
}
+
} else if (!strchr(ptr, '/')) {
len = snprintf(lib, MAXPATHLEN, "lib%s.%s", ptr, PHP_PSI_SHLIB_SUFFIX);
if (MAXPATHLEN == len) {
- data->error(PSI_WARNING, "Library name too long: '%s'", ptr);
+ data->error(NULL, PSI_WARNING, "Library name too long: '%s'", ptr);
}
lib[len] = 0;
ptr = lib;
}
if (!(*dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) {
- data->error(PSI_WARNING, "Could not open library '%s': %s.",
+ data->error(NULL, PSI_WARNING, "Could not open library '%s': %s.",
data->psi.file.ln, dlerror());
return 0;
}
}
static inline int validate_decl_typedef(PSI_Data *data, decl_typedef *def) {
if (!validate_decl_type(data, def->type)) {
- data->error(PSI_WARNING, "Type '%s' cannot be aliased to %s'%s'",
+ data->error(def->token, PSI_WARNING,
+ "Type '%s' cannot be aliased to %s'%s'",
def->type->name, def->type->type == PSI_T_STRUCT?"struct ":"",def->alias);
return 0;
}
static inline int validate_decl_arg(PSI_Data *data, decl_arg *arg) {
if (!validate_decl_type(data, arg->type)) {
- data->error(PSI_WARNING, "Cannot use '%s'(%d) as type for decl var '%s'"
- " in %s on line %zu at col %zu",
- arg->type->name, arg->type->type, arg->var->name,
- arg->type->token->file, arg->type->token->line, arg->type->token->col);
+ data->error(arg->type->token, PSI_WARNING,
+ "Cannot use '%s'(%d) as type for decl var '%s'",
+ arg->type->name, arg->type->type, arg->var->name);
return 0;
}
return 1;
return 1;
}
}
- data->error(PSI_WARNING, "Invalid calling convention: '%s'", abi->convention);
return 0;
}
static inline int validate_decl_func(PSI_Data *data, void *dl, decl *decl, decl_arg *func)
struct psi_func_redir *redir;
if (!strcmp(func->var->name, "dlsym")) {
- data->error(PSI_WARNING, "Cannot dlsym dlsym (sic!)");
+ data->error(func->token, PSI_WARNING, "Cannot dlsym dlsym (sic!)");
return 0;
}
#endif
decl->call.sym = dlsym(dl ?: RTLD_NEXT, func->var->name);
if (!decl->call.sym) {
- data->error(PSI_WARNING, "Failed to locate symbol '%s': %s",
+ data->error(func->token, PSI_WARNING,
+ "Failed to locate symbol '%s': %s",
func->var->name, dlerror());
}
}
static inline int validate_decl(PSI_Data *data, void *dl, decl *decl) {
if (!validate_decl_abi(data, decl->abi)) {
+ data->error(decl->abi->token, PSI_WARNING,
+ "Invalid calling convention: '%s'", decl->abi->token->text);
return 0;
}
if (!validate_decl_func(data, dl, decl, decl->func)) {
switch (exp->t) {
case PSI_T_NAME:
if (!locate_decl_var_arg(exp->u.dvar, dargs, func)) {
- data->error(PSI_WARNING, "Unknown variable '%s' in numeric expression",
+ data->error(exp->token, PSI_WARNING, "Unknown variable '%s' in numeric expression",
exp->u.dvar->name);
return 0;
}
return 1;
case PSI_T_NSNAME:
if (!locate_num_exp_constant(exp, data->consts)) {
- data->error(PSI_WARNING, "Unknown constant '%s' in numeric expression",
+ data->error(exp->token, PSI_WARNING, "Unknown constant '%s' in numeric expression",
exp->u.numb);
return 0;
}
decl_var *set_var = set->vars->vars[0];
if (!validate_set_value_handler(set)) {
- data->error(PSI_WARNING, "Invalid cast '%s'", set->func->name);
+ data->error(set->func->token, PSI_WARNING, "Invalid cast '%s'", set->func->name);
return 0;
}
for (i = 0; i < set->vars->count; ++i) {
decl_var *svar = set->vars->vars[i];
if (!svar->arg && !locate_decl_var_arg(svar, ref_list, NULL)) {
- data->error(PSI_WARNING, "Unknown variable '%s'", svar->name);
+ data->error(svar->token, PSI_WARNING, "Unknown variable '%s'", svar->name);
return 0;
}
}
int is_pointer_to_struct = (ref_type->type == PSI_T_STRUCT && ref->var->pointer_level);
if (!is_to_array && !is_pointer_to_struct) {
- data->error(E_WARNING, "Inner `set` statement casts only work with "
+ data->error(set->func->token, E_WARNING, "Inner `set` statement casts only work with "
"to_array() casts on structs or pointers: %s(%s...", set->func->name, set->vars->vars[0]->name);
return 0;
}
set->inner[0]->outer.set = set;
if (sub_ref) {
if (strcmp(sub_var->name, set_var->name)) {
- data->error(E_WARNING, "Inner `set` statement casts on pointers must reference the same variable");
+ data->error(sub_var->token, E_WARNING, "Inner `set` statement casts on pointers must reference the same variable");
return 0;
}
if (!validate_set_value_ex(data, set->inner[0], sub_ref, ref_list)) {
}
}
} else if (set->count > 1) {
- data->error(E_WARNING, "Inner `set` statement casts on pointers may only occur once");
+ data->error(set->func->token, E_WARNING, "Inner `set` statement casts on pointers may only occur once");
return 0;
}
/* and which type cast to apply */
if (impl->stmts->ret.count != 1) {
if (impl->stmts->ret.count > 1) {
- data->error(PSI_WARNING, "Too many `return` statements for implmentation %s;"
+ data->error(impl->stmts->ret.list[1]->token, PSI_WARNING,
+ "Too many `return` statements for implmentation %s;"
" found %zu, exactly one is needed",
impl->func->name, impl->stmts->ret.count);
} else {
- data->error(PSI_WARNING, "Missing `return` statement for implementation %s",
+ data->error(impl->func->token, PSI_WARNING,
+ "Missing `return` statement for implementation %s",
impl->func->name);
}
return 0;
ret = impl->stmts->ret.list[0];
if (!(impl->decl = locate_impl_decl(data->decls, ret))) {
- data->error(PSI_WARNING, "Missing declaration for implementation %s",
- impl->func->name);
+ data->error(ret->token, PSI_WARNING,
+ "Missing declaration '%s' for `return` statment for implementation %s",
+ ret->set->vars->vars[0]->name, impl->func->name);
return 0;
}
}
if (!locate_decl_var_arg(let_var, impl->decl->args, impl->decl->func)) {
- data->error(PSI_WARNING, "Unknown variable '%s' in `let` statement"
+ data->error(let_var->token, PSI_WARNING, "Unknown variable '%s' in `let` statement"
" of implementation '%s'", let_var->name, impl->func->name);
return 0;
}
}
}
if (!check) {
- data->error(PSI_WARNING, "Unknown value '$%s' of `let` statement"
+ data->error(let->var->token, PSI_WARNING, "Unknown value '$%s' of `let` statement"
" for variable '%s' of implementation '%s'",
let->val->data.func->var->name, let->var->name, impl->func->name);
return 0;
}
}
if (!check) {
- data->error(PSI_WARNING, "Missing `let` statement for arg '%s %.*s%s'"
+ data->error(impl->func->token, PSI_WARNING,
+ "Missing `let` statement for arg '%s %.*s%s'"
" of declaration '%s' for implementation '%s'",
darg->type->name, (int) darg->var->pointer_level, "*****",
darg->var->name, impl->decl->func->var->name, impl->func->name);
}
}
if (!check) {
- data->error(PSI_WARNING, "Unknown variable '$%s' of `set` statement"
+ data->error(set->var->token, PSI_WARNING, "Unknown variable '$%s' of `set` statement"
" of implementation '%s'",
set->var->name, impl->func->name);
return 0;
}
if (!check) {
- data->error(PSI_WARNING, "Unknown value '%s' of `set` statement"
+ data->error(set_var->token, PSI_WARNING, "Unknown value '%s' of `set` statement"
" for variable '$%s' of implementation '%s'",
set_var->name, set->arg->var->name, impl->func->name);
return 0;
/* first find the decl of the free func */
if (!locate_free_decl(data->decls, free_call)) {
- data->error(PSI_WARNING, "Unknown function '%s' in `free` statement"
- " of implementation '%s'", free_call->func, impl->func->name);
+ data->error(free_call->token, PSI_WARNING,
+ "Missing declaration '%s' in `free` statement"
+ " of implementation '%s'",
+ free_call->func, impl->func->name);
return 0;
}
if (!impl->decl->args) {
- data->error(PSI_WARNING, "Declaration '%s' of implementation '%s'"
+ data->error(free_call->token, PSI_WARNING,
+ "Declaration '%s' of implementation '%s'"
" does not have any arguments to free",
impl->decl->func->var->name, impl->func->name);
}
}
if (!check) {
- data->error(PSI_WARNING, "Unknown variable '%s' of `free` statement"
+ data->error(free_var->token, PSI_WARNING,
+ "Unknown variable '%s' of `free` statement"
" of implementation '%s'",
free_var->name, impl->func->name);
return 0;
}
static inline int validate_impl_stmts(PSI_Data *data, impl *impl) {
if (!impl->stmts) {
- data->error(PSI_WARNING, "Missing body for implementation %s!",
+ data->error(impl->func->token, PSI_WARNING,
+ "Missing body for implementation %s!",
impl->func->name);
return 0;
}
PSI_Parser P;
if (MAXPATHLEN <= slprintf(psi, MAXPATHLEN, "%s/%s", ptr, entries[i]->d_name)) {
- C->error(PSI_WARNING, "Path to PSI file too long: %s/%s",
+ C->error(NULL, PSI_WARNING, "Path to PSI file too long: %s/%s",
ptr, entries[i]->d_name);
}
if (!PSI_ParserInit(&P, psi, C->error, flags)) {
- C->error(PSI_WARNING, "Failed to init PSI parser (%s): %s",
+ C->error(NULL, PSI_WARNING, "Failed to init PSI parser (%s): %s",
psi, strerror(errno));
continue;
}
if (PSI_ContextCompile(C) && SUCCESS != zend_register_functions(NULL, C->closures, NULL, MODULE_PERSISTENT)) {
- C->error(PSI_WARNING, "Failed to register functions!");
+ C->error(NULL, PSI_WARNING, "Failed to register functions!");
}
free(cpy);
#define PSI_ERROR 16
#define PSI_WARNING 32
-typedef void (*PSI_ContextErrorFunc)(int type, const char *msg, ...);
+typedef void (*PSI_ContextErrorFunc)(PSI_Token *token, int type, const char *msg, ...);
typedef struct PSI_Context PSI_Context;
typedef struct PSI_ContextOps PSI_ContextOps;
static zend_object_handlers psi_object_handlers;
static zend_class_entry *psi_class_entry;
-void psi_error(int type, const char *msg, ...)
+void psi_error_wrapper(PSI_Token *t, int type, const char *msg, ...)
{
- char buf[0x1000];
va_list argv;
va_start(argv, msg);
- vslprintf(buf, 0x1000, msg, argv);
+ psi_verror(type, t?t->file:"Unknown", t?*t->line:0, msg, argv);
va_end(argv);
+}
+void psi_error(int type, const char *fn, unsigned ln, const char *msg, ...)
+{
+ va_list argv;
- php_error(type, buf);
+ va_start(argv, msg);
+ psi_verror(type, fn, ln, msg, argv);
+ va_end(argv);
+}
+void psi_verror(int type, const char *fn, unsigned ln, const char *msg, va_list argv)
+{
+ zend_error_cb(type, fn, ln, msg, argv);
}
size_t psi_t_alignment(token_t t)
return FAILURE;
}
- PSI_ContextInit(&PSI_G(context), ops, psi_error);
+ PSI_ContextInit(&PSI_G(context), ops, psi_error_wrapper);
PSI_ContextBuild(&PSI_G(context), PSI_G(directory));
if (psi_check_env("PSI_DUMP")) {
typedef struct PSI_Token {
token_t type;
- size_t size, line, col;
+ unsigned size, *line;
char *text, *file;
char buf[1];
} PSI_Token;
}
typedef struct decl_typedef {
+ PSI_Token *token;
char *alias;
decl_type *type;
} decl_typedef;
}
static inline void free_decl_typedef(decl_typedef *t) {
+ if (t->token) {
+ free(t->token);
+ }
free(t->alias);
free_decl_type(t->type);
free(t);
}
typedef struct decl_var {
+ PSI_Token *token;
char *name;
unsigned pointer_level;
unsigned array_size;
}
static inline void free_decl_var(decl_var *var) {
+ if (var->token) {
+ free(var->token);
+ }
free(var->name);
free(var);
}
}
typedef struct decl_arg {
+ PSI_Token *token;
decl_type *type;
decl_var *var;
decl_struct_layout *layout;
static inline decl_arg *init_decl_arg(decl_type *type, decl_var *var) {
decl_arg *arg = calloc(1, sizeof(*arg));
+ arg->token = var->token;
arg->type = type;
arg->var = var;
var->arg = arg;
}
typedef struct decl_abi {
+ PSI_Token *token;
char *convention;
} decl_abi;
}
static inline void free_decl_abi(decl_abi *abi) {
+ if (abi->token) {
+ free(abi->token);
+ }
free(abi->convention);
free(abi);
}
}
typedef struct decl_struct {
+ PSI_Token *token;
char *name;
decl_args *args;
size_t size;
}
static inline void free_decl_struct(decl_struct *s) {
+ if (s->token) {
+ free(s->token);
+ }
if (s->args) {
free_decl_args(s->args);
}
}
typedef struct impl_var {
+ PSI_Token *token;
char *name;
unsigned reference:1;
} impl_var;
}
static inline void free_impl_var(impl_var *var) {
+ if (var->token) {
+ free(var->token);
+ }
free(var->name);
free(var);
}
}
typedef struct impl_func {
+ PSI_Token *token;
char *name;
impl_args *args;
impl_type *return_type;
}
static inline void free_impl_func(impl_func *f) {
+ if (f->token) {
+ free(f->token);
+ }
free_impl_type(f->return_type);
free_impl_args(f->args);
free(f->name);
}
typedef struct num_exp {
+ PSI_Token *token;
token_t t;
union {
char *numb;
}
static inline void free_num_exp(num_exp *exp) {
+ if (exp->token) {
+ free(exp->token);
+ }
switch (exp->t) {
case PSI_T_NUMBER:
free(exp->u.numb);
struct set_value;
typedef struct set_func {
+ PSI_Token *token;
token_t type;
char *name;
void (*handler)(zval *, struct set_value *set, impl_val *ret_val);
}
static inline void free_set_func(set_func *func) {
+ if (func->token) {
+ free(func->token);
+ }
free(func->name);
free(func);
}
}
typedef struct return_stmt {
+ PSI_Token *token;
set_value *set;
decl_arg *decl;
} return_stmt;
}
static inline void free_return_stmt(return_stmt *ret) {
- //free_set_func(ret->func);
- //free_decl_var(ret->decl);
+ if (ret->token) {
+ free(ret->token);
+ }
free_set_value(ret->set);
free(ret);
}
typedef struct free_call {
+ PSI_Token *token;
char *func;
decl_vars *vars;
decl *decl;
}
static inline void free_free_call(free_call *f) {
+ if (f->token) {
+ free(f->token);
+ }
free(f->func);
free_decl_vars(f->vars);
free(f);
#define PSI_ERROR 16
#define PSI_WARNING 32
-typedef void (*psi_error_cb)(int type, const char *msg, ...);
+typedef void (*psi_error_cb)(PSI_Token *token, int type, const char *msg, ...);
#define PSI_DATA(D) ((PSI_Data *) (D))
#define PSI_DATA_MEMBERS \
typedef struct PSI_Parser {
PSI_DATA_MEMBERS;
FILE *fp;
- unsigned flags;
- unsigned errors;
- void *proc;
- size_t line, col;
token_t num;
+ void *proc;
+ unsigned flags, errors, line, col;
char *cur, *tok, *lim, *eof, *ctx, *mrk, buf[BSIZE];
} PSI_Parser;
token_len = P->cur - P->tok;
fname_len = strlen(P->psi.file.fn);
- T = calloc(1, sizeof(*T) + token_len + fname_len + 1);
+ T = calloc(1, sizeof(*T) + token_len + fname_len + sizeof(unsigned) + 2);
T->type = token_typ;
T->size = token_len;
- T->line = P->line;
- T->col = P->col;
- T->file = &T->buf[0];
- T->text = &T->buf[fname_len + 1];
+ T->text = &T->buf[0];
+ T->file = &T->buf[token_len + 1];
+ T->line = (void *) &T->buf[fname_len + token_len + 2];
- memcpy(T->file, P->psi.file.fn, fname_len);
memcpy(T->text, P->tok, token_len);
+ memcpy(T->file, P->psi.file.fn, fname_len);
+ memcpy(T->line, &P->line, sizeof(unsigned));
return T;
}
static inline PSI_Token *PSI_TokenCopy(PSI_Token *src) {
size_t fname_len = strlen(src->file);
- size_t strct_len = sizeof(*src) + src->size + fname_len + 1;
+ size_t strct_len = sizeof(*src) + src->size + fname_len + sizeof(unsigned) + 2;
PSI_Token *ptr = malloc(strct_len);
memcpy(ptr, src, strct_len);
- ptr->file = &ptr->buf[0];
- ptr->text = &ptr->buf[fname_len + 1];
+ ptr->text = &ptr->buf[0];
+ ptr->file = &ptr->buf[ptr->size + 1];
return ptr;
}
+static inline const char *PSI_TokenLocation(PSI_Token *t) {
+ return t ? t->file : "<builtin>:0:0";
+}
+
#define PSI_PARSER_DEBUG 0x1
PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb error, unsigned flags);
return P;
}
-void PSI_ParserSyntaxError(PSI_Parser *P, const char *fn, size_t ln, const char *msg, ...) {
- char buf[0x1000] = {0};
- va_list argv;
-
- va_start(argv, msg);
- vsnprintf(buf, 0x1000-1, msg, argv);
- va_end(argv);
-
- P->error(PSI_WARNING, "PSI syntax error on line %zu in '%s'%s%s",
- ln, fn, msg ? ": ": "", buf);
-
- ++P->errors;
-}
-
size_t PSI_ParserFill(PSI_Parser *P, size_t n)
{
if (P->flags & PSI_PARSER_DEBUG) {
#define RETURN(t) do { \
P->num = t; \
if (P->flags & PSI_PARSER_DEBUG) { \
- fprintf(stderr, "PSI> TOKEN: %d %.*s (EOF=%d %s:%zu:%zu)\n", \
+ fprintf(stderr, "PSI> TOKEN: %d %.*s (EOF=%d %s:%u:%u)\n", \
P->num, (int) (P->cur-P->tok), P->tok, P->num == PSI_T_EOF, \
P->psi.file.fn, P->line, P->col); \
} \
#include "parser.h"
+void psi_error(int, const char *, int, const char *, ...);
}
%name PSI_ParserProc
%extra_argument {PSI_Parser *P}
/* TOKEN is defined inside syntax_error */
%syntax_error {
+ ++P->errors;
if (TOKEN && TOKEN->type != PSI_T_EOF) {
- PSI_ParserSyntaxError(P, P->psi.file.fn, P->line, "Unexpected token '%s'", TOKEN->text);
+ psi_error(PSI_WARNING, TOKEN->file, *TOKEN->line, "PSI syntax error: Unexpected token '%s'", TOKEN->text);
} else {
- PSI_ParserSyntaxError(P, P->psi.file.fn, P->line, "Unexpected end of input");
+ psi_error(PSI_WARNING, P->psi.file.fn, P->line, "PSI syntax error: Unexpected end of input");
}
}
block ::= LIB(T) QUOTED_STRING(libname) EOS. {
if (P->psi.file.ln) {
- PSI_ParserSyntaxError(P, P->psi.file.ln, T->line, "Extra 'lib %s' statement has no effect", libname->text);
+ P->error(T, PSI_WARNING, "Extra 'lib %s' statement has no effect", libname->text);
} else {
P->psi.file.ln = strndup(libname->text + 1, libname->size - 2);
}
decl_struct(strct) ::= STRUCT NAME(N) struct_size(size_) LBRACE struct_args(args) RBRACE. {
strct = init_decl_struct(N->text, args);
strct->size = size_;
- free(N);
+ strct->token = N;
}
%type struct_size {size_t}
%destructor decl_typedef {free_decl_typedef($$);}
decl_typedef(def) ::= TYPEDEF decl_type(type) NAME(ALIAS) EOS. {
def = init_decl_typedef(ALIAS->text, type);
- free(ALIAS);
+ def->token = ALIAS;
}
/* support opaque types */
decl_typedef(def) ::= TYPEDEF VOID(V) NAME(ALIAS) EOS. {
def = init_decl_typedef(ALIAS->text, init_decl_type(V->type, V->text));
+ def->token = ALIAS;
def->type->token = V;
- //free(V);
- free(ALIAS);
}
decl_typedef(def) ::= TYPEDEF STRUCT(S) NAME(N) NAME(ALIAS) EOS. {
def = init_decl_typedef(ALIAS->text, init_decl_type(S->type, N->text));
+ def->token = ALIAS;
def->type->token = N;
- free(ALIAS);
free(S);
- //free(N);
}
decl_typedef(def) ::= TYPEDEF decl_struct(s) NAME(ALIAS) EOS. {
def = init_decl_typedef(ALIAS->text, init_decl_type(PSI_T_STRUCT, s->name));
- def->type->token = ALIAS;
+ def->token = ALIAS;
+ def->type->token = PSI_TokenCopy(s->token);
def->type->strct = s;
- //free(ALIAS);
}
%type decl {decl*}
%destructor decl {free_decl($$);}
decl(decl) ::= decl_abi(abi) decl_func(func) LPAREN decl_args(args) RPAREN EOS. {
decl = init_decl(abi, func, args);
-
}
%type decl_func {decl_arg*}
%destructor decl_abi {free_decl_abi($$);}
decl_abi(abi) ::= NAME(T). {
abi = init_decl_abi(T->text);
- free(T);
+ abi->token = T;
}
%type decl_var {decl_var*}
%destructor decl_var {free_decl_var($$);}
decl_var(var) ::= indirection(p) NAME(T). {
var = init_decl_var(T->text, p, 0);
- free(T);
+ 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));
- free(T);
+ var->token = T;
free(D);
}
init_decl_var(N->text, p, 0)
);
arg_->type->token = T;
- //free(T);
- free(N);
+ arg_->var->token = N;
+ arg_->token = N;
}
decl_arg(arg_) ::= CONST VOID(T) pointers(p) NAME(N). {
arg_ = init_decl_arg(
init_decl_var(N->text, p, 0)
);
arg_->type->token = T;
- //free(T);
- free(N);
+ arg_->var->token = N;
+ arg_->token = N;
}
%type decl_args {decl_args*}
decl_type(type_) ::= decl_type_token(T). {
type_ = init_decl_type(T->type, T->text);
type_->token = T;
- //free(T);
}
/* unsigned, urgh */
decl_type(type_) ::= UNSIGNED NAME(T). {
memcpy(type_->name, "unsigned", sizeof("unsigned")-1);
type_->name[sizeof("unsigned")] = ' ';
type_->name[T->size + sizeof("unsigned")] = 0;
- //free(T);
}
/* we have to support plain int here because we have it in our lexer rules */
decl_type(type_) ::= INT(T). {
type_ = init_decl_type(PSI_T_NAME, T->text);
type_->token = T;
- //free(T);
}
/* structs ! */
decl_type(type_) ::= STRUCT(S) NAME(T). {
type_ = init_decl_type(S->type, T->text);
type_->token = T;
free(S);
- //free(T);
}
%type const_decl_type {decl_type*}
%destructor impl_func {free_impl_func($$);}
impl_func(func) ::= FUNCTION reference(r) NSNAME(NAME) impl_args(args) COLON impl_type(type). {
func = init_impl_func(NAME->text, args, type, r);
- free(NAME);
+ func->token = NAME;
}
%token_class impl_def_val_token NULL NUMBER TRUE FALSE QUOTED_STRING.
%destructor impl_var {free_impl_var($$);}
impl_var(var) ::= reference(r) DOLLAR NAME(T). {
var = init_impl_var(T->text, r);
- free(T);
+ var->token = T;
}
%type impl_arg {impl_arg*}
%destructor num_exp {free_num_exp($$);}
num_exp(exp) ::= num_exp_token(tok). {
exp = init_num_exp(tok->type, tok->text);
- free(tok);
+ exp->token = tok;
}
num_exp(exp) ::= decl_var(var). {
exp = init_num_exp(PSI_T_NAME, var);
+ exp->token = PSI_TokenCopy(var->token);
}
num_exp(exp) ::= num_exp(exp_) num_exp_op_token(operator_) num_exp(operand_). {
exp_->operator = operator_->type;
%destructor set_func {free_set_func($$);}
set_func(func) ::= set_func_token(T). {
func = init_set_func(T->type, T->text);
- free(T);
+ func->token = T;
}
%type return_stmt {return_stmt*}
%destructor return_stmt {free_return_stmt($$);}
-return_stmt(ret) ::= RETURN set_value(val) EOS. {
+return_stmt(ret) ::= RETURN(T) set_value(val) EOS. {
ret = init_return_stmt(val);
+ ret->token = T;
}
%type free_stmt {free_stmt*}
%destructor free_call {free_free_call($$);}
free_call(call) ::= NAME(F) LPAREN decl_vars(vars) RPAREN. {
call = init_free_call(F->text, vars);
- free(F);
+ call->token = F;
}
%token_class impl_type_token VOID MIXED BOOL INT FLOAT STRING ARRAY OBJECT.