mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2024-11-24 04:41:25 +00:00
tempcomitting parser changes for fields
This commit is contained in:
parent
c16a17ed5f
commit
5c0ac35d4c
1 changed files with 136 additions and 1 deletions
135
parser.c
135
parser.c
|
@ -13,7 +13,10 @@ typedef struct {
|
|||
lex_file *lex;
|
||||
int tok;
|
||||
|
||||
int fieldsize;
|
||||
|
||||
MEM_VECTOR_MAKE(varentry_t, globals);
|
||||
MEM_VECTOR_MAKE(varentry_t, fields);
|
||||
MEM_VECTOR_MAKE(ast_function*, functions);
|
||||
MEM_VECTOR_MAKE(ast_value*, imm_float);
|
||||
MEM_VECTOR_MAKE(ast_value*, imm_string);
|
||||
|
@ -27,6 +30,7 @@ typedef struct {
|
|||
} parser_t;
|
||||
|
||||
MEM_VEC_FUNCTIONS(parser_t, varentry_t, globals)
|
||||
MEM_VEC_FUNCTIONS(parser_t, varentry_t, fields)
|
||||
MEM_VEC_FUNCTIONS(parser_t, ast_value*, imm_float)
|
||||
MEM_VEC_FUNCTIONS(parser_t, ast_value*, imm_string)
|
||||
MEM_VEC_FUNCTIONS(parser_t, ast_value*, imm_vector)
|
||||
|
@ -126,6 +130,16 @@ ast_value* parser_const_vector(parser_t *parser, vector v)
|
|||
return out;
|
||||
}
|
||||
|
||||
ast_expression* parser_find_field(parser_t *parser, const char *name)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < parser->fields_count; ++i) {
|
||||
if (!strcmp(parser->fields[i].name, name))
|
||||
return parser->fields[i].var;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ast_expression* parser_find_global(parser_t *parser, const char *name)
|
||||
{
|
||||
size_t i;
|
||||
|
@ -1186,9 +1200,104 @@ static bool parser_do(parser_t *parser)
|
|||
}
|
||||
else if (parser->tok == '.')
|
||||
{
|
||||
ast_value *var;
|
||||
ast_value *fld;
|
||||
bool isfunc = false;
|
||||
int basetype;
|
||||
lex_ctx ctx = parser_ctx(parser);
|
||||
varentry_t varent;
|
||||
|
||||
/* entity-member declaration */
|
||||
if (!parser_next(parser) || parser->tok != TOKEN_TYPENAME) {
|
||||
parseerror(parser, "expected member variable definition");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* remember the base/return type */
|
||||
basetype = parser_token(parser)->constval.t;
|
||||
|
||||
/* parse into the declaration */
|
||||
if (!parser_next(parser)) {
|
||||
parseerror(parser, "expected field def");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* parse the field type fully */
|
||||
var = parser_parse_type(parser, basetype, &isfunc);
|
||||
if (!var)
|
||||
return false;
|
||||
|
||||
/* now the field name */
|
||||
if (parser->tok != TOKEN_IDENT) {
|
||||
parseerror(parser, "expected field name");
|
||||
ast_delete(var);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check for an existing field
|
||||
* in original qc we also have to check for an existing
|
||||
* global named like the field
|
||||
*/
|
||||
if (opts_standard == COMPILER_QCC) {
|
||||
if (parser_find_global(parser, parser_tokval(parser))) {
|
||||
parseerror(parser, "cannot declare a field and a global of the same name with -std=qcc");
|
||||
ast_delete(var);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (parser_find_field(parser, parser_tokval(parser))) {
|
||||
parseerror(parser, "field %s already exists", parser_tokval(parser));
|
||||
ast_delete(var);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* if it was a function, turn it into a function */
|
||||
if (isfunc) {
|
||||
ast_value *fval;
|
||||
/* turn var into a value of TYPE_FUNCTION, with the old var
|
||||
* as return type
|
||||
*/
|
||||
fval = ast_value_new(ctx, var->name, TYPE_FUNCTION);
|
||||
if (!fval) {
|
||||
ast_value_delete(var);
|
||||
ast_value_delete(fval);
|
||||
return false;
|
||||
}
|
||||
|
||||
fval->expression.next = (ast_expression*)var;
|
||||
MEM_VECTOR_MOVE(&var->expression, params, &fval->expression, params);
|
||||
|
||||
var = fval;
|
||||
}
|
||||
|
||||
/* turn it into a field */
|
||||
fld = ast_value_new(ctx, parser_tokval(parser), TYPE_FIELD);
|
||||
fld->expression.next = (ast_expression*)var;
|
||||
|
||||
varent.var = (ast_expression*)fld;
|
||||
if (var->expression.vtype == TYPE_VECTOR)
|
||||
{
|
||||
/* create _x, _y and _z fields as well */
|
||||
parseerror(parser, "TODO: vector field members (_x,_y,_z)");
|
||||
ast_delete(fld);
|
||||
return false;
|
||||
}
|
||||
|
||||
varent.name = util_strdup(fld->name);
|
||||
(void)!parser_t_fields_add(parser, varent);
|
||||
|
||||
/* end with a semicolon */
|
||||
if (!parser_next(parser) || parser->tok != ';') {
|
||||
parseerror(parser, "semicolon expected");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* skip the semicolon */
|
||||
if (!parser_next(parser))
|
||||
return parser->tok == TOKEN_EOF;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
parseerror(parser, "unexpected token: %s", parser->lex->tok->value);
|
||||
|
@ -1302,6 +1411,32 @@ bool parser_finish(const char *output)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < parser->fields_count; ++i) {
|
||||
ast_value *field;
|
||||
bool isconst;
|
||||
if (!ast_istype(parser->fields[i].var, ast_value))
|
||||
continue;
|
||||
field = (ast_value*)parser->fields[i].var;
|
||||
isconst = field->isconst;
|
||||
field->isconst = false;
|
||||
if (!ast_global_codegen((ast_value*)field, ir)) {
|
||||
printf("failed to generate field %s\n", field->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
if (isconst) {
|
||||
ir_value *ifld;
|
||||
ast_expression *subtype;
|
||||
field->isconst = true;
|
||||
subtype = field->expression.next;
|
||||
ifld = ir_builder_create_field(ir, field->name, subtype->expression.vtype);
|
||||
if (subtype->expression.vtype == TYPE_FIELD)
|
||||
ifld->fieldtype = subtype->expression.next->expression.vtype;
|
||||
else if (subtype->expression.vtype == TYPE_FUNCTION)
|
||||
ifld->outtype = subtype->expression.next->expression.vtype;
|
||||
(void)!ir_value_set_field(field->ir_v, ifld);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < parser->globals_count; ++i) {
|
||||
if (!ast_istype(parser->globals[i].var, ast_value))
|
||||
continue;
|
||||
|
|
Loading…
Reference in a new issue