]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
Starting expression parsing
authorWolfgang Bumiller <wolfgang.linux@bumiller.com>
Fri, 20 Jul 2012 12:45:23 +0000 (14:45 +0200)
committerWolfgang Bumiller <wolfgang.linux@bumiller.com>
Fri, 20 Jul 2012 12:45:23 +0000 (14:45 +0200)
lexer.h
parser.c

diff --git a/lexer.h b/lexer.h
index 8ccd2cf261d6a8dcb7d41d316cf0434fafc20a77..8715b652e83ea18edc6aacef560ea6877328efa4 100644 (file)
--- a/lexer.h
+++ b/lexer.h
@@ -183,6 +183,7 @@ static const oper_info operators[] = {
     { "^=",  opid2('^','='),     ASSOC_RIGHT, 2,  0 },
     { "|=",  opid2('|','='),     ASSOC_RIGHT, 2,  0 },
 };
+const size_t operator_count = (sizeof(operators) / sizeof(operators[0]));
 
 typedef struct
 {
index 9a2ba4d22e8e641649f9335202cb6e79f44d99fa..0db29c0c03c13eb5078871c262f2ebdbc9ae37b3 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -200,51 +200,96 @@ static sy_elem syexp(ast_expression *v) {
 }
 static sy_elem syval(ast_value *v) { return syexp((ast_expression*)v); }
 
-static bool parser_expression(parser_t *parser, ast_block *block)
+static ast_expression* parser_expression(parser_t *parser)
 {
+    ast_expression *expr = NULL;
     shynt sy;
+    bool wantop = false;
 
     MEM_VECTOR_INIT(&sy, out);
     MEM_VECTOR_INIT(&sy, ops);
 
-    if (parser->tok == TOKEN_IDENT)
+    while (true)
     {
-        /* variable */
-        ast_value *var = parser_find_var(parser, parser_tokval(parser));
-        if (!var) {
-            parseerror(parser, "unexpected ident: %s", parser_tokval(parser));
-            goto onerr;
-        }
-        if (!shynt_out_add(&sy, syval(var))) {
-            parseerror(parser, "out of memory");
-            goto onerr;
-        }
-    } else if (parser->tok == TOKEN_FLOATCONST) {
-        ast_value *val = parser_const_float(parser, (parser_token(parser)->constval.f));
-        if (!val)
-            return false;
-        if (!shynt_out_add(&sy, syval(val))) {
-            parseerror(parser, "out of memory");
-            goto onerr;
-        }
-    } else if (parser->tok == TOKEN_INTCONST) {
-        ast_value *val = parser_const_float(parser, (double)(parser_token(parser)->constval.i));
-        if (!val)
-            return false;
-        if (!shynt_out_add(&sy, syval(val))) {
-            parseerror(parser, "out of memory");
-            goto onerr;
+        if (!wantop)
+        {
+            if (parser->tok == TOKEN_IDENT)
+            {
+                /* variable */
+                ast_value *var = parser_find_var(parser, parser_tokval(parser));
+                if (!var) {
+                    parseerror(parser, "unexpected ident: %s", parser_tokval(parser));
+                    goto onerr;
+                }
+                if (!shynt_out_add(&sy, syval(var))) {
+                    parseerror(parser, "out of memory");
+                    goto onerr;
+                }
+            } else if (parser->tok == TOKEN_FLOATCONST) {
+                ast_value *val = parser_const_float(parser, (parser_token(parser)->constval.f));
+                if (!val)
+                    return false;
+                if (!shynt_out_add(&sy, syval(val))) {
+                    parseerror(parser, "out of memory");
+                    goto onerr;
+                }
+            } else if (parser->tok == TOKEN_INTCONST) {
+                ast_value *val = parser_const_float(parser, (double)(parser_token(parser)->constval.i));
+                if (!val)
+                    return false;
+                if (!shynt_out_add(&sy, syval(val))) {
+                    parseerror(parser, "out of memory");
+                    goto onerr;
+                }
+            } else {
+                /* TODO: prefix operators */
+                parseerror(parser, "expected statement");
+                goto onerr;
+            }
+            wantop = true;
+            parser->lex->flags.noops = false;
+            if (!parser_next(parser)) {
+                goto onerr;
+            }
+        } else {
+            if (parser->tok != TOKEN_OPERATOR) {
+                parseerror(parser, "expected operator or end of statement");
+                goto onerr;
+            } else {
+                /* classify the operator */
+                /* TODO: suffix operators */
+                size_t o;
+                for (o = 0; o < operator_count; ++o) {
+                    if (!(operators[o].flags & OP_PREFIX) &&
+                        !(operators[o].flags & OP_SUFFIX) && /* remove this */
+                        !strcmp(parser_tokval(parser), operators[o].op))
+                    {
+                        break;
+                    }
+                }
+                if (o == operator_count) {
+                    /* no operator found... must be the end of the statement */
+                    break;
+                }
+            }
+            wantop = false;
+            parser->lex->flags.noops = true;
+            if (!parser_next(parser)) {
+                goto onerr;
+            }
         }
     }
 
+    parser->lex->flags.noops = true;
     MEM_VECTOR_CLEAR(&sy, out);
     MEM_VECTOR_CLEAR(&sy, ops);
-    return true;
+    return expr;
 
 onerr:
+    parser->lex->flags.noops = true;
     MEM_VECTOR_CLEAR(&sy, out);
     MEM_VECTOR_CLEAR(&sy, ops);
-    return false;
+    return NULL;
 }
 
 static bool parser_variable(parser_t *parser, bool global);
@@ -264,7 +309,14 @@ static bool parser_body_do(parser_t *parser, ast_block *block)
         return false;
     }
     else
-        return parser_expression(parser, block);
+    {
+        ast_expression *exp = parser_expression(parser);
+        if (!exp)
+            return false;
+        if (!ast_block_exprs_add(block, exp))
+            return false;
+        return true;
+    }
 }
 
 static ast_block* parser_parse_block(parser_t *parser)