Implemented unary expressions
authorLukas Krickl <lukas@krickl.dev>
Mon, 20 Nov 2023 10:59:20 +0000 (11:59 +0100)
committerLukas Krickl <lukas@krickl.dev>
Mon, 20 Nov 2023 10:59:20 +0000 (11:59 +0100)
include/ulas.h
src/test.c
src/ulas.c

index f9305c84104150eeed223ff89603bf0e91e92769..32f8f6edfe81d6710208c97ccf165e62d177717c 100644 (file)
@@ -224,7 +224,7 @@ struct ulas_sym {
 enum ulas_exprs { ULAS_EXPUN, ULAS_EXPBIN, ULAS_EXPPRIM, ULAS_EXPGRP };
 
 struct ulas_expun {
-  long expr;
+  long right;
   long op;
 };
 
index c17b9e85b93cff09cc879e2622ba6d3760e04ec4..ecdd3c23e3024fbb5aa7dd2b05b84b2df3814304 100644 (file)
@@ -257,13 +257,18 @@ void test_intexpr(void) {
 
   ASSERT_INTEXPR(5, 0, "2 + 3");
   ASSERT_INTEXPR(-1, 0, "2 + 3 - 6");
-  
+
   ASSERT_INTEXPR(6, 0, "2 * 3");
   ASSERT_INTEXPR(2, 0, "8 / 4");
   ASSERT_INTEXPR(0, -1, "8 / 0");
   ASSERT_INTEXPR(0, -1, "8 % 0");
   ASSERT_INTEXPR(0, 0, "8 % 4");
 
+  ASSERT_INTEXPR(0, 0, "!1");
+  ASSERT_INTEXPR(-1, 0, "-1");
+  ASSERT_INTEXPR(1, 0, "--1");
+  ASSERT_INTEXPR(2, 0, "1 - -1");
+
   TESTEND("intexpr");
 }
 
index b97499b5b0eaff5d1f0393735943f4925b87915e..1a1cc3a0023f9986b820b688e368245d233ea78f 100644 (file)
@@ -193,7 +193,8 @@ int ulas_tok(struct ulas_str *dst, const char **out_line, unsigned long n) {
       }
       dst->buf[write] = line[i];
       write++;
-      break;
+      i++;
+      goto tokdone;
     default:
       if (isspace(line[i])) {
         goto tokdone;
@@ -1060,7 +1061,22 @@ int ulas_parseprim(int *i) {
 
 int ulas_parsecmp(int *i);
 
-int ulas_parseun(int *i) { return ulas_parseprim(i); }
+int ulas_parseun(int *i) {
+  struct ulas_tok *t = ulas_tokbufget(&ulas.toks, *i);
+
+  if (t && (t->type == '!' || t->type == '-')) {
+    int op = *i;
+    *i += 1;
+    int right = ulas_parseun(i);
+
+    struct ulas_expun un = {right, op};
+    union ulas_expval val = {.un = un};
+    struct ulas_expr e = {ULAS_EXPUN, val, -1};
+    return ulas_exprbufpush(&ulas.exprs, e);
+  }
+
+  return ulas_parseprim(i);
+}
 
 int ulas_parsefact(int *i) {
   int expr = ulas_parseun(i);
@@ -1070,7 +1086,7 @@ int ulas_parsefact(int *i) {
          (t->type == '*' || t->type == '/' || t->type == '%')) {
     int op = *i;
     *i += 1;
-    int right = ulas_parsecmp(i);
+    int right = ulas_parseun(i);
 
     struct ulas_expbin bin = {expr, right, op};
     union ulas_expval val = {.bin = bin};
@@ -1089,7 +1105,7 @@ int ulas_parseterm(int *i) {
          (t->type == '+' || t->type == '-')) {
     int op = *i;
     *i += 1;
-    int right = ulas_parsecmp(i);
+    int right = ulas_parsefact(i);
 
     struct ulas_expbin bin = {expr, right, op};
     union ulas_expval val = {.bin = bin};
@@ -1109,7 +1125,7 @@ int ulas_parsecmp(int *i) {
           t->type == '<')) {
     int op = *i;
     *i += 1;
-    int right = ulas_parsecmp(i);
+    int right = ulas_parseterm(i);
 
     struct ulas_expbin bin = {expr, right, op};
     union ulas_expval val = {.bin = bin};
@@ -1125,7 +1141,6 @@ int ulas_parseeq(int *i) {
   struct ulas_tok *t = NULL;
   while ((t = ulas_tokbufget(&ulas.toks, *i)) &&
          (t->type == ULAS_EQ || t->type == ULAS_NEQ)) {
-
     int op = *i;
     *i += 1;
     int right = ulas_parsecmp(i);
@@ -1216,7 +1231,23 @@ int ulas_intexpreval(int i, int *rc) {
     }
     break;
   }
-  case ULAS_EXPUN:
+  case ULAS_EXPUN: {
+    struct ulas_tok *op = ulas_tokbufget(&ulas.toks, e->val.un.op);
+    if (!op) {
+      ULASPANIC("Unary operator was NULL\n");
+    }
+    int right = ulas_intexpreval(e->val.un.right, rc);
+    switch ((int)op->type) {
+    case '!':
+      return !right;
+    case '-':
+      return -right;
+    default:
+      ULASPANIC("Unhandeled unary operation\n");
+      break;
+    }
+    break;
+  }
   case ULAS_EXPGRP:
     break;
   case ULAS_EXPPRIM: {