From: Wolfgang (Blub) Bumiller Date: Fri, 30 Nov 2012 23:31:00 +0000 (+0100) Subject: some SYA fix; adding optional variable parsing to the head of a switch block X-Git-Tag: 0.1.9~152 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=d52879315d0f511ea256b51814f1ef09f79b0d3d;p=xonotic%2Fgmqcc.git some SYA fix; adding optional variable parsing to the head of a switch block --- diff --git a/parser.c b/parser.c index 12e3096..6c126c6 100644 --- a/parser.c +++ b/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);