update of packages
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
;;; ess-r-syntax.el --- Utils to work with R code
|
||||
;;; ess-r-syntax.el --- Utils to work with R code -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2015-2020 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
|
||||
;; Author: Lionel Henry <lionel.hry@gmail.com>
|
||||
;; Created: 12 Oct 2015
|
||||
;; Maintainer: ESS-core <ESS-core@r-project.org>
|
||||
@@ -123,7 +123,7 @@ This is useful to trigger side-effects. FORMS follows the same
|
||||
syntax as arguments to `cond'."
|
||||
(declare (indent 0) (debug nil))
|
||||
`(let ((forms (list ,@(mapcar (lambda (form) `(progn ,@form)) forms))))
|
||||
(cl-some 'identity (mapcar 'eval forms))))
|
||||
(cl-some #'identity (mapcar (lambda (e) (eval e t)) forms))))
|
||||
|
||||
(defun ess-char-syntax (string)
|
||||
(char-to-string (char-syntax (string-to-char string))))
|
||||
@@ -340,25 +340,6 @@ content. Return nil when the end of the buffer is reached."
|
||||
(ess-forward-sexp)
|
||||
"%infix%")))
|
||||
|
||||
(defun ess-escape-token ()
|
||||
(ess-escape-comment)
|
||||
(ess-skip-blanks-forward)
|
||||
(or (ess-escape-string)
|
||||
(when (ess-token-delimiter-p (ess-token-after))
|
||||
(prog1 t
|
||||
(mapc (lambda (delims)
|
||||
(while (and (ess-token-after= nil delims)
|
||||
(eq (char-before) (string-to-char
|
||||
(car delims))))
|
||||
(ess-backward-char)))
|
||||
'(("[" "[[") ("]" "]]")))))
|
||||
(ess-token-after= '("," ";"))
|
||||
(and (ess-token-after= "identifier")
|
||||
(not (memq (char-syntax (char-before)) '(?w ?_))))
|
||||
(progn (skip-syntax-backward ".")
|
||||
(ess-token-operator-p (ess-token-after)))
|
||||
(/= (skip-syntax-backward "w_") 0)))
|
||||
|
||||
(defun ess-refine-token (token)
|
||||
(let ((refined-type
|
||||
(pcase (ess-token-type token)
|
||||
@@ -407,15 +388,6 @@ content. Return nil when the end of the buffer is reached."
|
||||
(nth 1 token))
|
||||
token)))
|
||||
|
||||
(defun ess-token-balancing-delim (token)
|
||||
(pcase (ess-token-type token)
|
||||
(`"(" ")")
|
||||
(`")" "(")
|
||||
(`"[" "]")
|
||||
(`"]" "[")
|
||||
(`"[[" "]]")
|
||||
(`"]]" "[[")))
|
||||
|
||||
|
||||
;;;*;;; Token predicates
|
||||
|
||||
@@ -457,294 +429,6 @@ content. Return nil when the end of the buffer is reached."
|
||||
(member (ess-token-type token) ess-r-keywords-list))
|
||||
|
||||
|
||||
;;;*;;; Tokens properties and accessors
|
||||
|
||||
(defun ess-token-make-hash (&rest specs)
|
||||
(let ((table (make-hash-table :test #'equal)))
|
||||
(mapc (lambda (spec)
|
||||
;; alist
|
||||
(if (listp (cdr spec))
|
||||
(mapc (lambda (cell)
|
||||
(puthash (car cell) (cdr cell) table))
|
||||
spec)
|
||||
;; Cons cell
|
||||
(mapc (lambda (token)
|
||||
(puthash token (cdr spec) table))
|
||||
(car spec))))
|
||||
specs)
|
||||
table))
|
||||
|
||||
(defvar ess-token-r-powers-delimiters
|
||||
'(("(" . 100)
|
||||
("[" . 100)
|
||||
("[[" . 100)))
|
||||
|
||||
(defvar ess-token-r-powers-operator
|
||||
'(("?" . 5)
|
||||
("else" . 8)
|
||||
("<-" . 10)
|
||||
("<<-" . 10)
|
||||
("=" . 15)
|
||||
("->" . 20)
|
||||
("->>" . 20)
|
||||
("~" . 25)
|
||||
("|" . 30)
|
||||
("||" . 30)
|
||||
("&" . 35)
|
||||
("&&" . 35)
|
||||
("!" . 40)
|
||||
("<" . 45)
|
||||
(">" . 45)
|
||||
("<=" . 45)
|
||||
(">=" . 45)
|
||||
("==" . 45)
|
||||
("+" . 50)
|
||||
("-" . 50)
|
||||
("*" . 55)
|
||||
("/" . 55)
|
||||
("%infix%" . 60)
|
||||
(":" . 65)
|
||||
("^" . 70)
|
||||
("$" . 75)
|
||||
("@" . 75)
|
||||
("::" . 80)
|
||||
(":::" . 80)))
|
||||
|
||||
(defvar ess-token-r-power-table
|
||||
(ess-token-make-hash ess-token-r-powers-operator
|
||||
ess-token-r-powers-delimiters))
|
||||
|
||||
(defvar ess-token-r-right-powers-operator
|
||||
'((")" . 1)))
|
||||
|
||||
(defvar ess-token-r-right-power-table
|
||||
(ess-token-make-hash ess-token-r-powers-operator
|
||||
ess-token-r-right-powers-operator))
|
||||
|
||||
(defvar ess-token-r-nud-table
|
||||
(ess-token-make-hash
|
||||
'(("identifier" . identity)
|
||||
("literal" . identity)
|
||||
("number" . identity)
|
||||
("function" . identity)
|
||||
("if" . identity)
|
||||
("while" . identity)
|
||||
("for" . identity))
|
||||
'(("(" . ess-parser-nud-block)
|
||||
("{" . ess-parser-nud-block))))
|
||||
|
||||
(defvar ess-token-r-rnud-table
|
||||
(ess-token-make-hash
|
||||
'(("identifier" . identity)
|
||||
("literal" . identity)
|
||||
("number" . identity))
|
||||
'((")" . ess-parser-rnud-paren)
|
||||
("}" . ess-parser-nud-block))))
|
||||
|
||||
(defvar ess-token-r-leds-operator
|
||||
(let ((operators-list (append '("%infix%" "else") ess-r-operators-list)))
|
||||
(cons operators-list #'ess-parser-led-lassoc)))
|
||||
|
||||
(defvar ess-token-r-leds-delimiter
|
||||
'(("(" . ess-parser-led-funcall)
|
||||
("[" . ess-parser-led-funcall)
|
||||
("[[" . ess-parser-led-funcall)))
|
||||
|
||||
(defvar ess-token-r-led-table
|
||||
(ess-token-make-hash ess-token-r-leds-operator
|
||||
ess-token-r-leds-delimiter))
|
||||
|
||||
(defvar ess-token-r-rid-table
|
||||
(ess-token-make-hash
|
||||
'((")" . ess-parser-rid-expr-prefix))))
|
||||
|
||||
|
||||
;;;*;;; Nud, led and rid functions
|
||||
|
||||
(defun ess-parser-nud-block (prefix-token)
|
||||
(let ((right (list (cons "TODO" nil))))
|
||||
(ess-parser-advance-pair nil prefix-token)
|
||||
(ess-node (cons "block" nil)
|
||||
(cons (ess-token-start prefix-token) (point))
|
||||
(list prefix-token right))))
|
||||
|
||||
(defun ess-parser-led-lassoc (start infix-token)
|
||||
(let* ((power (ess-parser-power infix-token))
|
||||
(end (ess-parse-expression power)))
|
||||
(ess-node (cons "binary-op" nil)
|
||||
(cons (ess-parser-token-start start) (point))
|
||||
(list start infix-token end))))
|
||||
|
||||
(defun ess-parser-led-funcall (left infix-token)
|
||||
(when (ess-token= left (append '("identifier" "string" "node")
|
||||
ess-r-prefix-keywords-list))
|
||||
(let* ((power (ess-parser-power infix-token))
|
||||
(right (ess-parse-arglist power infix-token))
|
||||
(type (if (ess-token= left ess-r-prefix-keywords-list)
|
||||
"prefixed-expr"
|
||||
"funcall")))
|
||||
(when (string= type "prefixed-expr")
|
||||
(setq right (list right (ess-parse-expression 0))))
|
||||
(ess-node (cons type nil)
|
||||
(cons (ess-parser-token-start left) (point))
|
||||
(list left right)))))
|
||||
|
||||
(defun ess-parser-rid-expr-prefix (right suffix-token)
|
||||
(when (ess-refined-token= suffix-token "prefixed-expr-delimiter")
|
||||
(ess-parser-rnud-paren suffix-token right)))
|
||||
|
||||
(defun ess-parser-rnud-paren (suffix-token &optional prefixed-expr)
|
||||
(let* ((infix-token (save-excursion
|
||||
(ess-parser-advance-pair nil suffix-token)))
|
||||
(power (ess-parser-power infix-token))
|
||||
(args (ess-parse-arglist power suffix-token))
|
||||
(left (if prefixed-expr
|
||||
(ess-parser-advance)
|
||||
(ess-parse-expression power)))
|
||||
(type (cond (prefixed-expr "prefixed-expr")
|
||||
(left "funcall")
|
||||
(t "enclosed-expr"))))
|
||||
(when prefixed-expr
|
||||
(setcdr (car prefixed-expr) (list infix-token suffix-token)))
|
||||
(ess-node (cons type nil)
|
||||
(cons (ess-parser-token-start suffix-token) (point))
|
||||
(if prefixed-expr
|
||||
(list prefixed-expr args left)
|
||||
(list args left)))))
|
||||
|
||||
|
||||
;;;*;;; Parsing
|
||||
|
||||
(defun ess-parser-advance (&optional type value)
|
||||
(if (bound-and-true-p ess-parser--backward)
|
||||
(ess-climb-token type value)
|
||||
(ess-jump-token type value)))
|
||||
|
||||
(defun ess-parser-advance-pair (&optional type token)
|
||||
(if (bound-and-true-p ess-parser--backward)
|
||||
(ess-climb-paired-delims type token)
|
||||
(ess-jump-paired-delims type token)))
|
||||
|
||||
(defun ess-parser-next-token ()
|
||||
(if (bound-and-true-p ess-parser--backward)
|
||||
(ess-token-before)
|
||||
(ess-token-after)))
|
||||
|
||||
(defun ess-parser-token-start (token)
|
||||
(if (bound-and-true-p ess-parser--backward)
|
||||
(ess-token-end token)
|
||||
(ess-token-start token)))
|
||||
|
||||
(defun ess-parser-power (token)
|
||||
(or (if (bound-and-true-p ess-parser--backward)
|
||||
(gethash (ess-token-type token) ess-token-r-right-power-table)
|
||||
(gethash (ess-token-type token) ess-token-r-power-table))
|
||||
0))
|
||||
|
||||
(defun ess-node (type pos contents)
|
||||
(let ((pos (if (bound-and-true-p ess-parser--backward)
|
||||
(cons (cdr pos) (car pos))
|
||||
pos))
|
||||
(contents (if (bound-and-true-p ess-parser--backward)
|
||||
(nreverse contents)
|
||||
contents)))
|
||||
(list type pos contents)))
|
||||
|
||||
(defalias 'ess-node-start #'ess-token-start)
|
||||
(defalias 'ess-node-end #'ess-token-end)
|
||||
|
||||
(defun ess-parse-start-token (token)
|
||||
(let* ((table (if (bound-and-true-p ess-parser--backward)
|
||||
ess-token-r-rnud-table
|
||||
ess-token-r-nud-table))
|
||||
(nud (gethash (ess-token-type token) table)))
|
||||
(when (fboundp nud)
|
||||
(funcall nud token))))
|
||||
|
||||
(defun ess-parse-infix-token (infix-token left)
|
||||
(let ((infix-power (ess-parser-power infix-token))
|
||||
(led (or (when (bound-and-true-p ess-parser--backward)
|
||||
(gethash (ess-token-type infix-token) ess-token-r-rid-table))
|
||||
(gethash (ess-token-type infix-token) ess-token-r-led-table))))
|
||||
(funcall led left infix-token)))
|
||||
|
||||
(defun ess-parse-expression (&optional power)
|
||||
(let ((current (ess-parse-start-token (ess-parser-advance)))
|
||||
(power (or power 0))
|
||||
(next (ess-parser-next-token))
|
||||
(last-successful-pos (point))
|
||||
last-success)
|
||||
(setq last-success current)
|
||||
(while (and current (< power (ess-parser-power next)))
|
||||
(ess-parser-advance)
|
||||
(when (setq current (ess-parse-infix-token next current))
|
||||
(setq last-successful-pos (point))
|
||||
(setq last-success current))
|
||||
(setq next (ess-parser-next-token)))
|
||||
(goto-char last-successful-pos)
|
||||
last-success))
|
||||
|
||||
(defun ess-parse-arglist (power start-token)
|
||||
(let ((start-pos (point))
|
||||
(arg-start-pos (point))
|
||||
(arglist (list start-token))
|
||||
(closing-delim (ess-token-balancing-delim start-token))
|
||||
expr)
|
||||
(while (and (setq expr (ess-parse-expression))
|
||||
(push (ess-node (cons "arg" nil)
|
||||
(cons arg-start-pos (point))
|
||||
(list expr))
|
||||
arglist)
|
||||
(ess-parser-advance ","))
|
||||
(setq arg-start-pos (point)))
|
||||
(push (ess-parser-advance closing-delim) arglist)
|
||||
(ess-node (cons "arglist" nil)
|
||||
(cons start-pos (1- (point)))
|
||||
(nreverse arglist))))
|
||||
|
||||
(defun forward-ess-r-expr ()
|
||||
(interactive)
|
||||
(ess-save-excursion-when-nil
|
||||
(ess-escape-token)
|
||||
(ess-parse-expression)))
|
||||
|
||||
(defun forward-ess-r-sexp ()
|
||||
(interactive)
|
||||
(ess-save-excursion-when-nil
|
||||
(ess-escape-token)
|
||||
(let* ((orig-token (ess-token-after))
|
||||
(tree (ess-parse-expression))
|
||||
(sexp-node (ess-parser-tree-assoc orig-token tree)))
|
||||
(when sexp-node
|
||||
(goto-char (ess-token-end sexp-node))
|
||||
sexp-node))))
|
||||
|
||||
(defun backward-ess-r-expr ()
|
||||
(interactive)
|
||||
(let ((ess-parser--backward t))
|
||||
(ess-parse-expression)))
|
||||
|
||||
(defun backward-ess-r-sexp ()
|
||||
(interactive)
|
||||
(error "Todo"))
|
||||
|
||||
(defun ess-parser-tree-assoc (key tree)
|
||||
(let ((next tree)
|
||||
stack last-node result)
|
||||
(while (and next (null result))
|
||||
(cond ((eq next 'node-end)
|
||||
(pop last-node))
|
||||
((nth 2 next)
|
||||
(push 'node-end stack)
|
||||
(dolist (node (nth 2 next))
|
||||
(push node stack))
|
||||
(push next last-node))
|
||||
((equal next key)
|
||||
(setq result (car last-node))))
|
||||
(setq next (pop stack)))
|
||||
result))
|
||||
|
||||
|
||||
;;*;; Point predicates
|
||||
|
||||
(defun ess-inside-call-p (&optional call)
|
||||
@@ -914,7 +598,7 @@ nil, return the prefix."
|
||||
(defun ess-behind-prefixed-block-p (&optional call)
|
||||
(if call
|
||||
(looking-at (concat call "[ \t]*("))
|
||||
(cl-some 'looking-at ess-prefixed-block-patterns)))
|
||||
(cl-some #'looking-at ess-prefixed-block-patterns)))
|
||||
|
||||
(defun ess-unbraced-block-p (&optional ignore-ifelse)
|
||||
"This indicates whether point is in front of an unbraced
|
||||
@@ -926,7 +610,7 @@ position of the control flow function (if, for, while, etc)."
|
||||
(not ignore-ifelse))
|
||||
(and (looking-at "(")
|
||||
(ess-backward-sexp)
|
||||
(cl-some 'looking-at ess-prefixed-block-patterns)
|
||||
(cl-some #'looking-at ess-prefixed-block-patterns)
|
||||
(if ignore-ifelse
|
||||
(not (looking-at "if\\b"))
|
||||
t)))
|
||||
|
||||
Reference in New Issue
Block a user