mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-02-17 09:02:25 +00:00
parsing goto
This commit is contained in:
parent
4b71b74c6a
commit
24f9b63475
3 changed files with 61 additions and 1 deletions
5
ast.c
5
ast.c
|
@ -844,6 +844,11 @@ void ast_goto_delete(ast_goto *self)
|
|||
mem_d(self);
|
||||
}
|
||||
|
||||
void ast_goto_set_label(ast_goto *self, ast_label *label)
|
||||
{
|
||||
self->target = label;
|
||||
}
|
||||
|
||||
ast_call* ast_call_new(lex_ctx ctx,
|
||||
ast_expression *funcexpr)
|
||||
{
|
||||
|
|
2
ast.h
2
ast.h
|
@ -525,7 +525,7 @@ struct ast_goto_s
|
|||
|
||||
ast_goto* ast_goto_new(lex_ctx ctx, const char *name);
|
||||
void ast_goto_delete(ast_goto*);
|
||||
void ast_goto_setlabel(ast_goto*, ast_label*);
|
||||
void ast_goto_set_label(ast_goto*, ast_label*);
|
||||
|
||||
bool ast_goto_codegen(ast_goto*, ast_function*, bool lvalue, ir_value**);
|
||||
|
||||
|
|
55
parser.c
55
parser.c
|
@ -58,6 +58,12 @@ typedef struct {
|
|||
|
||||
ast_function *function;
|
||||
|
||||
/* All the labels the function defined...
|
||||
* Should they be in ast_function instead?
|
||||
*/
|
||||
ast_label **labels;
|
||||
ast_goto **gotos;
|
||||
|
||||
/* A list of hashtables for each scope */
|
||||
ht *variables;
|
||||
ht htfields;
|
||||
|
@ -2227,6 +2233,40 @@ static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **ou
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool parse_goto(parser_t *parser, ast_expression **out)
|
||||
{
|
||||
size_t i;
|
||||
ast_goto *gt;
|
||||
|
||||
if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
|
||||
parseerror(parser, "expected label name after `goto`");
|
||||
return false;
|
||||
}
|
||||
|
||||
gt = ast_goto_new(parser_ctx(parser), parser_tokval(parser));
|
||||
|
||||
for (i = 0; i < vec_size(parser->labels); ++i) {
|
||||
if (!strcmp(parser->labels[i]->name, parser_tokval(parser))) {
|
||||
ast_goto_set_label(gt, parser->labels[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == vec_size(parser->labels))
|
||||
vec_push(parser->gotos, gt);
|
||||
|
||||
if (!parser_next(parser) || parser->tok != ';') {
|
||||
parseerror(parser, "semicolon expected after goto label");
|
||||
return false;
|
||||
}
|
||||
if (!parser_next(parser)) {
|
||||
parseerror(parser, "parse error after goto");
|
||||
return false;
|
||||
}
|
||||
|
||||
*out = (ast_expression*)gt;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parse_statement(parser_t *parser, ast_block *block, ast_expression **out, bool allow_cases)
|
||||
{
|
||||
ast_value *typevar = NULL;
|
||||
|
@ -2316,6 +2356,10 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression *
|
|||
}
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(parser_tokval(parser), "goto"))
|
||||
{
|
||||
return parse_goto(parser, out);
|
||||
}
|
||||
else if (!strcmp(parser_tokval(parser), "typedef"))
|
||||
{
|
||||
if (!parser_next(parser)) {
|
||||
|
@ -2350,6 +2394,7 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression *
|
|||
label = ast_label_new(parser_ctx(parser), parser_tokval(parser));
|
||||
if (!label)
|
||||
return false;
|
||||
vec_push(parser->labels, label);
|
||||
*out = (ast_expression*)label;
|
||||
if (!parser_next(parser)) {
|
||||
parseerror(parser, "parse error after label");
|
||||
|
@ -2495,6 +2540,11 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
|
|||
has_frame_think = false;
|
||||
old = parser->function;
|
||||
|
||||
if (vec_size(parser->gotos) || vec_size(parser->labels)) {
|
||||
parseerror(parser, "gotos/labels leaking");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (var->expression.variadic) {
|
||||
if (parsewarning(parser, WARN_VARIADIC_FUNCTION,
|
||||
"variadic function with implementation will not be able to access additional parameters"))
|
||||
|
@ -3871,6 +3921,8 @@ skipvar:
|
|||
if (!parse_function_body(parser, var))
|
||||
break;
|
||||
ast_delete(basetype);
|
||||
vec_free(parser->gotos);
|
||||
vec_free(parser->labels);
|
||||
return true;
|
||||
} else {
|
||||
ast_expression *cexp;
|
||||
|
@ -4248,6 +4300,9 @@ void parser_cleanup()
|
|||
vec_free(parser->typedefs);
|
||||
vec_free(parser->_blocktypedefs);
|
||||
|
||||
vec_free(parser->labels);
|
||||
vec_free(parser->gotos);
|
||||
|
||||
mem_d(parser);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue