enum support

This commit is contained in:
Bill Currie 2002-01-21 19:03:29 +00:00
parent d5fb0f5a68
commit 64c5983742
7 changed files with 137 additions and 15 deletions

View file

@ -128,6 +128,7 @@ expr_t *new_binary_expr (int op, expr_t *e1, expr_t *e2);
expr_t *new_unary_expr (int op, expr_t *e1);
expr_t *new_temp_def_expr (type_t *type);
expr_t *new_bind_expr (expr_t *e1, expr_t *e2);
expr_t *new_name_expr (const char *name);
void inc_users (expr_t *e);

View file

@ -45,4 +45,7 @@ struct_field_t *struct_find_field (struct type_s *strct, const char *name);
struct type_s *new_struct (const char *name);
struct type_s *find_struct (const char *name);
void process_enum (struct expr_s *enm);
expr_t *get_enum (const char *name);
#endif//__struct_h

View file

@ -103,14 +103,22 @@ void
convert_name (expr_t *e)
{
if (e->type == ex_name) {
const char * name = e->e.string_val;
const char *name = e->e.string_val;
def_t *d = PR_GetDef (NULL, name, pr_scope, 0);
expr_t *enm;
e->type = ex_def;
e->e.def = PR_GetDef (NULL, name, pr_scope, false);
if (!e->e.def) {
error (e, "Undeclared variable \"%s\".", name);
e->e.def = &def_float;
if (d) {
e->type = ex_def;
e->e.def = d;
return;
}
enm = get_enum (name);
if (enm) {
e->type = ex_integer;
e->e.integer_val = enm->e.integer_val;
return;
}
error (e, "Undeclared variable \"%s\".", name);
}
}
@ -418,6 +426,15 @@ new_bind_expr (expr_t *e1, expr_t *e2)
return e;
}
expr_t *
new_name_expr (const char *name)
{
expr_t *e = new_expr ();
e->type = ex_name;
e->e.string_val = name;
return e;
}
expr_t *
append_expr (expr_t *block, expr_t *e)
{

View file

@ -26,6 +26,7 @@ static const char rcsid[] =
#include <QF/sys.h>
#include "qfcc.h"
#include "struct.h"
typedef struct locref_s {
struct locref_s *next;
@ -60,6 +61,10 @@ check_for_name (type_t *type, const char *name, def_t *scope, int *allocate)
if (!defs_by_name) {
defs_by_name = Hash_NewTable (16381, defs_get_key, 0, &defs_by_name);
}
if (!scope && (find_struct (name) || get_enum (name))) {
error (0, "%s redeclared", name);
return 0;
}
// see if the name is already in use
def = (def_t *) Hash_Find (defs_by_name, name);
if (def) {

View file

@ -241,6 +241,7 @@ static keyword_t keywords[] = {
{"default", DEFAULT, 0, PROG_ID_VERSION},
{"NIL", NIL, 0, PROG_ID_VERSION},
{"struct", STRUCT, 0, PROG_VERSION},
{"enum", ENUM, 0, PROG_ID_VERSION},
};
static const char *

View file

@ -110,7 +110,7 @@ typedef struct {
%token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELIPSIS NIL
%token IFBE IFB IFAE IFA
%token SWITCH CASE DEFAULT STRUCT
%token SWITCH CASE DEFAULT STRUCT ENUM
%token <type> TYPE
%type <type> type opt_func func_parms array_decl
@ -120,7 +120,7 @@ typedef struct {
%type <def> func_def_item func_def_list
%type <expr> const opt_expr expr arg_list element_list element_list1 element
%type <expr> statement statements statement_block
%type <expr> break_label continue_label
%type <expr> break_label continue_label enum_list enum
%type <function> begin_function
%type <def_list> save_inits
%type <switch_block> switch_block
@ -160,6 +160,8 @@ def
{ current_type = build_type ($1, $4); } func_def_list
| STRUCT NAME
{ struct_type = new_struct ($2); } '=' '{' struct_defs '}'
| ENUM '{' enum_list opt_comma '}'
{ process_enum ($3); }
;
struct_defs
@ -176,6 +178,34 @@ struct_def
{ current_type = build_type ($1, $4); } struct_def_list
;
enum_list
: enum
| enum_list ',' enum
{
if ($3) {
$3->next = $1;
$$ = $3;
} else {
$$ = $1;
}
}
;
enum
: NAME { $$ = new_name_expr ($1); }
| NAME '=' expr
{
$$ = 0;
if ($3->type < ex_string) {
error ($3, "non-constant initializer");
} else if ($3->type != ex_integer) {
error ($3, "invalid initializer type");
} else {
$$ = new_binary_expr ('=', new_name_expr ($1), $3);
}
}
;
opt_field
: /* empty */ { $$ = 0; }
| '.' { $$ = 1; }
@ -251,7 +281,7 @@ var_def_item
: def_name opt_var_initializer
{
$$ = $1;
if (!$$->scope && $$->type->type != ev_func)
if ($$ && !$$->scope && $$->type->type != ev_func)
PR_DefInitialized ($$);
}
;
@ -758,12 +788,7 @@ expr
| '&' expr %prec UNARY { $$ = address_expr ($2, 0, 0); }
| INCOP expr { $$ = incop_expr ($1, $2, 0); }
| expr INCOP { $$ = incop_expr ($2, $1, 1); }
| NAME
{
$$ = new_expr ();
$$->type = ex_name;
$$->e.string_val = $1;
}
| NAME { $$ = new_name_expr ($1); }
| const { $$ = $1; }
| '(' expr ')' { $$ = $2; $$->paren = 1; }
;

View file

@ -31,6 +31,7 @@ static const char rcsid[] =
"$Id$";
#include <QF/hash.h>
#include <QF/sys.h>
#include "qfcc.h"
#include "struct.h"
@ -40,7 +41,13 @@ typedef struct {
type_t *type;
} struct_t;
typedef struct {
const char *name;
expr_t value;
} enum_t;
static hashtab_t *structs;
static hashtab_t *enums;
static const char *
structs_get_key (void *s, void *unused)
@ -54,6 +61,12 @@ struct_field_get_key (void *f, void *unused)
return ((struct_field_t *) f)->name;
}
static const char *
enums_get_key (void *e, void *unused)
{
return ((enum_t *) e)->name;
}
struct_field_t *
new_struct_field (type_t *strct, type_t *type, const char *name)
{
@ -116,3 +129,60 @@ find_struct (const char *name)
return strct->type;
return 0;
}
void
process_enum (expr_t *enm)
{
expr_t *e = enm;
expr_t *c_enum = 0;
int enum_val = 0;
if (!enums) {
enums = Hash_NewTable (16381, enums_get_key, 0, 0);
}
while (e) {
expr_t *t = e->next;
e->next = c_enum;
c_enum = e;
e = t;
}
for (e = c_enum; e; e = e->next) {
expr_t *name = e;
expr_t *val = 0;
enum_t *new_enum;
if (name->type == ex_expr) {
val = name->e.expr.e2;
name = name->e.expr.e1;
}
if ((structs && find_struct (name->e.string_val))
|| get_enum (name->e.string_val)
|| PR_GetDef (NULL, name->e.string_val, 0, 0)) {
error (name, "%s redeclared", name->e.string_val);
continue;
}
if (val)
enum_val = val->e.integer_val;
new_enum = malloc (sizeof (enum_t));
if (!new_enum)
Sys_Error ("out of memory");
new_enum->name = name->e.string_val;
new_enum->value.type = ex_integer;
new_enum->value.e.integer_val = enum_val++;
Hash_Add (enums, new_enum);
//printf ("%s = %d\n", new_enum->name, new_enum->value.e.integer_val);
}
}
expr_t *
get_enum (const char *name)
{
enum_t *e;
if (!enums)
return 0;
e = (enum_t *) Hash_Find (enums, name);
if (!e)
return 0;
return &e->value;
}