]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
-std=gmqcc way to handle fields by 'namespace'
authorWolfgang (Blub) Bumiller <blub@speed.at>
Sun, 12 Aug 2012 17:24:08 +0000 (19:24 +0200)
committerWolfgang (Blub) Bumiller <blub@speed.at>
Sun, 12 Aug 2012 17:24:08 +0000 (19:24 +0200)
parser.c

index 8c4d0358b561e72c99d5fe3f83f84ab32b2ccd8c..486c32794919dd4fdf5aefb49ada8fa64c3b147f 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -25,6 +25,12 @@ typedef struct {
     size_t blocklocal;
 
     size_t errors;
+
+    /* TYPE_FIELD -> parser_find_fields is used instead of find_var
+     * TODO: TYPE_VECTOR -> x, y and z are accepted in the gmqcc standard
+     * anything else: type error
+     */
+    qcint  memberof;
 } parser_t;
 
 MEM_VEC_FUNCTIONS(parser_t, varentry_t, globals)
@@ -583,6 +589,7 @@ static ast_expression* parser_expression(parser_t *parser)
     ast_expression *expr = NULL;
     shunt sy;
     bool wantop = false;
+    bool gotmemberof = false;
 
     /* count the parens because an if starts with one, so the
      * end of a condition is an unmatched closing paren
@@ -594,16 +601,37 @@ static ast_expression* parser_expression(parser_t *parser)
 
     while (true)
     {
+        if (gotmemberof)
+            gotmemberof = false;
+        else
+            parser->memberof = 0;
         if (!wantop)
         {
             bool nextwant = true;
             if (parser->tok == TOKEN_IDENT)
             {
                 /* variable */
-                ast_expression *var = parser_find_var(parser, parser_tokval(parser));
-                /* in the gmqcc standard, fields are in their own namespace */
-                if (!var && opts_standard != COMPILER_GMQCC)
-                    var = parser_find_field(parser, parser_tokval(parser));
+                ast_expression *var;
+                if (opts_standard == COMPILER_GMQCC)
+                {
+                    if (parser->memberof == TYPE_FIELD)
+                        var = parser_find_field(parser, parser_tokval(parser));
+                    else if (parser->memberof == TYPE_VECTOR)
+                    {
+                        parseerror(parser, "TODO: implement effective vector member access");
+                        goto onerr;
+                    }
+                    else if (parser->memberof) {
+                        parseerror(parser, "namespace for member not found");
+                        goto onerr;
+                    }
+                    else
+                        var = parser_find_var(parser, parser_tokval(parser));
+                } else {
+                    var = parser_find_var(parser, parser_tokval(parser));
+                    if (!var)
+                        var = parser_find_field(parser, parser_tokval(parser));
+                }
                 if (!var) {
                     parseerror(parser, "unexpected ident: %s", parser_tokval(parser));
                     goto onerr;
@@ -714,6 +742,23 @@ static ast_expression* parser_expression(parser_t *parser)
                 }
                 /* found an operator */
                 op = &operators[o];
+                if (op->id == opid1('.')) {
+                    /* for gmqcc standard: open up the namespace of the previous type */
+                    ast_expression *prevex = sy.out[sy.out_count-1].out;
+                    if (!prevex) {
+                        parseerror(parser, "unexpected member operator");
+                        goto onerr;
+                    }
+                    if (prevex->expression.vtype == TYPE_ENTITY)
+                        parser->memberof = TYPE_FIELD;
+                    else if (prevex->expression.vtype == TYPE_VECTOR)
+                        parser->memberof = TYPE_VECTOR;
+                    else {
+                        parseerror(parser, "type error: type has no members");
+                        goto onerr;
+                    }
+                    gotmemberof = true;
+                }
 
                 if (sy.ops_count && !sy.ops[sy.ops_count-1].paren)
                     olast = &operators[sy.ops[sy.ops_count-1].etype-1];