|
;;; parseclj.el --- Clojure/EDN parser -*- lexical-binding: t; -*-
|
|
|
|
;; Copyright (C) 2017-2018 Arne Brasseur
|
|
|
|
;; Author: Arne Brasseur <arne@arnebrasseur.net>
|
|
;; Keywords: lisp clojure edn parser
|
|
;; Package-Requires: ((emacs "25") (a "0.1.0alpha4"))
|
|
;; Version: 0.1.0
|
|
|
|
;; This file is not part of GNU Emacs.
|
|
|
|
;; This file is free software; you can redistribute it and/or modify
|
|
;; it under the terms of the GNU General Public License as published by
|
|
;; the Free Software Foundation; either version 3, or (at your option)
|
|
;; any later version.
|
|
|
|
;; This file is distributed in the hope that it will be useful,
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
;; GNU General Public License for more details.
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
;; along with GNU Emacs; see the file COPYING. If not, write to
|
|
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
;; Boston, MA 02110-1301, USA.
|
|
|
|
;;; Commentary:
|
|
|
|
;; Top level API for the Clojure parser.
|
|
|
|
;;; Code:
|
|
|
|
(require 'parseclj-parser)
|
|
(require 'parseclj-ast)
|
|
|
|
(defun parseclj-parse-clojure (&rest string-and-options)
|
|
"Parse Clojure source to AST.
|
|
|
|
Reads either from the current buffer, starting from point, until
|
|
`point-max', or reads from the optional string argument.
|
|
|
|
STRING-AND-OPTIONS can be an optional string, followed by
|
|
key-value pairs to specify parsing options.
|
|
|
|
- `:lexical-preservation' Retain whitespace, comments, and
|
|
discards. Defaults to nil.
|
|
- `:fail-fast' Raise an error when encountering invalid syntax.
|
|
Defaults to t.
|
|
- `:read-one'
|
|
Read a single form. Defaults to false: parse the complete input."
|
|
(if (stringp (car string-and-options))
|
|
(with-temp-buffer
|
|
(insert (car string-and-options))
|
|
(goto-char 1)
|
|
(apply 'parseclj-parse-clojure (cdr string-and-options)))
|
|
(let* ((value-p (lambda (e)
|
|
(and (parseclj-ast-node-p e)
|
|
(not (member (parseclj-ast-node-type e) '(:whitespace :comment :discard))))))
|
|
(options (apply 'a-list :value-p value-p string-and-options))
|
|
(lexical? (a-get options :lexical-preservation)))
|
|
(parseclj-parser (if lexical?
|
|
#'parseclj-ast--reduce-leaf-with-lexical-preservation
|
|
#'parseclj-ast--reduce-leaf)
|
|
(if lexical?
|
|
#'parseclj-ast--reduce-branch-with-lexical-preservation
|
|
#'parseclj-ast--reduce-branch)
|
|
options))))
|
|
|
|
(defun parseclj-unparse-clojure (ast)
|
|
"Parse Clojure AST to source code.
|
|
|
|
Given an abstract syntax tree AST (as returned by
|
|
`parseclj-parse-clojure'), turn it back into source code, and
|
|
insert it into the current buffer."
|
|
(if (parseclj-ast-leaf-node-p ast)
|
|
(insert (a-get ast :form))
|
|
(if (eql (parseclj-ast-node-type ast) :tag)
|
|
(parseclj-ast--unparse-tag ast)
|
|
(parseclj-ast--unparse-collection ast))))
|
|
|
|
(defun parseclj-unparse-clojure-to-string (ast)
|
|
"Parse Clojure AST to a source code string.
|
|
|
|
Given an abstract syntax tree AST (as returned by
|
|
`parseclj-parse-clojure'), turn it back into source code, and
|
|
return it as a string"
|
|
(with-temp-buffer
|
|
(parseclj-unparse-clojure ast)
|
|
(buffer-substring-no-properties (point-min) (point-max))))
|
|
|
|
(provide 'parseclj)
|
|
|
|
;;; parseclj.el ends here
|