about summary refs log tree commit diff stats
path: root/apps/arith.mu
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-06-15 23:33:13 -0700
committerKartik Agaram <vc@akkartik.com>2020-06-15 23:33:13 -0700
commit743a99e83bf0df13d45157a4da91fa1a9d405ca5 (patch)
treee0c03dd071c4cbc460921cdb88eea2a20d746016 /apps/arith.mu
parent076f837af60371aa3b7b11ebb2a9613cd93c8bb0 (diff)
downloadmu-743a99e83bf0df13d45157a4da91fa1a9d405ca5.tar.gz
6542 - arith: brackets
Ok, I think I'm done with this app for now.
Diffstat (limited to 'apps/arith.mu')
-rw-r--r--apps/arith.mu53
1 files changed, 47 insertions, 6 deletions
diff --git a/apps/arith.mu b/apps/arith.mu
index 53566ed5..0c735e66 100644
--- a/apps/arith.mu
+++ b/apps/arith.mu
@@ -23,8 +23,13 @@ fn simplify -> result/eax: int, look/esi: byte {
   # prime the pump
   look <- get-char  # prime the pump
   look <- skip-spaces look
+  result, look <- expression look
+}
+
+fn expression _look: byte -> result/eax: int, look/esi: byte {
+  look <- copy _look  # should be a no-op
   result, look <- term look
-  $simplify:loop: {
+  $expression:loop: {
     # operator
     var op/ecx: byte <- copy 0
     look <- skip-spaces look
@@ -32,6 +37,11 @@ fn simplify -> result/eax: int, look/esi: byte {
     break-if-=
     compare look, 0xa
     break-if-=
+    {
+      var continue?/eax: boolean <- is-add-or-sub? look
+      compare continue?, 0  # false
+      break-if-= $expression:loop
+    }
     op, look <- operator look
     # second arg
     var second/edx: int <- copy 0
@@ -42,18 +52,18 @@ fn simplify -> result/eax: int, look/esi: byte {
       second <- copy tmp
     }
     # perform op
-    $simplify:perform-op: {
+    $expression:perform-op: {
       {
         compare op, 0x2b  # '+'
         break-if-!=
         result <- add second
-        break $simplify:perform-op
+        break $expression:perform-op
       }
       {
         compare op, 0x2d  # '-'
         break-if-!=
         result <- subtract second
-        break $simplify:perform-op
+        break $expression:perform-op
       }
     }
     loop
@@ -107,14 +117,27 @@ fn term _look: byte -> result/eax: int, look/esi: byte {
 }
 
 fn factor _look: byte -> result/eax: int, look/esi: byte {
+$factor:body: {
   look <- copy _look  # should be a no-op
   look <- skip-spaces look
-  result, look <- num look
+  # if next char is not '(' just parse a number
+  compare look, 0x28  # '('
+  {
+    break-if-=
+    result, look <- num look
+    break $factor:body
+  }
+  # otherwise recurse
+  look <- get-char look  # '('
+  result, look <- expression look
+  look <- skip-spaces look
+  look <- get-char look  # ')'
+}  # $factor:body
 }
 
 fn is-mul-or-div? c: byte -> result/eax: bool {
 $is-mul-or-div?:body: {
-  compare c, 0x2a
+  compare c, 0x2a  # '*'
   {
     break-if-!=
     result <- copy 1  # true
@@ -124,6 +147,24 @@ $is-mul-or-div?:body: {
 }  # $is-mul-or-div?:body
 }
 
+fn is-add-or-sub? c: byte -> result/eax: bool {
+$is-add-or-sub?:body: {
+  compare c, 0x2b  # '+'
+  {
+    break-if-!=
+    result <- copy 1  # true
+    break $is-add-or-sub?:body
+  }
+  compare c, 0x2d  # '-'
+  {
+    break-if-!=
+    result <- copy 1  # true
+    break $is-add-or-sub?:body
+  }
+  result <- copy 0  # false
+}  # $is-add-or-sub?:body
+}
+
 fn operator _look: byte -> op/ecx: byte, look/esi: byte {
   op <- copy _look
   look <- get-char