dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

parseclj.el (3508B)


      1 ;;; parseclj.el --- Clojure/EDN parser              -*- lexical-binding: t; -*-
      2 
      3 ;; Copyright (C) 2017-2021  Arne Brasseur
      4 
      5 ;; Author: Arne Brasseur <arne@arnebrasseur.net>
      6 ;; Keywords: lisp clojure edn parser
      7 ;; Package-Requires: ((emacs "25"))
      8 ;; Version: 1.1.0
      9 
     10 ;; This file is not part of GNU Emacs.
     11 
     12 ;; This file is free software; you can redistribute it and/or modify
     13 ;; it under the terms of the GNU General Public License as published by
     14 ;; the Free Software Foundation; either version 3, or (at your option)
     15 ;; any later version.
     16 
     17 ;; This file is distributed in the hope that it will be useful,
     18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     20 ;; GNU General Public License for more details.
     21 
     22 ;; You should have received a copy of the GNU General Public License
     23 ;; along with GNU Emacs; see the file COPYING.  If not, write to
     24 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     25 ;; Boston, MA 02110-1301, USA.
     26 
     27 ;;; Commentary:
     28 
     29 ;; Top level API for the Clojure parser.
     30 
     31 ;;; Code:
     32 
     33 (require 'map)
     34 (require 'seq)
     35 
     36 (require 'parseclj-parser)
     37 (require 'parseclj-ast)
     38 (require 'parseclj-alist)
     39 
     40 (defun parseclj-parse-clojure (&rest string-and-options)
     41   "Parse Clojure source to AST.
     42 
     43 Reads either from the current buffer, starting from point, until
     44 `point-max', or reads from the optional string argument.
     45 
     46 STRING-AND-OPTIONS can be an optional string, followed by
     47 key-value pairs to specify parsing options.
     48 
     49 - `:lexical-preservation' Retain whitespace, comments, and
     50   discards.  Defaults to nil.
     51 - `:fail-fast' Raise an error when encountering invalid syntax.
     52   Defaults to t.
     53 - `:read-one'
     54   Read a single form.  Defaults to false: parse the complete input."
     55   (if (stringp (car string-and-options))
     56       (with-temp-buffer
     57         (insert (car string-and-options))
     58         (goto-char 1)
     59         (apply 'parseclj-parse-clojure (cdr string-and-options)))
     60     (let* ((value-p (lambda (e)
     61                       (and (parseclj-ast-node-p e)
     62                            (not (member (parseclj-ast-node-type e) '(:whitespace :comment :discard))))))
     63            (options (apply 'parseclj-alist :value-p value-p string-and-options))
     64            (lexical? (map-elt options :lexical-preservation)))
     65       (parseclj-parser (if lexical?
     66                            #'parseclj-ast--reduce-leaf-with-lexical-preservation
     67                          #'parseclj-ast--reduce-leaf)
     68                        (if lexical?
     69                            #'parseclj-ast--reduce-branch-with-lexical-preservation
     70                          #'parseclj-ast--reduce-branch)
     71                        options))))
     72 
     73 (defun parseclj-unparse-clojure (ast)
     74   "Parse Clojure AST to source code.
     75 
     76 Given an abstract syntax tree AST (as returned by
     77 `parseclj-parse-clojure'), turn it back into source code, and
     78 insert it into the current buffer."
     79   (if (parseclj-ast-leaf-node-p ast)
     80       (insert (map-elt ast :form))
     81     (if (eql (parseclj-ast-node-type ast) :tag)
     82         (parseclj-ast--unparse-tag ast)
     83       (parseclj-ast--unparse-collection ast))))
     84 
     85 (defun parseclj-unparse-clojure-to-string (ast)
     86   "Parse Clojure AST to a source code string.
     87 
     88 Given an abstract syntax tree AST (as returned by
     89 `parseclj-parse-clojure'), turn it back into source code, and
     90 return it as a string"
     91   (with-temp-buffer
     92     (parseclj-unparse-clojure ast)
     93     (buffer-substring-no-properties (point-min) (point-max))))
     94 
     95 (provide 'parseclj)
     96 
     97 ;;; parseclj.el ends here