branch: elpa/parseclj
commit f34b8460a8467b1923510982ac759ac4f599c06d
Author: Arne Brasseur <[email protected]>
Commit: Arne Brasseur <[email protected]>
Correctly parse numbers in scientific notation
---
DESIGN.md | 15 +++++++++
clj-lex.el | 34 ++++++++++++++++---
tests/edn-el-test-suite.el | 82 ++++++++++++++++++++++++----------------------
3 files changed, 86 insertions(+), 45 deletions(-)
diff --git a/DESIGN.md b/DESIGN.md
index 65d22ae503..064618274e 100644
--- a/DESIGN.md
+++ b/DESIGN.md
@@ -231,6 +231,21 @@ The EDN parser functions will take an optional tag handler
function. This functi
When parsing code to an AST the situation is different, here tags simply
become part of the AST, without caring about their semantics.
+## Representing EDN as Emacs Lisp values
+
+See also the section at the top regarding differences between Clojure's data
types vs those available in Emacs Lisp.
+
+These are the choices that the edn.el library has made:
+
+- represent sets as `'(edn-set (... set values ...))`
+- parse maps as hash tables
+- represent characters as integers, *but* parse `\newline` `\return` `\space`
and `\tab` as the symbols `'newline` `'return` etc.
+- parse `true` as `t`, `nil` and `false` as `nil`.
+
+### Differences with EDN.el
+
+At the moment the `clj-parse-edn-*` copy the parsing behavior of edn.el,
*except* that the character literals `\newline`, `\return`, `\space`, and
`\tab` are parsed to their character code (10, 13, 32, and 9 respectively),
instead of to symbols.
+
## AST
An AST (abstract syntax tree) is a tree structure made up of nodes. A node
looks like this
diff --git a/clj-lex.el b/clj-lex.el
index 66f307deef..c5570331a6 100644
--- a/clj-lex.el
+++ b/clj-lex.el
@@ -59,14 +59,38 @@
(buffer-substring-no-properties pos (point))
pos)))
+(defun clj-lex-skip-digits ()
+ (while (and (char-after (point))
+ (<= ?0 (char-after (point)))
+ (<= (char-after (point)) ?9))
+ (right-char)))
+
+(defun clj-lex-skip-number ()
+ ;; [\+\-]?\d+\.\d+
+ (when (member (char-after (point)) '(?+ ?-))
+ (right-char))
+
+ (clj-lex-skip-digits)
+
+ (when (eq (char-after (point)) ?.)
+ (right-char))
+
+ (clj-lex-skip-digits))
+
(defun clj-lex-number ()
(let ((pos (point)))
- (while (and (char-after (point))
- (or (and (<= ?0 (char-after (point))) (<= (char-after (point))
?9))
- (eq (char-after (point)) ?.)
- (eq (char-after (point)) ?M)
- (eq (char-after (point)) ?r)))
+ (clj-lex-skip-number)
+
+ ;; 10110r2 or 4.3e+22
+ (when (member (char-after (point)) '(?E ?e ?r))
(right-char))
+
+ (clj-lex-skip-number)
+
+ ;; trailing M
+ (when (eq (char-after (point)) ?M)
+ (right-char))
+
(clj-lex-token :number
(buffer-substring-no-properties pos (point))
pos)))
diff --git a/tests/edn-el-test-suite.el b/tests/edn-el-test-suite.el
index 7e11b695df..7a2387b021 100644
--- a/tests/edn-el-test-suite.el
+++ b/tests/edn-el-test-suite.el
@@ -79,46 +79,48 @@
(should (equal :\#/:a (clj-parse-edn-str ":#/:a")))
(should (equal :\#foo (clj-parse-edn-str ":#foo"))))
-;; (ert-deftest integers ()
-;; :tags '(edn integers)
-;; (should (= 0 (clj-parse-edn-str "0")))
-;; (should (= 0 (clj-parse-edn-str "+0")))
-;; (should (= 0 (clj-parse-edn-str "-0")))
-;; (should (= 100 (clj-parse-edn-str "100")))
-;; (should (= -100 (clj-parse-edn-str "-100"))))
-
-;; (ert-deftest floats ()
-;; :tags '(edn floats)
-;; (should (= 12.32 (clj-parse-edn-str "12.32")))
-;; (should (= -12.32 (clj-parse-edn-str "-12.32")))
-;; (should (= 9923.23 (clj-parse-edn-str "+9923.23")))
-;; (should (= 4.5e+044 (clj-parse-edn-str "45e+43")))
-;; (should (= -4.5e-042 (clj-parse-edn-str "-45e-43")))
-;; (should (= 4.5e+044 (clj-parse-edn-str "45E+43"))))
-
-;; (ert-deftest lists ()
-;; :tags '(edn lists)
-;; (should-not (clj-parse-edn-str "()"))
-;; (should (equal '(1 2 3) (clj-parse-edn-str "( 1 2 3)")))
-;; (should (equal '(12.1 ?a foo :bar) (clj-parse-edn-str "(12.1 \\a foo
:bar)")))
-;; (should (equal '((:foo bar :bar 12)) (clj-parse-edn-str "( (:foo bar :bar
12))")))
-;; (should (equal
-;; '(defproject com\.thortech/data\.edn "0.1.0-SNAPSHOT")
-;; (clj-parse-edn-str "(defproject com.thortech/data.edn
\"0.1.0-SNAPSHOT\")"))))
-
-;; (ert-deftest vectors ()
-;; :tags '(edn vectors)
-;; (should (equal [] (clj-parse-edn-str "[]")))
-;; (should (equal [] (clj-parse-edn-str "[ ]")))
-;; (should (equal '[1 2 3] (clj-parse-edn-str "[ 1 2 3 ]")))
-;; (should (equal '[12.1 ?a foo :bar] (clj-parse-edn-str "[ 12.1 \\a foo
:bar]")))
-;; (should (equal '[[:foo bar :bar 12]] (clj-parse-edn-str "[[:foo bar :bar
12]]")))
-;; (should (equal '[( :foo bar :bar 12 ) "foo"]
-;; (clj-parse-edn-str "[(:foo bar :bar 12) \"foo\"]")))
-;; (should (equal '[/ \. * ! _ \? $ % & = - +]
-;; (clj-parse-edn-str "[/ . * ! _ ? $ % & = - +]")))
-;; (should (equal [99 newline return space tab]
-;; (clj-parse-edn-str "[\\c \\newline \\return \\space
\\tab]"))))
+(ert-deftest integers ()
+ :tags '(edn integers)
+ (should (= 0 (clj-parse-edn-str "0")))
+ (should (= 0 (clj-parse-edn-str "+0")))
+ (should (= 0 (clj-parse-edn-str "-0")))
+ (should (= 100 (clj-parse-edn-str "100")))
+ (should (= -100 (clj-parse-edn-str "-100"))))
+
+(ert-deftest floats ()
+ :tags '(edn floats)
+ (should (= 12.32 (clj-parse-edn-str "12.32")))
+ (should (= -12.32 (clj-parse-edn-str "-12.32")))
+ (should (= 9923.23 (clj-parse-edn-str "+9923.23")))
+ (should (= 4.5e+044 (clj-parse-edn-str "45e+43")))
+ (should (= -4.5e-042 (clj-parse-edn-str "-45e-43")))
+ (should (= 4.5e+044 (clj-parse-edn-str "45E+43"))))
+
+(ert-deftest lists ()
+ :tags '(edn lists)
+ (should-not (clj-parse-edn-str "()"))
+ (should (equal '(1 2 3) (clj-parse-edn-str "( 1 2 3)")))
+ (should (equal '(12.1 ?a foo :bar) (clj-parse-edn-str "(12.1 \\a foo
:bar)")))
+ (should (equal '((:foo bar :bar 12)) (clj-parse-edn-str "( (:foo bar :bar
12))")))
+ (should (equal
+ '(defproject com\.thortech/data\.edn "0.1.0-SNAPSHOT")
+ (clj-parse-edn-str "(defproject com.thortech/data.edn
\"0.1.0-SNAPSHOT\")"))))
+
+(ert-deftest vectors ()
+ :tags '(edn vectors)
+ (should (equal [] (clj-parse-edn-str "[]")))
+ (should (equal [] (clj-parse-edn-str "[ ]")))
+ (should (equal '[1 2 3] (clj-parse-edn-str "[ 1 2 3 ]")))
+ (should (equal '[12.1 ?a foo :bar] (clj-parse-edn-str "[ 12.1 \\a foo
:bar]")))
+ (should (equal '[[:foo bar :bar 12]] (clj-parse-edn-str "[[:foo bar :bar
12]]")))
+ (should (equal '[( :foo bar :bar 12 ) "foo"]
+ (clj-parse-edn-str "[(:foo bar :bar 12) \"foo\"]")))
+ (should (equal '[/ \. * ! _ \? $ % & = - +]
+ (clj-parse-edn-str "[/ . * ! _ ? $ % & = - +]")))
+ (should (equal
+ ;;[99 newline return space tab]
+ [99 10 13 32 9]
+ (clj-parse-edn-str "[\\c \\newline \\return \\space \\tab]"))))
(defun map-equal (m1 m2)
(and (and (hash-table-p m1) (hash-table-p m2))