37cd2173940e

Refactor discarding into its own file
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Fri, 14 Aug 2020 22:56:53 -0400
parents 56f93a6f58b4
children 6d9143f80df3
branches/tags (none)
files jarl.asd src/basic.lisp src/discard.lisp

Changes

--- a/jarl.asd	Fri Aug 14 00:40:27 2020 -0400
+++ b/jarl.asd	Fri Aug 14 22:56:53 2020 -0400
@@ -14,6 +14,7 @@
   :components ((:module "src" :serial t
                 :components ((:file "package")
                              (:file "basic")
+                             (:file "discard")
                              (:file "mop")))))
 
 
--- a/src/basic.lisp	Fri Aug 14 00:40:27 2020 -0400
+++ b/src/basic.lisp	Fri Aug 14 22:56:53 2020 -0400
@@ -225,76 +225,6 @@
 (defgeneric read% (class contained-class input))
 
 
-(defmethod read% ((class (eql 'nil)) contained-class input)
-  ;; Optimized reader for cases where you don't actually care about the value
-  ;; and just need to parse over it without allocating anything.
-  (labels
-      ((any% ()
-         (case (p input)
-           (:eof (r input) (e nil input "got ~S" :eof))
-           (#\n (literal% "null"))
-           (#\t (literal% "true"))
-           (#\f (literal% "false"))
-           (#\" (string%))
-           (#\{ (object%))
-           (#\[ (array%))
-           ((#\- #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) (number%))
-           (t (e nil input "unexpected character ~S" (r input)))))
-       (literal% (string)
-         (loop :for next :across string
-               :for char = (r input)
-               :unless (eql next char)
-               :do (e nil input "expected ~S when parsing ~S but got ~S" next string char)))
-       (array% ()
-         (r input) ; [
-         (incf-depth input)
-         (skip-whitespace input)
-         (if (eql (p input) #\])
-           (progn (decf-depth input)
-                  (r input))
-           (loop (any%)
-                 (skip-whitespace input)
-                 (let ((ch (r input)))
-                   (case ch
-                     (#\] (decf-depth input) (return))
-                     (#\, (skip-whitespace input))
-                     (t (e nil input "expected ~S or ~S but got ~S." #\] #\, ch)))))))
-       (object% ()
-         (r input) ; {
-         (incf-depth input)
-         (skip-whitespace input)
-         (if (eql (p input) #\})
-           (progn
-             (decf-depth input)
-             (r input))
-           (loop
-             (string%)
-             (parse-kv-separator nil input)
-             (any%)
-             (skip-whitespace input)
-             (let ((ch (r input)))
-               (case ch
-                 (#\} (decf-depth input) (return))
-                 (#\, (skip-whitespace input))
-                 (t (e nil input "expected ~S or ~S but got ~S" #\} #\, ch)))))))
-       (number% ()
-         ;; TODO: Optimize this too.  Not a huge priority since fixnums don't cons.
-         (parse-number input))
-       (string% ()
-         (let ((ch (r input)))
-           (unless (eql ch #\")
-             (e nil input "expected opening ~S but got ~S" #\" ch)))
-         (loop :for ch = (r input)
-               :do (cond
-                     ((eql ch :eof) (e nil input "got ~S" :eof))
-                     ((eql ch #\\) (parse-escaped-character input)) ; TODO: Optimize this too.
-                     ((eql ch #\") (return))
-                     ((requires-escape-p ch) (e nil input "bad unescaped character ~S" ch))
-                     (t nil)))))
-    (skip-whitespace input)
-    (any%)
-    (values)))
-
 (defmethod read% ((class (eql 'keyword)) contained-class input)
   (let ((ch (r input)))
     (case ch
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/discard.lisp	Fri Aug 14 22:56:53 2020 -0400
@@ -0,0 +1,76 @@
+(in-package :jarl)
+
+;; Optimized reader for cases where you don't actually care about the value and
+;; just need to parse over it without allocating anything.
+
+(defun discard-literal (string input)
+  (loop :for next :across string
+        :for char = (r input)
+        :unless (eql next char)
+        :do (e nil input "expected ~S when parsing ~S but got ~S" next string char)))
+
+(defun discard-array (input)
+  (r input) ; [
+  (incf-depth input)
+  (skip-whitespace input)
+  (if (eql (p input) #\])
+    (progn (decf-depth input)
+           (r input))
+    (loop (discard-any input)
+          (skip-whitespace input)
+          (let ((ch (r input)))
+            (case ch
+              (#\] (decf-depth input) (return))
+              (#\, (skip-whitespace input))
+              (t (e nil input "expected ~S or ~S but got ~S." #\] #\, ch)))))))
+
+(defun discard-object (input)
+  (r input) ; {
+  (incf-depth input)
+  (skip-whitespace input)
+  (if (eql (p input) #\})
+    (progn (decf-depth input)
+           (r input))
+    (loop (discard-string input)
+          (parse-kv-separator nil input)
+          (discard-any input)
+          (skip-whitespace input)
+          (let ((ch (r input)))
+            (case ch
+              (#\} (decf-depth input) (return))
+              (#\, (skip-whitespace input))
+              (t (e nil input "expected ~S or ~S but got ~S" #\} #\, ch)))))))
+
+(defun discard-string (input)
+  (let ((ch (r input)))
+    (unless (eql ch #\")
+      (e nil input "expected opening ~S but got ~S" #\" ch)))
+  (loop :for ch = (r input)
+        :do (cond
+              ((eql ch :eof) (e nil input "got ~S" :eof))
+              ((eql ch #\\) (parse-escaped-character input)) ; TODO: Optimize this too.
+              ((eql ch #\") (return))
+              ((requires-escape-p ch) (e nil input "bad unescaped character ~S" ch))
+              (t nil))))
+
+(defun discard-number (input)
+  ;; TODO: Optimize this too.  Not a huge priority since fixnums don't cons.
+  (parse-number input))
+
+(defun discard-any (input)
+  (case (p input)
+    (:eof (r input) (e nil input "got ~S" :eof))
+    (#\n (discard-literal "null" input))
+    (#\t (discard-literal "true" input))
+    (#\f (discard-literal "false" input))
+    (#\" (discard-string input))
+    (#\{ (discard-object input))
+    (#\[ (discard-array input))
+    ((#\- #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) (discard-number input))
+    (t (e nil input "unexpected character ~S" (r input)))))
+
+
+(defmethod read% ((class (eql 'nil)) contained-class input)
+  (skip-whitespace input)
+  (discard-any input)
+  (values))