./lemon: lemon.c | lempar.c
$(CC) -o $@ $<
-$(PHP_PSI_SRCDIR)/src/parser_proc.h: $(PHP_PSI_SRCDIR)/src/parser_proc.y
+$(PHP_PSI_SRCDIR)/src/parser_proc.h: $(PHP_PSI_SRCDIR)/src/parser_proc.c
$(PHP_PSI_SRCDIR)/src/%.c: $(PHP_PSI_SRCDIR)/src/parser.h $(PHP_PSI_SRCDIR)/src/parser_proc.h
touch $@
PHP_ADD_BUILD_DIR($PHP_PSI_BUILDDIR/src)
PHP_PSI_HEADERS=`(cd $PHP_PSI_SRCDIR/src && echo *.h)`
- PHP_PSI_SOURCES=`(cd $PHP_PSI_SRCDIR && echo src/context*.c)`
+ PHP_PSI_SOURCES= # parser* should come first
PHP_PSI_SOURCES="$PHP_PSI_SOURCES src/parser_proc.c src/parser.c"
PHP_PSI_SOURCES="$PHP_PSI_SOURCES src/libjit.c src/libffi.c src/engine.c"
PHP_PSI_SOURCES="$PHP_PSI_SOURCES src/marshal.c src/calc.c src/module.c"
+ PHP_PSI_SOURCES="$PHP_PSI_SOURCES `(cd $PHP_PSI_SRCDIR && echo src/context*.c)`"
PHP_NEW_EXTENSION(psi, $PHP_PSI_SOURCES, $ext_shared)
PHP_INSTALL_HEADERS(ext/psi, php_psi.h $PHP_PSI_HEADERS)
#include "php.h"
#include "php_psi.h"
+#include "calc.h"
static inline int psi_calc_num_exp_value(num_exp *exp, impl_val *strct, impl_val *res) {
impl_val *ref, *tmp = NULL;
}
break;
+ case PSI_T_ENUM:
+ return psi_calc_num_exp(exp->u.enm->num ?: &exp->u.enm->inc, NULL, res);
+ break;
+
case PSI_T_NAME:
if (strct) {
ref = struct_member_ref(exp->u.dvar->arg, strct, &tmp);
#include "php.h"
#include "php_scandir.h"
#include "php_psi.h"
-
+#include "calc.h"
#include "libjit.h"
#include "libffi.h"
zend_function_entry *PSI_ContextCompile(PSI_Context *C)
{
size_t i;
+ zend_constant zc;
- if (C->consts) {
- zend_constant zc;
-
- zc.flags = CONST_PERSISTENT|CONST_CS;
- zc.module_number = EG(current_module)->module_number;
+ zc.flags = CONST_PERSISTENT|CONST_CS;
+ zc.module_number = EG(current_module)->module_number;
+ if (C->consts) {
for (i = 0; i < C->consts->count; ++i) {
constant *c = C->consts->list[i];
zend_register_constant(&zc);
}
}
+ if (C->enums) {
+ for (i = 0; i < C->enums->count; ++i) {
+ decl_enum *e = C->enums->list[i];
+ size_t j;
+
+ for (j = 0; j < e->items->count; ++j) {
+ decl_enum_item *i = e->items->list[j];
+ zend_string *name = strpprintf(0, "psi\\%s\\%s", e->name, i->name);
+
+ zc.name = zend_string_dup(name, 1);
+ ZVAL_LONG(&zc.value, psi_long_num_exp(i->num, NULL));
+ zend_register_constant(&zc);
+ zend_string_release(name);
+ }
+ }
+ }
return C->closures = C->ops->compile(C);
}
}
free(C->structs);
}
+ if (C->enums) {
+ if (C->enums->list) {
+ free(C->enums->list);
+ }
+ free(C->enums);
+ }
if (C->decls) {
if (C->decls->list) {
free(C->decls->list);
case PSI_T_NAME:
dump_decl_var(fd, exp->u.dvar);
break;
+ case PSI_T_ENUM:
+ dprintf(fd, "%s", exp->u.enm->name);
+ break;
EMPTY_SWITCH_DEFAULT_CASE();
}
if (exp->operand) {
dprintf(fd, ";");
}
}
+
static inline void dump_structs(int fd, decl_structs *structs) {
size_t i;
}
}
+static inline void dump_enum(int fd, decl_enum *e) {
+ size_t j;
+
+ dprintf(fd, "enum %s {\n", e->name);
+ for (j = 0; j < e->items->count; ++j) {
+ decl_enum_item *i = e->items->list[j];
+
+ if (j) {
+ dprintf(fd, ",\n");
+ }
+ dprintf(fd, "\t%s", i->name);
+ if (i->num && i->num != &i->inc) {
+ dprintf(fd, " = ");
+ dump_num_exp(fd, i->num);
+ }
+ }
+ dprintf(fd, "\n}");
+}
+
+static inline void dump_enums(int fd, decl_enums *enums) {
+ size_t i;
+
+ for (i = 0; i < enums->count; ++i) {
+ decl_enum *e = enums->list[i];
+
+ dump_enum(fd, e);
+ dprintf(fd, "\n");
+ }
+}
static inline void dump_constant(int fd, constant *cnst) {
dprintf(fd, "const %s %s = ", cnst->type->name, cnst->name);
if (cnst->val->type == PSI_T_QUOTED_STRING) {
dump_structs(fd, C->structs);
dprintf(fd, "\n");
}
+ if (C->enums) {
+ dump_enums(fd, C->enums);
+ dprintf(fd, "\n");
+ }
if (C->consts) {
dump_constants(fd, C->consts);
dprintf(fd, "\n");
-#ifdef HAVE_CONFIG_H
+ #ifdef HAVE_CONFIG_H
# include "config.h"
#endif
return 0;
}
+
static inline int locate_decl_type_struct(decl_structs *structs, decl_type *type) {
size_t i;
return 0;
}
+static inline int locate_decl_type_enum(decl_enums *enums, decl_type *type) {
+ size_t i;
+
+ if (type->enm) {
+ return 1;
+ }
+ for (i = 0; i < enums->count; ++i) {
+ if (!strcmp(enums->list[i]->name, type->name)) {
+ type->enm = enums->list[i];
+ return 1;
+ }
+ }
+ return 0;
+}
+
static inline int validate_decl_type(PSI_Data *data, decl_type *type) {
switch (type->type) {
case PSI_T_CHAR:
return 0;
}
break;
+ case PSI_T_ENUM:
+ if (!data->enums || !locate_decl_type_enum(data->enums, type)) {
+ return 0;
+ }
}
return 1;
}
static inline decl_arg *locate_decl_var_arg(decl_var *var, decl_args *args, decl_arg *func) {
size_t i;
- for (i = 0; i < args->count; ++i) {
+ if (args) for (i = 0; i < args->count; ++i) {
decl_arg *arg = args->args[i];
if (!strcmp(var->name, arg->var->name)) {
return NULL;
}
-static inline int validate_num_exp(PSI_Data *data, decl_args *dargs, decl_arg *func, num_exp *exp) {
+static inline decl_enum_item *locate_num_exp_enum_item_ex(num_exp *exp, decl_enum *e) {
+ size_t k;
+
+ if (e) for (k = 0; k < e->items->count; ++k) {
+ decl_enum_item *i = e->items->list[k];
+
+ if (!strcmp(i->name, exp->u.dvar->name)) {
+ free_decl_var(exp->u.dvar);
+ exp->t = PSI_T_ENUM;
+ exp->u.enm = i;
+ return i;
+ }
+ }
+ return NULL;
+}
+static inline decl_enum_item *locate_num_exp_enum_item(num_exp *exp, decl_enums *enums) {
+ size_t j;
+
+ if (enums) for (j = 0; j < enums->count; ++j) {
+ decl_enum *e = enums->list[j];
+ decl_enum_item *i = locate_num_exp_enum_item_ex(exp, e);
+
+ if (i) {
+ return i;
+ }
+ }
+ return NULL;
+}
+static inline int validate_num_exp(PSI_Data *data, num_exp *exp, decl_args *dargs, decl_arg *func, decl_enum *enm) {
if (exp->operand) {
switch (exp->operator) {
case PSI_T_PLUS:
break;
EMPTY_SWITCH_DEFAULT_CASE();
}
- if (!validate_num_exp(data, dargs, func, exp->operand)) {
+ if (!validate_num_exp(data, exp->operand, dargs, func, enm)) {
return 0;
}
}
switch (exp->t) {
case PSI_T_NAME:
if (!locate_decl_var_arg(exp->u.dvar, dargs, func)) {
- data->error(exp->token, PSI_WARNING, "Unknown variable '%s' in numeric expression",
- exp->u.dvar->name);
- return 0;
+ if (!locate_num_exp_enum_item(exp, data->enums) && !locate_num_exp_enum_item_ex(exp, enm)) {
+ data->error(exp->token, PSI_WARNING, "Unknown variable '%s' in numeric expression",
+ exp->u.dvar->name);
+ return 0;
+ }
}
return 1;
case PSI_T_NSNAME:
}
return 1;
case PSI_T_NUMBER:
+ case PSI_T_ENUM:
return 1;
default:
return 0;
}
}
+
+static inline int validate_decl_enum(PSI_Data *data, decl_enum *e) {
+ size_t j;
+
+ if (!e->items || !e->items->count) {
+ data->error(e->token, PSI_WARNING, "Empty enum '%s'", e->name);
+ return 0;
+ }
+
+ for (j = 0; j < e->items->count; ++j) {
+ decl_enum_item *i = e->items->list[j];
+
+ if (!i->num) {
+ if (j) {
+ i->inc.t = PSI_T_NUMBER;
+ i->inc.u.numb = "1";
+ i->inc.operator = PSI_T_PLUS;
+ i->inc.operand = i->prev->num ?: &i->prev->inc;
+ i->num = &i->inc;
+ } else {
+ i->inc.t = PSI_T_NUMBER;
+ i->inc.u.numb = "0";
+ i->num = &i->inc;
+ }
+ }
+ if (!validate_num_exp(data, i->num, NULL, NULL, e)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
static inline int validate_set_value_handler(set_value *set) {
switch (set->func->type) {
case PSI_T_TO_BOOL:
}
}
if (set->num) {
- if (!validate_num_exp(data, ref_list, ref, set->num)) {
+ if (!validate_num_exp(data, set->num, ref_list, ref, NULL)) {
return 0;
}
}
let->var->array_size));
break;
case PSI_LET_NUMEXP:
- if (!validate_num_exp(data, impl->decl->args, impl->decl->func, let->val->data.num)) {
+ 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, impl->decl->args, impl->decl->func, let->val->data.alloc->nmemb)) {
+ if (!validate_num_exp(data, let->val->data.alloc->nmemb, impl->decl->args, impl->decl->func, NULL)) {
return 0;
}
- if (!validate_num_exp(data, impl->decl->args, impl->decl->func, let->val->data.alloc->size)) {
+ if (!validate_num_exp(data, let->val->data.alloc->size, impl->decl->args, impl->decl->func, NULL)) {
return 0;
}
break;
}
}
}
+ if (D->enums) {
+ size_t i;
+
+ for (i = 0; i < D->enums->count; ++i) {
+ if (validate_decl_enum(PSI_DATA(C), D->enums->list[i])) {
+ C->enums = add_decl_enum(C->enums, D->enums->list[i]);
+ }
+ }
+ }
if (D->consts) {
size_t i;
}
}
+ if (source->enums) for (i = 0; i < source->enums->count; ++i) {
+ decl_enum *denum = source->enums->list[i];
+
+ if (validate_decl_enum(source, denum)) {
+ if (dest) {
+ dest->enums = add_decl_enum(dest->enums, denum);
+ }
+ } else {
+ ++errors;
+ }
+ }
+
if (source->decls) for (i = 0; i < source->decls->count; ++i) {
decl *decl = source->decls->list[i];
fn = zend_get_executed_filename();
ln = zend_get_executed_lineno();
} else if (zend_is_compiling()) {
- fn = zend_get_compiled_filename();
+ fn = zend_get_compiled_filename()->val;
ln = zend_get_compiled_lineno();
}
typedef int token_t;
-/* in php_psi.h */
size_t psi_t_alignment(token_t);
size_t psi_t_size(token_t);
token_t type;
struct decl_type *real;
struct decl_struct *strct;
+ struct decl_enum *enm;
} decl_type;
static inline decl_type *init_decl_type(token_t type, const char *name) {
return t;
}
-static inline decl_type *init_decl_type_ex(token_t type, int argc, ...) {
- va_list argv;
- char *ptr, *arg;
- unsigned i;
- size_t len, pos = 0, all = 0;
- decl_type *t = calloc(1, sizeof(*t));
-
- va_start(argv, argc);
- for (i = 0; i < argc; ++i) {
- arg = va_arg(argv, char *);
- len = va_arg(argv, size_t);
-
- if (len) {
- if (all) {
- pos = all;
- ptr = realloc(ptr, 1 + (all += len));
- } else {
- ptr = malloc(1 + (all = len));
- }
- memcpy(ptr + pos, arg, len);
- }
- }
- va_end(argv);
-
- if (!all) {
- ptr = calloc(1, 1);
- } else {
- ptr[all] = 0;
- }
- t->type = type;
- t->name = ptr;
- return t;
-}
-
static inline decl_type *real_decl_type(decl_type *type) {
while (type->real) {
type = type->real;
free(decls);
}
+
typedef struct decl_struct {
PSI_Token *token;
char *name;
char *numb;
constant *cnst;
decl_var *dvar;
+ struct decl_enum_item *enm;
} u;
token_t operator;
int (*calculator)(int t1, impl_val *v1, int t2, impl_val *v2, impl_val *res);
return exp;
}
+static inline PSI_Token *PSI_TokenCopy(PSI_Token *src);
+static inline num_exp *copy_num_exp(num_exp *exp) {
+ decl_var *dvar;
+ num_exp *num = calloc(1, sizeof(*num));
+
+ memcpy(num, exp, sizeof(*num));
+
+ if (num->token) {
+ num->token = PSI_TokenCopy(num->token);
+ }
+ if (num->operand) {
+ num->operand = copy_num_exp(num->operand);
+ }
+ switch (num->t) {
+ case PSI_T_NUMBER:
+ case PSI_T_NSNAME:
+ num->u.numb = strdup(num->u.numb);
+ break;
+ case PSI_T_NAME:
+ dvar = init_decl_var(num->u.dvar->name, num->u.dvar->pointer_level, num->u.dvar->array_size);
+ dvar->arg = num->u.dvar->arg;
+ if (num->u.dvar->token) {
+ dvar->token = PSI_TokenCopy(num->u.dvar->token);
+ }
+ num->u.dvar = dvar;
+ break;
+ }
+ return num;
+}
+
static inline void free_num_exp(num_exp *exp) {
if (exp->token) {
free(exp->token);
case PSI_T_NAME:
free_decl_var(exp->u.dvar);
break;
+ case PSI_T_ENUM:
+ break;
EMPTY_SWITCH_DEFAULT_CASE();
}
if (exp->operand) {
free(exp);
}
+typedef struct decl_enum_item {
+ PSI_Token *token;
+ char *name;
+ num_exp *num;
+ num_exp inc;
+ struct decl_enum_item *prev;
+} decl_enum_item;
+
+static inline decl_enum_item *init_decl_enum_item(const char *name, num_exp *num) {
+ decl_enum_item *i = calloc(1, sizeof(*i));
+
+ i->name = strdup(name);
+ i->num = num;
+ return i;
+}
+
+static inline void free_decl_enum_item(decl_enum_item *i) {
+ if (i->token) {
+ free(i->token);
+ }
+ if (i->num && i->num != &i->inc) {
+ free_num_exp(i->num);
+ }
+ free(i->name);
+ free(i);
+}
+
+typedef struct decl_enum_items {
+ decl_enum_item **list;
+ size_t count;
+} decl_enum_items;
+
+static inline decl_enum_items *init_decl_enum_items(decl_enum_item *i) {
+ decl_enum_items *l = calloc(1, sizeof(*l));
+
+ if (i) {
+ l->count = 1;
+ l->list = calloc(1, sizeof(*l->list));
+ l->list[0] = i;
+ }
+ return l;
+}
+
+static inline decl_enum_items *add_decl_enum_item(decl_enum_items *l, decl_enum_item *i) {
+ l->list = realloc(l->list, sizeof(*l->list) * (l->count + 1));
+ l->list[l->count] = i;
+ if (l->count) {
+ i->prev = l->list[l->count - 1];
+ }
+ ++l->count;
+ return l;
+}
+
+static inline void free_decl_enum_items(decl_enum_items *l) {
+ if (l->list) {
+ size_t j;
+
+ for (j = 0; j < l->count; ++j) {
+ free_decl_enum_item(l->list[j]);
+ }
+ free(l->list);
+ }
+ free(l);
+}
+
+typedef struct decl_enum {
+ PSI_Token *token;
+ char *name;
+ decl_enum_items *items;
+} decl_enum;
+
+static inline decl_enum *init_decl_enum(const char *name, decl_enum_items *l) {
+ decl_enum *e = calloc(1, sizeof(*e));
+
+ e->name = strdup(name);
+ e->items = l;
+ return e;
+}
+
+static inline void free_decl_enum(decl_enum *e) {
+ if (e->token) {
+ free(e->token);
+ }
+ if (e->items) {
+ free_decl_enum_items(e->items);
+ }
+ free(e->name);
+ free(e);
+}
+
+typedef struct decl_enums {
+ decl_enum **list;
+ size_t count;
+} decl_enums;
+
+static inline decl_enums* add_decl_enum(decl_enums *es, decl_enum *e) {
+ if (!es) {
+ es = calloc(1, sizeof(*es));
+ }
+ es->list = realloc(es->list, ++es->count * sizeof(*es->list));
+ es->list[es->count-1] = e;
+ return es;
+}
+
+static inline void free_decl_enums(decl_enums *es) {
+ if (es->list) {
+ size_t j;
+
+ for (j = 0; j < es->count; ++j) {
+ free_decl_enum(es->list[j]);
+ }
+ }
+ free(es->list);
+ free(es);
+}
+
typedef struct let_calloc {
num_exp *nmemb;
num_exp *size;
constants *consts; \
decl_typedefs *defs; \
decl_structs *structs; \
+ decl_enums *enums; \
decls *decls; \
impls *impls; \
union { \
if (data->structs) {
free_decl_structs(data->structs);
}
+ if (data->enums) {
+ free_decl_enums(data->enums);
+ }
if (data->decls) {
free_decls(data->decls);
}
'FUNCTION' {RETURN(PSI_T_FUNCTION);}
'TYPEDEF' {RETURN(PSI_T_TYPEDEF);}
'STRUCT' {RETURN(PSI_T_STRUCT);}
+ 'ENUM' {RETURN(PSI_T_ENUM);}
'CONST' {RETURN(PSI_T_CONST);}
'LIB' {RETURN(PSI_T_LIB);}
'LET' {RETURN(PSI_T_LET);}
#define PSI_T_EOF 13
#define PSI_T_EOS 14
#define PSI_T_QUOTED_STRING 15
-#define PSI_T_STRUCT 16
+#define PSI_T_ENUM 16
#define PSI_T_LBRACE 17
#define PSI_T_RBRACE 18
-#define PSI_T_COLON 19
-#define PSI_T_LPAREN 20
-#define PSI_T_NUMBER 21
-#define PSI_T_RPAREN 22
-#define PSI_T_BOOL 23
-#define PSI_T_INT 24
-#define PSI_T_FLOAT 25
-#define PSI_T_CONST 26
-#define PSI_T_NSNAME 27
-#define PSI_T_EQUALS 28
-#define PSI_T_TYPEDEF 29
-#define PSI_T_VOID 30
-#define PSI_T_LBRACKET 31
-#define PSI_T_RBRACKET 32
-#define PSI_T_COMMA 33
-#define PSI_T_ELLIPSIS 34
-#define PSI_T_CHAR 35
-#define PSI_T_SHORT 36
-#define PSI_T_LONG 37
-#define PSI_T_DOUBLE 38
-#define PSI_T_UNSIGNED 39
-#define PSI_T_SIGNED 40
-#define PSI_T_INT8 41
-#define PSI_T_UINT8 42
-#define PSI_T_INT16 43
-#define PSI_T_UINT16 44
-#define PSI_T_INT32 45
-#define PSI_T_UINT32 46
-#define PSI_T_INT64 47
-#define PSI_T_UINT64 48
-#define PSI_T_FUNCTION 49
-#define PSI_T_NULL 50
-#define PSI_T_TRUE 51
-#define PSI_T_FALSE 52
-#define PSI_T_DOLLAR 53
-#define PSI_T_CALLOC 54
-#define PSI_T_OBJVAL 55
-#define PSI_T_ARRVAL 56
-#define PSI_T_PATHVAL 57
-#define PSI_T_STRLEN 58
-#define PSI_T_STRVAL 59
-#define PSI_T_FLOATVAL 60
-#define PSI_T_INTVAL 61
-#define PSI_T_BOOLVAL 62
-#define PSI_T_TO_OBJECT 63
-#define PSI_T_TO_ARRAY 64
-#define PSI_T_TO_STRING 65
-#define PSI_T_TO_INT 66
-#define PSI_T_TO_FLOAT 67
-#define PSI_T_TO_BOOL 68
-#define PSI_T_MIXED 69
-#define PSI_T_ARRAY 70
-#define PSI_T_OBJECT 71
-#define PSI_T_AMPERSAND 72
+#define PSI_T_COMMA 19
+#define PSI_T_EQUALS 20
+#define PSI_T_STRUCT 21
+#define PSI_T_COLON 22
+#define PSI_T_LPAREN 23
+#define PSI_T_NUMBER 24
+#define PSI_T_RPAREN 25
+#define PSI_T_BOOL 26
+#define PSI_T_INT 27
+#define PSI_T_FLOAT 28
+#define PSI_T_CONST 29
+#define PSI_T_NSNAME 30
+#define PSI_T_TYPEDEF 31
+#define PSI_T_VOID 32
+#define PSI_T_LBRACKET 33
+#define PSI_T_RBRACKET 34
+#define PSI_T_ELLIPSIS 35
+#define PSI_T_CHAR 36
+#define PSI_T_SHORT 37
+#define PSI_T_LONG 38
+#define PSI_T_DOUBLE 39
+#define PSI_T_UNSIGNED 40
+#define PSI_T_SIGNED 41
+#define PSI_T_INT8 42
+#define PSI_T_UINT8 43
+#define PSI_T_INT16 44
+#define PSI_T_UINT16 45
+#define PSI_T_INT32 46
+#define PSI_T_UINT32 47
+#define PSI_T_INT64 48
+#define PSI_T_UINT64 49
+#define PSI_T_FUNCTION 50
+#define PSI_T_NULL 51
+#define PSI_T_TRUE 52
+#define PSI_T_FALSE 53
+#define PSI_T_DOLLAR 54
+#define PSI_T_CALLOC 55
+#define PSI_T_OBJVAL 56
+#define PSI_T_ARRVAL 57
+#define PSI_T_PATHVAL 58
+#define PSI_T_STRLEN 59
+#define PSI_T_STRVAL 60
+#define PSI_T_FLOATVAL 61
+#define PSI_T_INTVAL 62
+#define PSI_T_BOOLVAL 63
+#define PSI_T_TO_OBJECT 64
+#define PSI_T_TO_ARRAY 65
+#define PSI_T_TO_STRING 66
+#define PSI_T_TO_INT 67
+#define PSI_T_TO_FLOAT 68
+#define PSI_T_TO_BOOL 69
+#define PSI_T_MIXED 70
+#define PSI_T_ARRAY 71
+#define PSI_T_OBJECT 72
+#define PSI_T_AMPERSAND 73
block ::= decl_struct(strct). {
P->structs = add_decl_struct(P->structs, strct);
}
+block ::= decl_enum(e). {
+ P->enums = add_decl_enum(P->enums, e);
+}
+
+enum_name(n) ::= ENUM NAME(N). {
+ n = N;
+}
+
+%type decl_enum {decl_enum *}
+%destructor decl_enum {free_decl_enum($$);}
+decl_enum(e) ::= enum_name(N) LBRACE decl_enum_items(list) RBRACE. {
+ e = init_decl_enum(N->text, list);
+ e->token = N;
+}
+
+%type decl_enum_items {decl_enum_items*}
+%destructor decl_enum_items {free_decl_enum_items($$);}
+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);
+}
+
+%type decl_enum_item {decl_enum_item*}
+%destructor decl_enum_item {free_decl_enum_item($$);}
+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;
+}
struct_name(n) ::= STRUCT NAME(N). {
n = N;
type_->token = T;
free(S);
}
+decl_type(type_) ::= ENUM(E) NAME(T). {
+ type_ = init_decl_type(E->type, T->text);
+ type_->token = T;
+ free(E);
+}
%token_class decl_type_token FLOAT DOUBLE INT8 UINT8 INT16 UINT16 INT32 UINT32 INT64 UINT64 NAME.
%type decl_type {decl_type*}
%destructor decl_type {free_decl_type($$);}