about summary refs log tree commit diff stats
path: root/shell/parse.mu
diff options
context:
space:
mode:
Diffstat (limited to 'shell/parse.mu')
-rw-r--r--shell/parse.mu136
1 files changed, 136 insertions, 0 deletions
diff --git a/shell/parse.mu b/shell/parse.mu
new file mode 100644
index 00000000..a0045eb3
--- /dev/null
+++ b/shell/parse.mu
@@ -0,0 +1,136 @@
+fn parse-input tokens: (addr stream cell), out: (addr handle cell), trace: (addr trace) {
+  rewind-stream tokens
+  var empty?/eax: boolean <- stream-empty? tokens
+  compare empty?, 0/false
+  {
+    break-if-=
+    error trace, "nothing to parse"
+    return
+  }
+  var close-paren?/eax: boolean <- parse-sexpression tokens, out, trace
+  {
+    compare close-paren?, 0/false
+    break-if-=
+    error trace, "')' is not a valid expression"
+    return
+  }
+  {
+    var empty?/eax: boolean <- stream-empty? tokens
+    compare empty?, 0/false
+    break-if-!=
+    error trace, "unexpected tokens at end; only type in a single expression at a time"
+  }
+}
+
+# return value: true if close-paren was encountered
+fn parse-sexpression tokens: (addr stream cell), _out: (addr handle cell), trace: (addr trace) -> _/eax: boolean {
+  trace-text trace, "read", "parse"
+  trace-lower trace
+  var curr-token-storage: cell
+  var curr-token/ecx: (addr cell) <- address curr-token-storage
+  var empty?/eax: boolean <- stream-empty? tokens
+  compare empty?, 0/false
+  {
+    break-if-=
+    error trace, "end of stream; never found a balancing ')'"
+    return 1/true
+  }
+  read-from-stream tokens, curr-token
+  $parse-sexpression:type-check: {
+    # not bracket -> parse atom
+    var is-bracket-token?/eax: boolean <- is-bracket-token? curr-token
+    compare is-bracket-token?, 0/false
+    {
+      break-if-!=
+      parse-atom curr-token, _out, trace
+      break $parse-sexpression:type-check
+    }
+    # open paren -> parse list
+    var is-open-paren?/eax: boolean <- is-open-paren-token? curr-token
+    compare is-open-paren?, 0/false
+    {
+      break-if-=
+      var curr/esi: (addr handle cell) <- copy _out
+      $parse-sexpression:list-loop: {
+        allocate-pair curr
+        var curr-addr/eax: (addr cell) <- lookup *curr
+        var left/ecx: (addr handle cell) <- get curr-addr, left
+        {
+          var is-close-paren?/eax: boolean <- parse-sexpression tokens, left, trace
+          compare is-close-paren?, 0/false
+          break-if-!= $parse-sexpression:list-loop
+        }
+        #
+        curr <- get curr-addr, right
+        loop
+      }
+      break $parse-sexpression:type-check
+    }
+    # close paren -> parse list
+    var is-close-paren?/eax: boolean <- is-close-paren-token? curr-token
+    compare is-close-paren?, 0/false
+    {
+      break-if-=
+      trace-higher trace
+      return 1/true
+    }
+    # otherwise abort
+    var stream-storage: (stream byte 0x40)
+    var stream/edx: (addr stream byte) <- address stream-storage
+    write stream, "unexpected token "
+    var curr-token-data-ah/eax: (addr handle stream byte) <- get curr-token, text-data
+    var curr-token-data/eax: (addr stream byte) <- lookup *curr-token-data-ah
+    rewind-stream curr-token-data
+    write-stream stream, curr-token-data
+    trace trace, "error", stream
+  }
+  trace-higher trace
+  return 0/false
+}
+
+fn parse-atom _curr-token: (addr cell), _out: (addr handle cell), trace: (addr trace) {
+  trace-text trace, "read", "parse atom"
+  var curr-token/ecx: (addr cell) <- copy _curr-token
+  var curr-token-data-ah/eax: (addr handle stream byte) <- get curr-token, text-data
+  var _curr-token-data/eax: (addr stream byte) <- lookup *curr-token-data-ah
+  var curr-token-data/esi: (addr stream byte) <- copy _curr-token-data
+  trace trace, "read", curr-token-data
+  # number
+  var is-number-token?/eax: boolean <- is-number-token? curr-token
+  compare is-number-token?, 0/false
+  {
+    break-if-=
+    rewind-stream curr-token-data
+    var _val/eax: int <- parse-decimal-int-from-stream curr-token-data
+    var val/ecx: int <- copy _val
+    var val-float/xmm0: float <- convert val
+    allocate-number _out
+    var out/eax: (addr handle cell) <- copy _out
+    var out-addr/eax: (addr cell) <- lookup *out
+    var dest/edi: (addr float) <- get out-addr, number-data
+    copy-to *dest, val-float
+    {
+      var stream-storage: (stream byte 0x40)
+      var stream/ecx: (addr stream byte) <- address stream-storage
+      write stream, "=> number "
+      print-number out-addr, stream, 0/no-trace
+      trace trace, "read", stream
+    }
+    return
+  }
+  # default: symbol
+  # just copy token data
+  allocate-symbol _out
+  var out/eax: (addr handle cell) <- copy _out
+  var out-addr/eax: (addr cell) <- lookup *out
+  var curr-token-data-ah/ecx: (addr handle stream byte) <- get curr-token, text-data
+  var dest-ah/edx: (addr handle stream byte) <- get out-addr, text-data
+  copy-object curr-token-data-ah, dest-ah
+  {
+    var stream-storage: (stream byte 0x40)
+    var stream/ecx: (addr stream byte) <- address stream-storage
+    write stream, "=> symbol "
+    print-symbol out-addr, stream, 0/no-trace
+    trace trace, "read", stream
+  }
+}