emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/parseedn e70ca8d03a 2/3: Merge pull request #11 from r0man


From: ELPA Syncer
Subject: [nongnu] elpa/parseedn e70ca8d03a 2/3: Merge pull request #11 from r0man/default-data-reader
Date: Mon, 7 Feb 2022 08:58:46 -0500 (EST)

branch: elpa/parseedn
commit e70ca8d03a314f97e4f49b7d6098fa565742e217
Merge: e5ba280d1f c94ac06b53
Author: Arne Brasseur <arne@arnebrasseur.net>
Commit: GitHub <noreply@github.com>

    Merge pull request #11 from r0man/default-data-reader
    
    Default data reader function and tagged literals
---
 parseedn.el                | 32 ++++++++++++++++++++++++++++----
 test/parseedn-test-data.el |  9 +++++++++
 test/parseedn-test.el      | 19 ++++++++++++++++++-
 3 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/parseedn.el b/parseedn.el
index a1cecbf99c..239f56a60c 100644
--- a/parseedn.el
+++ b/parseedn.el
@@ -65,6 +65,23 @@ is not recommended you change this variable, as this globally
 changes the behavior of the EDN reader.  Instead pass your own
 handlers as an optional argument to the reader functions.")
 
+(defun parseedn-tagged-literal (tag form)
+  "Construct a data representation of a tagged literal from TAG and FORM."
+  (list 'edn-tagged-literal tag form))
+
+(defvar parseedn-default-data-reader-fn nil
+  "The default tagged literal reader function.
+
+When no data reader is found for a tag and
+`parseedn-default-data-reader-fn' is non-nil, it will be called
+with two arguments, the tag and the value.  If
+`parseedn-default-data-reader-fn' is nil (the default), an
+exception will be thrown for the unknown tag.
+
+The default data reader can also be provided via the tagged
+reader options registered under the :default keyword when calling
+the reader functions.")
+
 (defun parseedn-reduce-leaf (stack token _options)
   "Put in the STACK an elisp value representing TOKEN.
 
@@ -101,10 +118,14 @@ on available options."
                                            kvs)
                                    hash-map))
         ((eq :tag token-type) (let* ((tag (intern (substring (alist-get :form 
opening-token) 1)))
-                                     (reader (alist-get tag tag-readers 
:missing)))
-                                (when (eq :missing reader)
-                                  (user-error "No reader for tag #%S in %S" 
tag (map-keys tag-readers)))
-                                (funcall reader (car children)))))
+                                     (reader (alist-get tag tag-readers))
+                                     (default-reader (alist-get :default 
tag-readers parseedn-default-data-reader-fn)))
+                                (cond
+                                 ((functionp reader)
+                                  (funcall reader (car children)))
+                                 ((functionp default-reader)
+                                  (funcall default-reader tag (car children)))
+                                 (t (user-error "No reader for tag #%S in %S" 
tag (map-keys tag-readers)))))))
        stack))))
 
 (defun parseedn-read (&optional tag-readers)
@@ -236,6 +257,9 @@ DATUM can be any Emacs Lisp value."
       (insert "#uuid ") (parseedn-print-seq (cdr datum)))
      ((eq 'edn-inst (car datum))
       (insert "#inst ") (parseedn-print-inst (cdr datum)))
+     ((eq 'edn-tagged-literal (car datum))
+      (insert "#" (symbol-name (cadr datum)) " ")
+      (parseedn-print (caddr datum)))
      (t (insert "(") (parseedn-print-seq datum) (insert ")"))))
 
    (t (error "Don't know how to print: %s" datum))))
diff --git a/test/parseedn-test-data.el b/test/parseedn-test-data.el
index 84da3c89f8..74b791574c 100644
--- a/test/parseedn-test-data.el
+++ b/test/parseedn-test-data.el
@@ -277,7 +277,10 @@
 
        "tag-1"
        (a-list
+        :tags '(:edn-roundtrip)
+        :tag-readers '((:default . parseedn-tagged-literal))
         :source "#foo/bar [1]"
+        :edn '((edn-tagged-literal foo/bar [1]))
         :ast '((:node-type . :root)
                (:position . 1)
                (:children . (((:node-type . :tag)
@@ -292,7 +295,10 @@
 
        "tag-2"
        (a-list
+        :tags '(:edn-roundtrip)
+        :tag-readers '((:default . parseedn-tagged-literal))
         :source "(fn #param :param-name 1)"
+        :edn '((fn (edn-tagged-literal param :param-name) 1))
         :ast '((:node-type . :root)
                (:position . 1)
                (:children . (((:node-type . :list)
@@ -315,6 +321,9 @@
 
        "nested-tags"
        (a-list
+        :tags '(:edn-roundtrip)
+        :tag-readers '((:default . parseedn-tagged-literal))
+        :edn (list (vector `(edn-tagged-literal lazy-error (edn-tagged-literal 
error ,(a-hash-table :cause "Divide by zero")))))
         :source "[#lazy-error #error {:cause \"Divide by zero\"}]"
         :ast '((:node-type . :root)
                (:position . 1)
diff --git a/test/parseedn-test.el b/test/parseedn-test.el
index 0c060b9924..49a3a66b2c 100644
--- a/test/parseedn-test.el
+++ b/test/parseedn-test.el
@@ -43,6 +43,8 @@
   (should (equal (parseedn-print-str '((a . 1) (b . ((c . 3))))) "{a 1, b {c 
3}}"))
   (should (equal (parseedn-print-str '(:a 1 :b 2)) "{:a 1, :b 2}"))
   (should (equal (parseedn-print-str '(:a 1 :b (:c 3))) "{:a 1, :b {:c 3}}"))
+  (should (equal (parseedn-print-str '(edn-tagged-literal unknown "data")) 
"#unknown \"data\""))
+  (should (equal (parseedn-print-str '(edn-tagged-literal unknown 
(edn-tagged-literal unknown "data"))) "#unknown #unknown \"data\""))
   (should (listp (member (parseedn-print-str
                           (let ((ht (make-hash-table)))
                             (puthash :a 1 ht)
@@ -59,6 +61,20 @@
 (ert-deftest parseedn-read-test ()
   (should (equal (parseedn-read-str "true") t)))
 
+(ert-deftest parseedn-tagged-literal-test ()
+  (let ((data "#unknown \"data\"")
+        (expected '(edn-tagged-literal unknown "data")))
+    ;; Default reader can be passed as a function
+    (should (equal expected (parseedn-read-str data `((:default . 
,#'parseedn-tagged-literal)))))
+    ;; Default reader can be passed as a symbol
+    (should (equal expected (parseedn-read-str data '((:default . 
parseedn-tagged-literal)))))
+    ;; Default reader can be bound to a function
+    (let ((parseedn-default-data-reader-fn #'parseedn-tagged-literal))
+      (should (equal expected (parseedn-read-str data))))
+    ;; Default reader can be bound to a symbol
+    (let ((parseedn-default-data-reader-fn 'parseedn-tagged-literal))
+      (should (equal expected (parseedn-read-str data))))))
+
 (defmacro define-parseedn-read-tests ()
   `(progn
      ,@(mapcar
@@ -72,7 +88,8 @@
                      (with-temp-buffer
                        (insert ,(a-get data :source))
                        (goto-char 1)
-                       (should (a-equal (parseedn-read) ',(a-get data 
:edn)))))))))
+                       (should (a-equal (parseedn-read ',(a-get data 
:tag-readers))
+                                        ',(a-get data :edn)))))))))
         parseedn-test-data)))
 
 (defmacro define-parseedn-roundtrip-tests ()



reply via email to

[Prev in Thread] Current Thread [Next in Thread]