From: Wolfgang Bumiller Date: Sun, 22 Jul 2012 09:17:01 +0000 (+0200) Subject: Handling parenthesis in expressions X-Git-Tag: 0.1-rc1~402 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=dcb815a65f02b2168f7678e3be57d2a3b7d560b2;p=xonotic%2Fgmqcc.git Handling parenthesis in expressions --- diff --git a/parser.c b/parser.c index b023426..1eeda39 100644 --- a/parser.c +++ b/parser.c @@ -182,6 +182,7 @@ static ast_value *parser_parse_type(parser_t *parser, int basetype, bool *isfunc typedef struct { size_t etype; /* 0 = expression, others are operators */ + int paren; ast_expression *out; ast_value *value; /* need to know if we can assign */ lex_ctx ctx; @@ -200,6 +201,7 @@ static sy_elem syexp(lex_ctx ctx, ast_expression *v) { e.out = v; e.value = NULL; e.ctx = ctx; + e.paren = 0; return e; } static sy_elem syval(lex_ctx ctx, ast_value *v) { @@ -208,6 +210,7 @@ static sy_elem syval(lex_ctx ctx, ast_value *v) { e.out = (ast_expression*)v; e.value = v; e.ctx = ctx; + e.paren = 0; return e; } @@ -217,6 +220,17 @@ static sy_elem syop(lex_ctx ctx, const oper_info *op) { e.out = NULL; e.value = NULL; e.ctx = ctx; + e.paren = 0; + return e; +} + +static sy_elem syparen(lex_ctx ctx, int p) { + sy_elem e; + e.etype = 0; + e.out = NULL; + e.value = NULL; + e.ctx = ctx; + e.paren = p; return e; } @@ -234,6 +248,11 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy) return false; } + if (sy->ops[sy->ops_count-1].paren) { + parseerror(parser, "unmatched parenthesis"); + return false; + } + op = &operators[sy->ops[sy->ops_count-1].etype - 1]; ctx = sy->ops[sy->ops_count-1].ctx; @@ -377,6 +396,7 @@ static ast_expression* parser_expression(parser_t *parser) { if (!wantop) { + bool nextwant = true; if (parser->tok == TOKEN_IDENT) { /* variable */ @@ -390,7 +410,8 @@ static ast_expression* parser_expression(parser_t *parser) goto onerr; } printf("Added: %s\n", var->name); - } else if (parser->tok == TOKEN_FLOATCONST) { + } + else if (parser->tok == TOKEN_FLOATCONST) { ast_value *val = parser_const_float(parser, (parser_token(parser)->constval.f)); if (!val) return false; @@ -398,7 +419,8 @@ static ast_expression* parser_expression(parser_t *parser) parseerror(parser, "out of memory"); goto onerr; } - } else if (parser->tok == TOKEN_INTCONST) { + } + else if (parser->tok == TOKEN_INTCONST) { ast_value *val = parser_const_float(parser, (double)(parser_token(parser)->constval.i)); if (!val) return false; @@ -407,18 +429,48 @@ static ast_expression* parser_expression(parser_t *parser) goto onerr; } printf("Added: %i\n", parser_token(parser)->constval.i); - } else { + } + else if (parser->tok == '(') { + nextwant = false; /* not expecting an operator next */ + if (!shunt_ops_add(&sy, syparen(parser_ctx(parser), 1))) { + parseerror(parser, "out of memory"); + goto onerr; + } + } + else { /* TODO: prefix operators */ parseerror(parser, "expected statement"); goto onerr; } - wantop = true; - parser->lex->flags.noops = false; + wantop = nextwant; + parser->lex->flags.noops = !wantop; } else { - if (parser->tok != TOKEN_OPERATOR) { + if (parser->tok == ')') { + /* we do expect an operator next */ + /* closing an opening paren */ + printf("Applying closing paren\n"); + if (!sy.ops_count) { + parseerror(parser, "unmatched closing paren"); + goto onerr; + } + if (sy.ops[sy.ops_count-1].paren == 1) { + parseerror(parser, "empty parenthesis expression"); + goto onerr; + } + while (sy.ops_count) { + if (sy.ops[sy.ops_count-1].paren == 1) { + sy.ops_count--; + break; + } + if (!parser_sy_pop(parser, &sy)) + goto onerr; + } + } + else if (parser->tok != TOKEN_OPERATOR) { parseerror(parser, "expected operator or end of statement"); goto onerr; - } else { + } + else { /* classify the operator */ /* TODO: suffix operators */ const oper_info *op; @@ -439,7 +491,7 @@ static ast_expression* parser_expression(parser_t *parser) /* found an operator */ op = &operators[o]; - if (sy.ops_count) + if (sy.ops_count && !sy.ops[sy.ops_count-1].paren) olast = &operators[sy.ops[sy.ops_count-1].etype-1]; while (olast && ( @@ -448,7 +500,8 @@ static ast_expression* parser_expression(parser_t *parser) { if (!parser_sy_pop(parser, &sy)) goto onerr; - olast = sy.ops_count ? (&operators[sy.ops[sy.ops_count-1].etype-1]) : NULL; + if (sy.ops_count && !sy.ops[sy.ops_count-1].paren) + olast = &operators[sy.ops[sy.ops_count-1].etype-1]; } if (!shunt_ops_add(&sy, syop(parser_ctx(parser), op)))