branch: elpa/proof-general
commit d60382db080370501bfe81d2a4f069035c8372a7
Merge: b82c21961f2 74ba7fc6de7
Author: Pierre Courtieu <[email protected]>
Commit: GitHub <[email protected]>

    Merge pull request #847 from Matafou/fix-elpi-parsing
    
    Fixing elpi syntax
    
    Initial idea by Philip Kaludercic.
---
 ci/coq-tests.el           |  18 ++++++++
 ci/test_command_parsing.v |  27 +++++++++++
 coq/coq-indent.el         | 113 +++++++++++++++++++++-------------------------
 coq/coq.el                |   7 +--
 4 files changed, 98 insertions(+), 67 deletions(-)

diff --git a/ci/coq-tests.el b/ci/coq-tests.el
index 9ab3cc9cef6..3e88ec6e9a2 100644
--- a/ci/coq-tests.el
+++ b/ci/coq-tests.el
@@ -137,6 +137,7 @@ then evaluate the BODY function and finally tear-down (exit 
Coq)."
 ;;; For info on macros: https://mullikine.github.io/posts/macro-tutorial
 ;;; (pp (macroexpand '(macro args)))
   (save-excursion
+    (if file (should (file-exists-p file)))
     (let* (;; avoids bad width detection in batch mode 
            (coq-auto-adapt-printing-width nil)
            (openfile (or file
@@ -503,6 +504,23 @@ For example, COMMENT could be (*test-definition*)"
                        (equal (span-end sp) (+ 1 proof-cmd-point (length 
"bar")))))
            )
          (should (equal (proof-queue-or-locked-end) (point-min)))))))) 
+
+(ert-deftest 200_test-command-spliting ()
+  "Test command splitting of a file."
+  (coq-fixture-on-file
+   (coq-test-full-path "test_command_parsing.v")
+   (lambda ()
+     (coq-test-goto-before "(*init*)")
+     (proof-goto-point)
+     (proof-shell-wait)
+     (goto-char (point-min))
+     (let ((cpt 0) type)
+       (while (setq type (funcall proof-script-parse-function))
+         (setq cpt (+ 1 cpt))
+         (should (equal type 'cmd)))
+       (should (equal cpt 17))))))
+
+
 (provide 'coq-tests)
 
 ;;; coq-tests.el ends here
diff --git a/ci/test_command_parsing.v b/ci/test_command_parsing.v
new file mode 100644
index 00000000000..62a04da8f2d
--- /dev/null
+++ b/ci/test_command_parsing.v
@@ -0,0 +1,27 @@
+Definition Foo := nat.
+Definition Bar := nat.
+(*init*)
+From elpi Require Import elpi.
+
+
+Lemma le_prop: forall n m p:entier, le n m -> le m p -> le n p.
+Proof.
+  intros n m p. 
+  intro H.
+  revert p.
+  induction H;intros.
+  - assumption.
+  - { + apply IHle.
+        apply le_Suuc_a_gauche.
+        assumption. }
+Qed.
+
+
+
+Elpi Tactic show.
+Elpi Accumulate lp:{{
+
+  solve (goal Ctx _Trigger Type Proof _) _ :-
+    coq.say "Goal:" Ctx "|-" Proof ":" Type.
+
+}}.
diff --git a/coq/coq-indent.el b/coq/coq-indent.el
index aab99837fab..1cefeb92ccd 100644
--- a/coq/coq-indent.el
+++ b/coq/coq-indent.el
@@ -3,7 +3,7 @@
 ;; This file is part of Proof General.
 
 ;; Portions © Copyright 1994-2012  David Aspinall and University of Edinburgh
-;; Portions © Copyright 2003-2021  Free Software Foundation, Inc.
+;; Portions © Copyright 2003-2021, 2023  Free Software Foundation, Inc.
 ;; Portions © Copyright 2001-2017  Pierre Courtieu
 ;; Portions © Copyright 2010, 2016  Erik Martin-Dorel
 ;; Portions © Copyright 2011-2013, 2016-2017  Hendrik Tews
@@ -37,7 +37,7 @@
 (defconst coq-comment-start-or-end-regexp
   (concat coq-comment-start-regexp "\\|" coq-comment-end-regexp))
 
-(defconst coq-bullet-regexp-nospace "\\(-\\)+\\|\\(+\\)+\\|\\(\\*\\)+"
+(defconst coq-bullet-regexp-nospace "\\(-\\)+\\|\\(\\+\\)+\\|\\(\\*\\)+"
   "Matches single bullet, WARNING: Lots of false positive.
 
 No context checking.")
@@ -53,9 +53,9 @@ No context checking.")
 ;; use of the fact that the file is processed from top to bottom. At
 ;; each step the point is put just after the last recognized chunk,
 ;; then spaces are jumped, and THEN the regexp for command end is
-;; searched. Since bullets are are command ends occurring at command
+;; searched. Since bullets are command ends occurring at command
 ;; start, we use the "\\=" regexp to tell if we are at the beginning
-;; of a command. We don't car for the presence of comments, as the
+;; of a command. We don't care for the presence of comments, as the
 ;; regexp search is launched once coments are passed.
 ;; On the contrary when going backward we cannot use this trick.
 
@@ -96,9 +96,11 @@ There are 3 substrings (2 and 3 may be nil):
 * number 2 is the left context matched that is not part of the bullet
 * number 3 is the right context matched that is not part of the bullet")
 
-;; captures a lot of false bullets, unless called at the first non
-;; space character of a command. The primary use of this variable is
-;; to split the buffer into commands, from top to bottom.
+;; captures a lot of false bullets, unless called at the first non space 
character
+;; of a command. The primary use of this variable is to split the buffer into
+;; commands, from top to bottom. We use the \= regexp for the special case 
where we
+;; match the regexp at the very starting point (in which case we don't look at 
what
+;; is before the main regexp)
 (defconst coq-bullet-end-command-forward
   (concat "\\(?:\\=\\(?1:" coq-bullet-regexp-nospace "\\)\\)")
   "Matches ltac bullets.  WARNING: lots of false positive.
@@ -110,7 +112,7 @@ only when searching backward).")
 
 ;; Context aware detecting regexp, usefull when search backward.
 (defconst coq-bullet-end-command-backward
-  (concat "\\(?:\\(?2:" coq-bullet-prefix-regexp-backward 
"\\)\\(?1:\\(-\\)+\\|\\(+\\)+\\|\\(\\*\\)+\\)\\)")
+  (concat "\\(?:\\(?2:" coq-bullet-prefix-regexp-backward 
"\\)\\(?1:\\(-\\)+\\|\\(\\+\\)+\\|\\(\\*\\)+\\)\\)")
   "Matches ltac bullets when searching backward.
 
 This should match EXACTLY bullets.  No false positive should be accepted.
@@ -122,7 +124,7 @@ There are 2 substrings:
   (concat
    "\\(?:"
      "\\(?2:"
-       "\\(?:" coq-bullet-prefix-regexp-forward"\\)\\)"
+       "\\(?:" coq-bullet-prefix-regexp-forward "\\)\\)"
       "\\(?1:\\(?:" coq-goal-selector-regexp "\\)?{\\)"
       "\\(?3:\\s-*[^|{]\\)"
      "\\|"
@@ -191,7 +193,6 @@ There are 3 substrings (2 and 3 may be nil):
 Remark: This regexp is much more precise than `coq-end-command-regexp-forward'
 but only works when searching backward.")
 
-(defconst coq-cmd-end-backward-matcher (concat "\\(?2:" 
coq-simple-cmd-ender-prefix-regexp-backward "\\)\\.\\s-"))
 
 (defun coq-looking-at-comment ()
   "Return non-nil if point is inside a comment."
@@ -345,9 +346,12 @@ a comment, return nil and does not move the point."
 ;;           )))
 ;;     (when found (point))))
 
-;; check if we are in the middle of an command ender. Return the
-;; number of shift needed to have to move one char to see the end of a
-;; command. typically if we are ( >< is the cursor). intro.><
+;; check if we are in the middle of an command ender. Return the number of left
+;; shifts needed to move to see the whole command ender a command. typically 
if we
+;; are ( >< is the cursor):
+;;   intro.><, then we return 1
+;;   intro><., then we return 0
+;;   int><ro., then we return 0
 (defun coq-is-on-ending-context ()
   (cond
    ((looking-at "}") 0)
@@ -388,6 +392,32 @@ Comments are ignored, of course."
    ))
 
 
+;; Strictly speaking lp:{{ could be a goal selector?
+(defun coq-is-at-elpi-block (pos)
+  (save-excursion (goto-char pos) (and (looking-at "{{") (looking-back 
"lp:"))))
+
+(defun coq-in-elpi-block (lopen)
+  (cl-find-if 'coq-is-at-elpi-block lopen))
+
+(defun coq-confirm-cmdend (&optional pos)
+  "Return t if POS is really a Rocq command end.
+
+WARNING: POS should be looking at a command that matched command end
+regexp. This function only checks if it is not a false positive, like
+something like a bullet (-,+,*) but actually not at the beginning of a
+command, or a regular command end but located in a comment or inside an
+elpi block."
+  (save-excursion
+    (if pos (goto-char pos))
+    (let ((ppss (syntax-ppss)))
+    (cond
+     ((nth 3 ppss) nil) ;; inside a string
+     ((nth 4 ppss) nil) ;; inside a comment
+     ((coq-in-elpi-block (nth 9 ppss)) nil)
+     ((looking-at "\\+\\|\\*\\|-\\|{\\|}") (coq-empty-command-p))
+     (t)))))
+  
+
 ; slight modification of proof-script-generic-parse-cmdend (one of the
 ; candidate for proof-script-parse-function), to allow "{" and "}" to
 ; be command terminator when the command is empty. This function is
@@ -411,36 +441,15 @@ regexp."
                         (and
                          (re-search-forward coq-end-command-regexp-forward 
limit t)
                          (match-end 1)))
-                  (or
-                   (and (not (or (string-equal (match-string 1) ".")
-                                 (string-equal (match-string 1) "...")))
-                        ;; Checking that this is really a bullet
-                        ;; command-end that are not a dot are + ++ -
-                        ;; -- etc or { or }. To ensure this is really
-                        ;; a bullet (and not one of the numerous
-                        ;; other possible uses of those tokens) we
-                        ;; check that the command ended by it is
-                        ;; empty. example:
-                        ;; destruct x.
-                        ;; - (* - here ends an empty command*)
-                        (save-excursion
-                          (goto-char (match-beginning 1))
-                          (not (coq-empty-command-p))))
-                   (and
-                    (goto-char foundend)
-                    (nth 8 (syntax-ppss)))))
+                  (not (coq-confirm-cmdend (match-beginning 1))))
         ;; Given the form of coq-end-command-regexp-forward
         ;; match-end 1 is the right place to start again
         ;; to search backward, next time we start from just
         ;; there
         (ignore-errors (goto-char foundend)))
-      (if (and foundend
-               (goto-char foundend) ; move to command end
-               (not (nth 8 (syntax-ppss))))
-          ;; Found command end outside string/comment
-          'cmd
-        ;; Didn't find command end
-        nil))))
+      (if (not foundend) nil
+        (goto-char foundend)
+        'cmd))))
 
 
 ;; This is not used by generic pg, just by a few functions in here.
@@ -464,31 +473,11 @@ and return nil."
                         (and
                          (re-search-backward coq-end-command-regexp-backward 
limit 'dummy)
                          (match-beginning 1)))
-                  ;; Given the form of coq-end-command-regexp-backward
-                  ;; - bullets should be correctly detected
-                  ;; - match-beginning 1 is the right place to start again
-                  ;;   to search backward, next time we start from just
-                  ;;   there, unless we are in a comment
-                  (goto-char foundbeg)
-                  (let ((ppss (syntax-ppss)))
-                    ;; If neither within a string nor a comment, just exit the
-                    ;; loop.  Otherwise see what kind of syntactic
-                    (and (nth 8 ppss)
-                         (cond
-                          ;; jump directly out of a comment
-                          ((nth 4 ppss)
-                           (setq foundbeg (goto-char (nth 8 ppss))))
-                          ((nth 3 ppss) t) ;FIXME: Why?
-                          ;; nil captured before entering the cond
-                          (t (message "assert false"))))))
+                  (not (coq-confirm-cmdend (match-beginning 1))))
         (ignore-errors (goto-char foundbeg)))
-      (if (and foundbeg
-               (goto-char foundbeg) ; move to command end
-               (not (nth 8 (syntax-ppss))))
-          ;; Found command end outside string/comment
-          'cmd
-        ;; Didn't find command end
-        nil))))
+      (if (not foundbeg) nil
+        (goto-char foundbeg)
+        'cmd))))
 
 
 (defun coq-find-current-start ()
diff --git a/coq/coq.el b/coq/coq.el
index 7d0f528b762..bbb187143e2 100644
--- a/coq/coq.el
+++ b/coq/coq.el
@@ -488,15 +488,12 @@ This is a subroutine of `proof-shell-filter'."
 
 
 ;; slight modification of proof-script-generic-parse-cmdend (one of the
-;; candidate for proof-script-parse-function), to allow "{" and "}" to be
-;; command terminator when the command is empty. TO PLUG: swith the comment
-;; below and rename coq-script-parse-function2 into coq-script-parse-function
+;; candidate for proof-script-parse-function). See its definition in
+;; coq-indent.el.
 (defun coq-script-parse-function ()
   "For `proof-script-parse-function' if `proof-script-command-end-regexp' set."
   (coq-script-parse-cmdend-forward))
 
-;;;;;;;;;;;;;;;;;;;;;;;;;; End of "{" and "} experiments ;;;;;;;;;;;;
-
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;; Freeze buffers ;;;;;;;;;;;;
 ;; For storing output of respnse and goals buffers into a permanent buffer.

Reply via email to