about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-02-21 22:45:45 -0800
committerKartik K. Agaram <vc@akkartik.com>2021-02-21 22:49:39 -0800
commit588d6df6511cc489191d5f63ce15bd40532b96c0 (patch)
tree4b1eb86949e8dfe82182d023faa3730f366a70ea
parente3f7765cb791c45513c67aadc0abc4865831b1c5 (diff)
downloadmu-588d6df6511cc489191d5f63ce15bd40532b96c0.tar.gz
7781 - baremetal/shell: tokenize numbers
We've now reached a point where we need to start thinking of error handling,
and tests for error handling. The top-level has `stop`, but that's really
just for working with Unix's exit(). Here we have the opportunity to bake
errors into the trace. Which might also be a good opportunity for fleshing
out the UX for the trace.
-rw-r--r--baremetal/shell/read.mu93
1 files changed, 93 insertions, 0 deletions
diff --git a/baremetal/shell/read.mu b/baremetal/shell/read.mu
index 81dd6f07..d6325c62 100644
--- a/baremetal/shell/read.mu
+++ b/baremetal/shell/read.mu
@@ -22,16 +22,109 @@ fn read-cell in: (addr gap-buffer), out: (addr handle cell) {
 fn next-token in: (addr gap-buffer), out: (addr stream byte) {
   clear-stream out
   skip-whitespace-from-gap-buffer in
+  var g/eax: grapheme <- peek-from-gap-buffer in
+  {
+    var digit?/eax: boolean <- is-decimal-digit? g
+    compare digit?, 0/false
+    break-if-=
+    next-number-token in, out
+    return
+  }
+  next-symbol-token in, out
+}
+
+fn next-symbol-token in: (addr gap-buffer), out: (addr stream byte) {
   {
     var done?/eax: boolean <- gap-buffer-scan-done? in
     compare done?, 0/false
     break-if-!=
+    var g/eax: grapheme <- peek-from-gap-buffer in
+    # if non-symbol, return
+    var symbol-grapheme?/eax: boolean <- is-symbol-grapheme? g
+    {
+      compare symbol-grapheme?, 0/false
+      break-if-!=
+      return
+    }
     var g/eax: grapheme <- read-from-gap-buffer in
     write-grapheme out, g
     loop
   }
 }
 
+fn is-symbol-grapheme? g: grapheme -> _/eax: boolean {
+  compare g, 0x20/space
+  {
+    break-if-!=
+    return 0/false
+  }
+  compare g, 0xa/newline
+  {
+    break-if-!=
+    return 0/false
+  }
+  compare g, 0x22/double-quote
+  {
+    break-if-!=
+    return 0/false
+  }
+  compare g, 0x28/open-paren
+  {
+    break-if-!=
+    return 0/false
+  }
+  compare g, 0x29/close-paren
+  {
+    break-if-!=
+    return 0/false
+  }
+  compare g, 0x5b/open-square-bracket
+  {
+    break-if-!=
+    return 0/false
+  }
+  compare g, 0x5d/close-square-bracket
+  {
+    break-if-!=
+    return 0/false
+  }
+  compare g, 0x7b/open-curly-bracket
+  {
+    break-if-!=
+    return 0/false
+  }
+  compare g, 0x7d/close-curly-bracket
+  {
+    break-if-!=
+    return 0/false
+  }
+  return 1/true
+}
+
+fn next-number-token in: (addr gap-buffer), out: (addr stream byte) {
+  var done?/eax: boolean <- gap-buffer-scan-done? in
+  compare done?, 0/false
+  break-if-!=
+  var g/eax: grapheme <- peek-from-gap-buffer in
+  # if not symbol grapheme, return
+  {
+    var symbol-grapheme?/eax: boolean <- is-symbol-grapheme? g
+    compare symbol-grapheme?, 0/false
+    break-if-!=
+    return
+  }
+  # if not digit grapheme, abort
+  {
+    var digit?/eax: boolean <- is-decimal-digit? g
+    compare digit?, 0/false
+    break-if-!=
+    abort "invalid number"
+  }
+  var g/eax: grapheme <- read-from-gap-buffer in
+  write-grapheme out, g
+  loop
+}
+
 fn read-symbol in: (addr stream byte), _out: (addr handle cell) {
   var out/eax: (addr handle cell) <- copy _out
   new-symbol out