if (op->id == opid1(',') && !parens && stopatcomma)
break;
+ if (sy.ops_count && !sy.ops[sy.ops_count-1].paren)
+ olast = &operators[sy.ops[sy.ops_count-1].etype-1];
+
+ while (olast && (
+ (op->prec < olast->prec) ||
+ (op->assoc == ASSOC_LEFT && op->prec <= olast->prec) ) )
+ {
+ if (!parser_sy_pop(parser, &sy))
+ goto onerr;
+ if (sy.ops_count && !sy.ops[sy.ops_count-1].paren)
+ olast = &operators[sy.ops[sy.ops_count-1].etype-1];
+ else
+ olast = NULL;
+ }
+
if (op->id == opid1('.')) {
/* for gmqcc standard: open up the namespace of the previous type */
ast_expression *prevex = sy.out[sy.out_count-1].out;
gotmemberof = true;
}
- if (sy.ops_count && !sy.ops[sy.ops_count-1].paren)
- olast = &operators[sy.ops[sy.ops_count-1].etype-1];
-
- while (olast && (
- (op->prec < olast->prec) ||
- (op->assoc == ASSOC_LEFT && op->prec <= olast->prec) ) )
- {
- if (!parser_sy_pop(parser, &sy))
- goto onerr;
- if (sy.ops_count && !sy.ops[sy.ops_count-1].paren)
- olast = &operators[sy.ops[sy.ops_count-1].etype-1];
- else
- olast = NULL;
- }
-
if (op->id == opid1('(')) {
if (wantop) {
DEBUGSHUNTDO(printf("push (\n"));
ast_delete(exp);
return false;
}
-
- *out = (ast_expression*)ret;
- } else if (!parser_next(parser)) {
- parseerror(parser, "expected semicolon");
+ } else {
+ if (!parser_next(parser))
+ parseerror(parser, "parse error");
if (expected->expression.next->expression.vtype != TYPE_VOID) {
parseerror(parser, "return without value");
}
+ ret = ast_return_new(parser_ctx(parser), NULL);
}
+ *out = (ast_expression*)ret;
return true;
}
else if (!strcmp(parser_tokval(parser), "if"))
break;
if (!parser_parse_statement(parser, block, &expr)) {
+ parseerror(parser, "parse error");
ast_block_delete(block);
block = NULL;
goto cleanup;
static ast_expression* parser_parse_statement_or_block(parser_t *parser)
{
- ast_expression *expr;
+ ast_expression *expr = NULL;
if (parser->tok == '{')
return (ast_expression*)parser_parse_block(parser);
if (!parser_parse_statement(parser, NULL, &expr))
varentry_t varent;
ast_expression *olddecl;
+ bool hadproto;
+
int basetype = parser_token(parser)->constval.t;
while (true)
{
+ hadproto = false;
+
if (!parser_next(parser)) { /* skip basetype or comma */
parseerror(parser, "expected variable declaration");
return false;
}
ast_function_delete(func);
ast_value_delete(fval);
- var = proto;
- func = var->constval.vfunc;
+ fval = proto;
+ func = proto->constval.vfunc;
+ hadproto = true;
}
else
{
var = fval;
}
- varent.name = util_strdup(var->name);
- varent.var = (ast_expression*)var;
- if (var->expression.vtype == TYPE_VECTOR)
- {
- size_t len = strlen(varent.name);
- varentry_t vx, vy, vz;
- vx.var = (ast_expression*)ast_member_new(var->expression.node.context, (ast_expression*)var, 0);
- vy.var = (ast_expression*)ast_member_new(var->expression.node.context, (ast_expression*)var, 1);
- vz.var = (ast_expression*)ast_member_new(var->expression.node.context, (ast_expression*)var, 2);
- vx.name = (char*)mem_a(len+3);
- vy.name = (char*)mem_a(len+3);
- vz.name = (char*)mem_a(len+3);
- memcpy(vx.name, varent.name, len);
- memcpy(vy.name, varent.name, len);
- memcpy(vz.name, varent.name, len);
- vx.name[len] = vy.name[len] = vz.name[len] = '_';
- vx.name[len+1] = 'x';
- vy.name[len+1] = 'y';
- vz.name[len+1] = 'z';
- vx.name[len+2] = vy.name[len+2] = vz.name[len+2] = 0;
-
- if (!localblock) {
- (void)!parser_t_globals_add(parser, varent);
- (void)!parser_t_globals_add(parser, vx);
- (void)!parser_t_globals_add(parser, vy);
- (void)!parser_t_globals_add(parser, vz);
- } else {
- (void)!parser_t_locals_add(parser, varent);
- (void)!parser_t_locals_add(parser, vx);
- (void)!parser_t_locals_add(parser, vy);
- (void)!parser_t_locals_add(parser, vz);
- if (!ast_block_locals_add(localblock, var) ||
- !ast_block_collect(localblock, vx.var) ||
- !ast_block_collect(localblock, vy.var) ||
- !ast_block_collect(localblock, vz.var))
+ if (!hadproto) {
+ varent.name = util_strdup(var->name);
+ varent.var = (ast_expression*)var;
+ if (var->expression.vtype == TYPE_VECTOR)
+ {
+ size_t len = strlen(varent.name);
+ varentry_t vx, vy, vz;
+ vx.var = (ast_expression*)ast_member_new(var->expression.node.context, (ast_expression*)var, 0);
+ vy.var = (ast_expression*)ast_member_new(var->expression.node.context, (ast_expression*)var, 1);
+ vz.var = (ast_expression*)ast_member_new(var->expression.node.context, (ast_expression*)var, 2);
+ vx.name = (char*)mem_a(len+3);
+ vy.name = (char*)mem_a(len+3);
+ vz.name = (char*)mem_a(len+3);
+ memcpy(vx.name, varent.name, len);
+ memcpy(vy.name, varent.name, len);
+ memcpy(vz.name, varent.name, len);
+ vx.name[len] = vy.name[len] = vz.name[len] = '_';
+ vx.name[len+1] = 'x';
+ vy.name[len+1] = 'y';
+ vz.name[len+1] = 'z';
+ vx.name[len+2] = vy.name[len+2] = vz.name[len+2] = 0;
+
+ if (!localblock) {
+ (void)!parser_t_globals_add(parser, varent);
+ (void)!parser_t_globals_add(parser, vx);
+ (void)!parser_t_globals_add(parser, vy);
+ (void)!parser_t_globals_add(parser, vz);
+ } else {
+ (void)!parser_t_locals_add(parser, varent);
+ (void)!parser_t_locals_add(parser, vx);
+ (void)!parser_t_locals_add(parser, vy);
+ (void)!parser_t_locals_add(parser, vz);
+ if (!ast_block_locals_add(localblock, var) ||
+ !ast_block_collect(localblock, vx.var) ||
+ !ast_block_collect(localblock, vy.var) ||
+ !ast_block_collect(localblock, vz.var))
+ {
+ parser_pop_local(parser);
+ parser_pop_local(parser);
+ parser_pop_local(parser);
+ parser_pop_local(parser);
+ ast_value_delete(var);
+ return false;
+ }
+ }
+ }
+ else
+ {
+ if ( (!localblock && !parser_t_globals_add(parser, varent)) ||
+ ( localblock && !parser_t_locals_add(parser, varent)) )
+ {
+ ast_value_delete(var);
+ return false;
+ }
+ if (localblock && !ast_block_locals_add(localblock, var))
{
- parser_pop_local(parser);
- parser_pop_local(parser);
- parser_pop_local(parser);
parser_pop_local(parser);
ast_value_delete(var);
return false;
}
}
}
- else
- {
- if ( (!localblock && !parser_t_globals_add(parser, varent)) ||
- ( localblock && !parser_t_locals_add(parser, varent)) )
- {
- ast_value_delete(var);
- return false;
- }
- if (localblock && !ast_block_locals_add(localblock, var))
- {
- parser_pop_local(parser);
- ast_value_delete(var);
- return false;
- }
- }
if (!parser_next(parser)) {
ast_value_delete(var);
else if (parser->tok == '.')
{
ast_value *var;
+ ast_value *typevar;
ast_value *fld;
ast_expression *oldex;
bool isfunc = false;
}
/* parse the field type fully */
- var = parser_parse_type(parser, basetype, &isfunc);
+ typevar = var = parser_parse_type(parser, basetype, &isfunc);
if (!var)
return false;
while (true) {
+ var = ast_value_copy(typevar);
/* now the field name */
if (parser->tok != TOKEN_IDENT) {
parseerror(parser, "expected field name");
return false;
}
}
+ ast_delete(typevar);
/* skip the semicolon */
if (!parser_next(parser))
else if (!parser->errors)
parseerror(parser, "parse error\n");
lex_close(parser->lex);
- mem_d(parser);
+ parser->lex = NULL;
return false;
}
}
}
lex_close(parser->lex);
+ parser->lex = NULL;
return !parser->errors;
}