branch: elpa/parseclj
commit 0d157d759b101aa13bcf9cff990d7ad9da10462b
Merge: e6bce85062 1bb3800f8f
Author: Arne Brasseur <[email protected]>
Commit: Arne Brasseur <[email protected]>
Merge branch 'master' into shebang-and-symbolic-values
---
.dir-locals.el | 1 +
CHANGELOG.md | 10 ++++++---
parseclj-parser.el | 62 +++++++++++++++++++++++++++++----------------------
test/parseclj-test.el | 30 ++++++++++++++++++++++++-
4 files changed, 72 insertions(+), 31 deletions(-)
diff --git a/.dir-locals.el b/.dir-locals.el
index ab85ded9a1..c45357d77a 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -1,5 +1,6 @@
((emacs-lisp-mode
(buffer-save-without-query . t)
+ (indent-tabs-mode . nil)
(eval . (flycheck-mode))
(eval . (checkdoc-minor-mode))
(sentence-end-double-space . t)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bfb96a20bf..7db45508be 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,11 +1,15 @@
# Unreleased
-## Added
-
- Added a `:read-one` option to read/parse a single form at a time
- Support more reader dispatch macro forms: eval (`#=`), shebang (`#!`),
symbolic value (`##NaN`)
-# 0.1.0 (2018-05-27)
+## Added
+
+## 0.2.0 (2020-10-12)
+
+- raise error on unmatched closing paren/brace
+
+## 0.1.0 (2018-05-27)
Initial release.
diff --git a/parseclj-parser.el b/parseclj-parser.el
index d0e5d24a21..fe3bb3c818 100644
--- a/parseclj-parser.el
+++ b/parseclj-parser.el
@@ -73,34 +73,42 @@ available options."
(let ((opening-token-type (parseclj--find-opening-token stack closing-token))
(fail-fast (a-get options :fail-fast t))
(collection nil))
-
- ;; unwind the stack until opening-token-type is found, adding to collection
- (while (and stack (not (eq (parseclj-lex-token-type (car stack))
opening-token-type)))
- (push (pop stack) collection))
-
- ;; did we find the right token?
- (if (eq (parseclj-lex-token-type (car stack)) opening-token-type)
- (progn
- (when fail-fast
- ;; any unreduced tokens left: bail early
- (when-let ((token (seq-find #'parseclj-lex-token-p collection)))
+ (if (not opening-token-type)
+ (if fail-fast
+ (parseclj--error "At position %s, unmatched %S"
+ (a-get closing-token :pos)
+ (parseclj-lex-token-type closing-token))
+
+ stack)
+
+ (progn
+ ;; unwind the stack until opening-token-type is found, adding to
collection
+ (while (and stack (not (eq (parseclj-lex-token-type (car stack))
opening-token-type)))
+ (push (pop stack) collection))
+
+ ;; did we find the right token?
+ (if (eq (parseclj-lex-token-type (car stack)) opening-token-type)
+ (progn
+ (when fail-fast
+ ;; any unreduced tokens left: bail early
+ (when-let ((token (seq-find #'parseclj-lex-token-p
collection)))
+ (parseclj--error "At position %s, unmatched %S"
+ (a-get token :pos)
+ (parseclj-lex-token-type token))))
+
+ ;; all good, call the reducer so it can return an updated stack
with a
+ ;; new node at the top.
+ (let ((opening-token (pop stack)))
+ (funcall reduce-branch stack opening-token collection
options)))
+
+ ;; Unwound the stack without finding a matching paren: either bail
early
+ ;; or return the original stack and continue parsing
+ (if fail-fast
(parseclj--error "At position %s, unmatched %S"
- (a-get token :pos)
- (parseclj-lex-token-type token))))
-
- ;; all good, call the reducer so it can return an updated stack with
a
- ;; new node at the top.
- (let ((opening-token (pop stack)))
- (funcall reduce-branch stack opening-token collection options)))
-
- ;; Unwound the stack without finding a matching paren: either bail early
- ;; or return the original stack and continue parsing
- (if fail-fast
- (parseclj--error "At position %s, unmatched %S"
- (a-get closing-token :pos)
- (parseclj-lex-token-type closing-token))
-
- (reverse collection)))))
+ (a-get closing-token :pos)
+ (parseclj-lex-token-type closing-token))
+
+ (reverse collection)))))))
(defun parseclj--take-value (stack value-p)
"Scan STACK until a value is found.
diff --git a/test/parseclj-test.el b/test/parseclj-test.el
index ad424030be..3c4d690489 100644
--- a/test/parseclj-test.el
+++ b/test/parseclj-test.el
@@ -93,7 +93,20 @@
(condition-case errdata
(parseclj-parse-clojure "(1 [2 {3 ( 4}])")
(parseclj-parser-error (cadr errdata)))
- "At position 10, unmatched :lparen")))
+ "At position 10, unmatched :lparen"))
+
+ (should (equal
+ (condition-case errdata
+ (parseclj-parse-clojure "{:a 1}}")
+ (parseclj-parser-error (cadr errdata)))
+ "At position 7, unmatched :rbrace"))
+
+ (should (equal
+ (condition-case errdata
+ (parseclj-parse-clojure "'(1))")
+ (parseclj-parser-error (cadr errdata)))
+ "At position 5, unmatched :rparen"))
+ )
(ert-deftest parseclj-parse-clojure-not-fail-fast-test ()
(should (equal (parseclj-parse-clojure "(1 [2 {3 ( 4}])" :fail-fast nil)
@@ -117,6 +130,21 @@
((:token-type . :lparen) (:form . "(") (:pos . 10))
((:node-type
. :number) (:position . 12) (:form . "4") (:value . 4))))))))))))
+ (should (equal
+ (parseclj-parse-clojure "{:a 1}}" :fail-fast nil)
+ '((:node-type . :root)
+ (:position . 1)
+ (:children ((:node-type . :map)
+ (:position . 1)
+ (:children ((:node-type . :keyword)
+ (:position . 2)
+ (:form . ":a")
+ (:value . :a))
+ ((:node-type . :number)
+ (:position . 5)
+ (:form . "1")
+ (:value . 1))))))))
+
;; TODO: uneven map forms
)