]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - parser.c
ast_label, and labels later used for goto
[xonotic/gmqcc.git] / parser.c
index 752d62a2ad3c5358e119facce38d7aa5c6ca2a69..1d752c409688c4f1270aa7a7cc1c3cd0b6832254 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -2253,8 +2253,11 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression *
     }
     else if (parser->tok == TOKEN_KEYWORD)
     {
-        if (!strcmp(parser_tokval(parser), "local"))
+        if (!strcmp(parser_tokval(parser), "local") ||
+            !strcmp(parser_tokval(parser), "const"))
         {
+            int cvq = parser_tokval(parser)[0] == 'c' ? CV_CONST : CV_VAR;
+
             if (!block) {
                 parseerror(parser, "cannot declare a local variable here");
                 return false;
@@ -2263,7 +2266,7 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression *
                 parseerror(parser, "expected variable declaration");
                 return false;
             }
-            if (!parse_variable(parser, block, true, CV_VAR, NULL))
+            if (!parse_variable(parser, block, true, cvq, NULL))
                 return false;
             *out = NULL;
             return true;
@@ -2333,6 +2336,27 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression *
         *out = (ast_expression*)inner;
         return true;
     }
+    else if (parser->tok == ':')
+    {
+        ast_label *label;
+        if (!parser_next(parser)) {
+            parseerror(parser, "expected label name");
+            return false;
+        }
+        if (parser->tok != TOKEN_IDENT) {
+            parseerror(parser, "label must be an identifier");
+            return false;
+        }
+        label = ast_label_new(parser_ctx(parser), parser_tokval(parser));
+        if (!label)
+            return false;
+        *out = (ast_expression*)label;
+        if (!parser_next(parser)) {
+            parseerror(parser, "parse error after label");
+            return false;
+        }
+        return true;
+    }
     else if (parser->tok == ';')
     {
         if (!parser_next(parser)) {
@@ -3876,7 +3900,10 @@ skipvar:
                     ast_unref(cval);
                 }
             } else {
+                bool cvq;
                 shunt sy = { NULL, NULL };
+                cvq = var->constant;
+                var->constant = false;
                 vec_push(sy.out, syexp(ast_ctx(var), (ast_expression*)var));
                 vec_push(sy.out, syexp(ast_ctx(cexp), (ast_expression*)cexp));
                 vec_push(sy.ops, syop(ast_ctx(var), parser->assign_op));
@@ -3889,6 +3916,7 @@ skipvar:
                 }
                 vec_free(sy.out);
                 vec_free(sy.ops);
+                var->constant = cvq;
             }
         }