mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-03-22 18:51:24 +00:00
some SYA fix; adding optional variable parsing to the head of a switch block
This commit is contained in:
parent
46942df6c0
commit
d52879315d
1 changed files with 63 additions and 0 deletions
63
parser.c
63
parser.c
|
@ -385,6 +385,7 @@ typedef struct
|
|||
#define SY_PAREN_EXPR '('
|
||||
#define SY_PAREN_FUNC 'f'
|
||||
#define SY_PAREN_INDEX '['
|
||||
#define SY_PAREN_TERNARY '?'
|
||||
|
||||
static sy_elem syexp(lex_ctx ctx, ast_expression *v) {
|
||||
sy_elem e;
|
||||
|
@ -1302,6 +1303,13 @@ static bool parser_close_paren(parser_t *parser, shunt *sy, bool functions_only)
|
|||
return false;
|
||||
return true;
|
||||
}
|
||||
if (sy->ops[vec_size(sy->ops)-1].paren == SY_PAREN_TERNARY) {
|
||||
if (functions_only)
|
||||
return false;
|
||||
/* pop off the parenthesis */
|
||||
vec_shrinkby(sy->ops, 1);
|
||||
return true;
|
||||
}
|
||||
if (!parser_sy_pop(parser, sy))
|
||||
return false;
|
||||
}
|
||||
|
@ -1621,10 +1629,13 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
|
|||
} else if (op->id == opid2('?',':')) {
|
||||
wantop = false;
|
||||
vec_push(sy.ops, syop(parser_ctx(parser), op));
|
||||
vec_push(sy.ops, syparen(parser_ctx(parser), SY_PAREN_TERNARY, 0));
|
||||
wantop = false;
|
||||
--ternaries;
|
||||
} else if (op->id == opid2(':','?')) {
|
||||
/* we don't push this operator */
|
||||
if (!parser_close_paren(parser, &sy, false))
|
||||
goto onerr;
|
||||
wantop = false;
|
||||
++ternaries;
|
||||
} else {
|
||||
|
@ -2103,6 +2114,7 @@ static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **ou
|
|||
{
|
||||
ast_expression *operand;
|
||||
ast_value *opval;
|
||||
ast_value *typevar;
|
||||
ast_switch *switchnode;
|
||||
ast_switch_case swcase;
|
||||
|
||||
|
@ -2149,6 +2161,55 @@ static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **ou
|
|||
return false;
|
||||
}
|
||||
|
||||
/* new block; allow some variables to be declared here */
|
||||
parser_enterblock(parser);
|
||||
while (true) {
|
||||
typevar = NULL;
|
||||
if (parser->tok == TOKEN_IDENT)
|
||||
typevar = parser_find_typedef(parser, parser_tokval(parser), 0);
|
||||
if (typevar || parser->tok == TOKEN_TYPENAME) {
|
||||
if (!parse_variable(parser, block, false, CV_NONE, typevar)) {
|
||||
ast_delete(switchnode);
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(parser_tokval(parser), "var") ||
|
||||
!strcmp(parser_tokval(parser), "local"))
|
||||
{
|
||||
if (!parser_next(parser)) {
|
||||
parseerror(parser, "expected variable declaration");
|
||||
ast_delete(switchnode);
|
||||
return false;
|
||||
}
|
||||
if (!parse_variable(parser, block, false, CV_VAR, NULL)) {
|
||||
ast_delete(switchnode);
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(parser_tokval(parser), "const")) {
|
||||
if (!parser_next(parser)) {
|
||||
parseerror(parser, "expected variable declaration");
|
||||
ast_delete(switchnode);
|
||||
return false;
|
||||
}
|
||||
if (!strcmp(parser_tokval(parser), "var")) {
|
||||
if (!parser_next(parser)) {
|
||||
parseerror(parser, "expected variable declaration");
|
||||
ast_delete(switchnode);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!parse_variable(parser, block, false, CV_CONST, NULL)) {
|
||||
ast_delete(switchnode);
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* case list! */
|
||||
while (parser->tok != '}') {
|
||||
ast_block *caseblock;
|
||||
|
@ -2231,6 +2292,8 @@ static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **ou
|
|||
}
|
||||
}
|
||||
|
||||
parser_leaveblock(parser);
|
||||
|
||||
/* closing paren */
|
||||
if (parser->tok != '}') {
|
||||
ast_delete(switchnode);
|
||||
|
|
Loading…
Reference in a new issue