diff --git a/parseclj-lex.el b/parseclj-lex.el index 15794c2..42145b1 100644 --- a/parseclj-lex.el +++ b/parseclj-lex.el @@ -163,11 +163,20 @@ S goes through three transformations: ((eq first-char ?o) (string-to-number (substring c 2) 8)) (t first-char)))) +(defun parseclj-lex--number-value (number-str) + "Parse the NUMBER-STR to an Elisp number." + (let ((ratio (split-string number-str "/"))) + (if (= 2 (length ratio)) + (let ((numerator (string-to-number (car ratio))) + (denominator (string-to-number (cadr ratio)))) + (/ numerator (float denominator))) + (string-to-number number-str)))) + (defun parseclj-lex--leaf-token-value (token) "Parse the given leaf TOKEN to an Emacs Lisp value." (let ((token-type (parseclj-lex-token-type token))) (cond - ((eq :number token-type) (string-to-number (alist-get :form token))) + ((eq :number token-type) (parseclj-lex--number-value (alist-get :form token))) ((eq :nil token-type) nil) ((eq :true token-type) t) ((eq :false token-type) nil) @@ -254,6 +263,11 @@ S goes through three transformations: (when (eq (char-after (point)) ?N) (right-char)) + ;; clojure.lang.Ratio + (when (eq (char-after (point)) ?/) + (right-char) + (parseclj-lex-skip-number)) + (let ((char (char-after (point)))) (if (and char (or (and (<= ?a char) (<= char ?z)) (and (<= ?A char) (<= char ?Z)) diff --git a/test/parseclj-lex-test.el b/test/parseclj-lex-test.el index a541b4b..dbf71c3 100644 --- a/test/parseclj-lex-test.el +++ b/test/parseclj-lex-test.el @@ -66,6 +66,13 @@ (:form . "0xff00AA") (:pos . 1))))) + (with-temp-buffer + (insert "12/34") + (goto-char 1) + (should (equal (parseclj-lex-next) '((:token-type . :number) + (:form . "12/34") + (:pos . 1))))) + (with-temp-buffer (insert "#?(:clj 1 :cljs 2)") (goto-char 1) diff --git a/test/parseclj-test-data.el b/test/parseclj-test-data.el index 053fe12..6e6abe4 100644 --- a/test/parseclj-test-data.el +++ b/test/parseclj-test-data.el @@ -211,6 +211,18 @@ (:form . ":foo-bar") (:value . :foo-bar)))))) + "ratio" + (parseclj-alist + :tags '(:edn-roundtrip) + :source "12/34" + :edn '(0.35294117647058826) + :ast '((:node-type . :root) + (:position . 1) + (:children ((:node-type . :number) + (:position . 1) + (:form . "12/34") + (:value . 0.35294117647058826))))) + "vector" (parseclj-alist :tags '(:edn-roundtrip) diff --git a/test/parseclj-unparse-test.el b/test/parseclj-unparse-test.el index dbf3c79..5b984aa 100644 --- a/test/parseclj-unparse-test.el +++ b/test/parseclj-unparse-test.el @@ -130,6 +130,16 @@ (:form . ":foo-bar") (:value . :foo-bar))))))))) +(ert-deftest parseclj-unparse-clojure-ratio () + (should (equal "12/34" + (parseclj-unparse-clojure-to-string + '((:node-type . :root) + (:position . 1) + (:children ((:node-type . :number) + (:position . 1) + (:form . "12/34") + (:value . 0.35294117647058826)))))))) + (ert-deftest parseclj-unparse-clojure-vector () (should (equal "[123]" (parseclj-unparse-clojure-to-string