]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
handling of operations
authorWolfgang Bumiller <wolfgang.linux@bumiller.com>
Fri, 20 Jul 2012 13:02:18 +0000 (15:02 +0200)
committerWolfgang Bumiller <wolfgang.linux@bumiller.com>
Fri, 20 Jul 2012 13:02:18 +0000 (15:02 +0200)
parser.c

index 0db29c0c03c13eb5078871c262f2ebdbc9ae37b3..acbba21ff4f34e0e879d6c0a2d1b9be694da8937 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -181,7 +181,7 @@ static ast_value *parser_parse_type(parser_t *parser, int basetype, bool *isfunc
 
 typedef struct
 {
-    int etype; /* 0 = expression, others are operators */
+    size_t etype; /* 0 = expression, others are operators */
     ast_expression* out;
 } sy_elem;
 typedef struct
@@ -200,6 +200,18 @@ static sy_elem syexp(ast_expression *v) {
 }
 static sy_elem syval(ast_value *v) { return syexp((ast_expression*)v); }
 
+static sy_elem syop(const oper_info *op) {
+    sy_elem e;
+    e.etype = 1 + (op - operators);
+    e.out = NULL;
+    return e;
+}
+
+static bool parser_sy_pop(parser_t *parser, shynt *sy)
+{
+    return true;
+}
+
 static ast_expression* parser_expression(parser_t *parser)
 {
     ast_expression *expr = NULL;
@@ -258,6 +270,8 @@ static ast_expression* parser_expression(parser_t *parser)
             } else {
                 /* classify the operator */
                 /* TODO: suffix operators */
+                const oper_info *op;
+                const oper_info *olast = NULL;
                 size_t o;
                 for (o = 0; o < operator_count; ++o) {
                     if (!(operators[o].flags & OP_PREFIX) &&
@@ -271,6 +285,23 @@ static ast_expression* parser_expression(parser_t *parser)
                     /* no operator found... must be the end of the statement */
                     break;
                 }
+                /* found an operator */
+                op = &operators[o];
+
+                if (sy.ops_count)
+                    olast = &operators[sy.ops[sy.ops_count-1].etype-1];
+
+                while (olast && (
+                        (op->prec < olast->prec) ||
+                        (op->assoc == ASSOC_LEFT && op->prec <= olast->prec) ) )
+                {
+                    if (!parser_sy_pop(parser, &sy))
+                        goto onerr;
+                    olast = sy.ops_count ? (&operators[sy.ops[sy.ops_count-1].etype-1]) : NULL;
+                }
+
+                if (!shynt_ops_add(&sy, syop(op)))
+                    goto onerr;
             }
             wantop = false;
             parser->lex->flags.noops = true;
@@ -280,7 +311,17 @@ static ast_expression* parser_expression(parser_t *parser)
         }
     }
 
+    while (sy.ops_count) {
+        if (!parser_sy_pop(parser, &sy))
+            goto onerr;
+    }
+
     parser->lex->flags.noops = true;
+    if (!sy.out_count) {
+        parseerror(parser, "empty expression");
+        expr = NULL;
+    } else
+        expr = sy.out[0].out;
     MEM_VECTOR_CLEAR(&sy, out);
     MEM_VECTOR_CLEAR(&sy, ops);
     return expr;