Skip to content

Instantly share code, notes, and snippets.

@enricoflor
Last active October 9, 2022 16:56
Show Gist options
  • Save enricoflor/ee55d82535d3f59ff431bb1445aed993 to your computer and use it in GitHub Desktop.
Save enricoflor/ee55d82535d3f59ff431bb1445aed993 to your computer and use it in GitHub Desktop.
Convert syntree Input to forest input
;; Copyright (C) 2022 Enrico Flor
;; SPDX-License-Identifier: GPL-3.0-or-later
;; This program 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 of the
;; License, or (at your option) any later version.
;;
;; This program 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 this program. If not, see
;; <https://www.gnu.org/licenses/>.
;;; Commentary:
;; Function syntree-convert-to-forest takes a *valid* syntree input
;; (one that passes the checks in syntree--check-input), and outputs a
;; string that can be interpreted in a Forest environment in LaTeX.
;; For example:
;;
;; "(\"Top\" \"Spec\" (\"Bar\" \"_Lab:Text\"))"
;;
;; ⟶ [ Top [Spec] [ Bar [Lab \\ Text, roof] ] ]
;;
;; For more info about syntree and its syntax:
;; <https://github.com/enricoflor/syntree>
;; For more info about Forest:
;; <https://www.ctan.org/pkg/forest>
;;; Code:
(require 'cl-lib)
(require 'subr-x)
(defun syntree--index (l)
"Return L with string replaced with indices preserving tree
structure."
(cond ((stringp l)
(secure-hash 'sha256 l))
((cl-every #'stringp l)
(cons (concat "!" (secure-hash 'sha256 (car l)))
;; the "!" indicates that it's a non-terminal
(mapcar (lambda (x) (secure-hash 'sha256 x))
(cdr l))))
((cons (concat "!" (secure-hash 'sha256 (car l)))
;; the "!" indicates that it's a non-terminal
(mapcar #'syntree--index
(cdr l))))))
(defun syntree--reformat-string (s)
(let* ((chopped (string-remove-prefix "_" s))
(roof (not (equal chopped s)))
(leaf-split (split-string (string-trim chopped) ":"))
(label (when (> (length leaf-split) 1)
(car leaf-split)))
(text (if (= (length leaf-split) 1)
(car leaf-split)
(mapconcat #'identity (cdr leaf-split) ":")))
(output text))
(when roof (setq output (concat output ", roof")))
(when (and (> (length leaf-split) 1)
(not (string-blank-p (car leaf-split))))
(setq output (concat label " \\\\ " output)))
(concat "[" output "]")))
(defun syntree-convert-to-forest (s)
"Convert syntree input string S to input for forest."
(let ((input (read s))
(shas))
(dolist (x (flatten-tree input))
(push (cons (secure-hash 'sha256 x) x) shas))
(let* ((indexed (syntree--index input))
(squaredlist (thread-last
indexed
(format "%s")
(replace-regexp-in-string "(" " [ ")
(replace-regexp-in-string ")" " ] ")
(split-string)))
(output))
(dolist (x squaredlist)
(cond ((or (equal x "[") (equal x "]"))
(push x output))
((string-prefix-p "!" x)
(push (cdr (assoc (string-remove-prefix "!" x) shas))
output))
(t (push (syntree--reformat-string (cdr (assoc x shas)))
output))))
(mapconcat #'identity (nreverse output) " "))))
;;; syntree-to-forest.el ends here
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment