about summary refs log tree commit diff stats
path: root/shell/parse.mu
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-04-15 19:47:01 -0700
committerKartik K. Agaram <vc@akkartik.com>2021-04-15 19:47:01 -0700
commit613b1d5734cf119494ef5921ec86bd6cf5e3e6ea (patch)
tree73f92581c4b272d34cea8862901a58f1dc1c99f8 /shell/parse.mu
parent2e06991834304f953be3c84d29c0083e9ecc286a (diff)
downloadmu-613b1d5734cf119494ef5921ec86bd6cf5e3e6ea.tar.gz
parse dotted lists
Diffstat (limited to 'shell/parse.mu')
-rw-r--r--shell/parse.mu56
1 files changed, 56 insertions, 0 deletions
diff --git a/shell/parse.mu b/shell/parse.mu
index 357b48fb..1fc74214 100644
--- a/shell/parse.mu
+++ b/shell/parse.mu
@@ -57,6 +57,14 @@ fn parse-sexpression tokens: (addr stream cell), _out: (addr handle cell), trace
       close-paren?, dot? <- parse-sexpression tokens, right-ah, trace
       return close-paren?, dot?
     }
+    # dot -> return
+    var dot?/eax: boolean <- dot-token? curr-token
+    compare dot?, 0/false
+    {
+      break-if-=
+      trace-higher trace
+      return 0/false, 1/true
+    }
     # not bracket -> parse atom
     var bracket-token?/eax: boolean <- bracket-token? curr-token
     compare bracket-token?, 0/false
@@ -78,6 +86,12 @@ fn parse-sexpression tokens: (addr stream cell), _out: (addr handle cell), trace
         var close-paren?/eax: boolean <- copy 0/false
         var dot?/ecx: boolean <- copy 0/false
         close-paren?, dot? <- parse-sexpression tokens, left, trace
+        {
+          compare dot?, 0/false
+          break-if-=
+          error trace, "'.' cannot be at the start of a list"
+          return 1/true, dot?
+        }
         compare close-paren?, 0/false
         break-if-!=
         var curr-addr/eax: (addr cell) <- lookup *curr
@@ -88,6 +102,13 @@ fn parse-sexpression tokens: (addr stream cell), _out: (addr handle cell), trace
           var close-paren?/eax: boolean <- copy 0/false
           var dot?/ecx: boolean <- copy 0/false
           close-paren?, dot? <- parse-sexpression tokens, tmp, trace
+          # '.' -> clean up right here and return
+          compare dot?, 0/false
+          {
+            break-if-=
+            parse-dot-tail tokens, curr, trace
+            return 0/false, 0/false
+          }
           allocate-pair curr
           # ')' -> return
           compare close-paren?, 0/false
@@ -170,3 +191,38 @@ fn parse-atom _curr-token: (addr cell), _out: (addr handle cell), trace: (addr t
     trace trace, "read", stream
   }
 }
+
+fn parse-dot-tail tokens: (addr stream cell), _out: (addr handle cell), trace: (addr trace) {
+  var out/edi: (addr handle cell) <- copy _out
+  var close-paren?/eax: boolean <- copy 0/false
+  var dot?/ecx: boolean <- copy 0/false
+  close-paren?, dot? <- parse-sexpression tokens, out, trace
+  compare close-paren?, 0/false
+  {
+    break-if-=
+    error trace, "'. )' makes no sense"
+    return
+  }
+  compare dot?, 0/false
+  {
+    break-if-=
+    error trace, "'. .' makes no sense"
+    return
+  }
+  #
+  var dummy: (handle cell)
+  var dummy-ah/edi: (addr handle cell) <- address dummy
+  close-paren?, dot? <- parse-sexpression tokens, dummy-ah, trace
+  compare close-paren?, 0/false
+  {
+    break-if-!=
+    error trace, "cannot have multiple expressions between '.' and ')'"
+    return
+  }
+  compare dot?, 0/false
+  {
+    break-if-=
+    error trace, "cannot have two dots in a single list"
+    return
+  }
+}