[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/wisi 511d382b2b 1/2: Release version 4.2.0
From: |
Stephen Leake |
Subject: |
[elpa] externals/wisi 511d382b2b 1/2: Release version 4.2.0 |
Date: |
Wed, 11 Jan 2023 19:24:22 -0500 (EST) |
branch: externals/wisi
commit 511d382b2be240a601c7e5807532d8b09e37785c
Author: Stephen Leake <stephen_leake@stephe-leake.org>
Commit: Stephen Leake <stephen_leake@stephe-leake.org>
Release version 4.2.0
---
Alire.make | 10 +
ELPA.make | 34 +-
NEWS | 31 +-
README | 2 +-
alire_rules.make | 16 +
emacs_wisi_common_parse.adb | 3 +-
emacs_wisi_common_parse.ads | 3 +-
gen_emacs_wisi_lr_parse.adb | 12 +-
gen_emacs_wisi_lr_text_rep_parse.adb | 12 +-
gen_run_wisi_lr_parse.adb | 12 +-
gen_run_wisi_lr_text_rep_parse.adb | 12 +-
install.sh | 2 +-
prj-alire.el | 11 +
prj-wisi.el | 30 ++
run_wisi_common_parse.adb | 10 +-
run_wisi_common_parse.ads | 5 +-
standard_common.gpr | 7 +
wisi-fringe.el | 107 +-----
wisi-parse_context.adb | 3 +-
wisi-parse_context.ads | 2 +-
wisi-prj.el | 24 +-
wisi-process-parse.el | 40 ++-
wisi-run-indent-test.el | 57 ++-
wisi-skel.el | 8 +-
wisi.el | 101 ++++--
wisi.texi | 12 +-
wisitoken-bnf-generate.adb | 36 +-
wisitoken-bnf-output_ada.adb | 12 +-
wisitoken-bnf.adb | 1 +
wisitoken-bnf.ads | 13 +-
wisitoken-generate-lr-lr1_generate.adb | 629 +--------------------------------
wisitoken-generate-lr-lr1_generate.ads | 18 +-
wisitoken-lexer-re2c.ads | 2 +-
wisitoken-parse-lr-parser-parse.adb | 3 +-
wisitoken-parse-lr-parser.adb | 6 +
wisitoken-parse-lr-parser.ads | 12 +-
wisitoken-parse.ads | 1 +
wisitoken-parse_table-mode.el | 10 +-
wisitoken-user_guide.texinfo | 6 +-
wisitoken_grammar_actions.adb | 2 +-
wisitoken_grammar_actions.ads | 2 +-
wisitoken_grammar_main.adb | 2 +-
wisitoken_grammar_main.ads | 2 +-
wisitoken_grammar_re2c.c | 2 +-
wisitoken_grammar_re2c_c.ads | 2 +-
45 files changed, 411 insertions(+), 916 deletions(-)
diff --git a/Alire.make b/Alire.make
new file mode 100644
index 0000000000..74f5027966
--- /dev/null
+++ b/Alire.make
@@ -0,0 +1,10 @@
+# Build Ada parts of Emacs wisi with Alire; see build/Makefile for non-Alire
build
+
+STEPHES_ADA_LIBRARY_ALIRE_PREFIX ?= $(CURDIR)/../org.stephe_leake.sal
+
+include $(STEPHES_ADA_LIBRARY_ALIRE_PREFIX)/build/alire_rules.make
+
+# Local Variables:
+# eval: (unless dvc-doing-ediff-p (load-file "prj-wisi.el"))
+# End:
+# end of file
diff --git a/ELPA.make b/ELPA.make
index 27829eef96..566092f31a 100644
--- a/ELPA.make
+++ b/ELPA.make
@@ -1,31 +1,31 @@
-# For compiling in elpa
+# For compiling wisi code in elpa worktree
-.PHONY : all force
-
-all : byte-compile autoloads
+#export Standard_Common_Build := Debug
-ifeq ($(shell uname),Linux)
-EMACS_EXE ?= emacs
+.PHONY : all force
-else ifeq ($(shell uname),Darwin)
-EMACS_EXE ?= "/Applications/Emacs.app/Contents/MacOS/Emacs"
+all : build_ada byte-compile
-else
-# windows
-# specify uniscribe to workaround weird Windows harfbuzz bug
-EMACS_EXE ?= emacs -xrm Emacs.fontBackend:uniscribe
+build_ada : wisi.gpr force
+ gprbuild -p -j8 wisi.gpr
-endif
+wisi.gpr : wisi.gpr.gp
+ gnatprep -DELPA="yes" wisi.gpr.gp wisi.gpr
-BYTE_COMPILE := "(progn (setq byte-compile-error-on-warn
t)(batch-byte-compile))"
+BYTE_COMPILE := "(progn (setq package-load-list '((wisi) (ada-mode)
(gnat-compiler) all)) (package-initialize)(setq byte-compile-error-on-warn
t)(batch-byte-compile))"
byte-compile : byte-compile-clean
- $(EMACS_EXE) -Q -batch -L . --eval $(BYTE_COMPILE) *.el
+ emacs -Q -batch -L . --eval $(BYTE_COMPILE) *.el
byte-compile-clean :
rm -f *.elc
-autoloads : force
- $(EMACS_EXE) -Q -batch --eval "(progn (setq generated-autoload-file
(expand-file-name \"autoloads.el\"))(update-directory-autoloads \".\"))"
+clean : force
+ rm -rf wisi.gpr obj *parse_table*
+recursive-clean : force
+ gprclean -r -P wisi.gpr
+# Local Variables:
+# eval: (unless dvc-doing-ediff-p (load-file "prj-wisi.el"))
+# End:
# end of file
diff --git a/NEWS b/NEWS
index 478b6f91ef..058168d67c 100644
--- a/NEWS
+++ b/NEWS
@@ -1,11 +1,40 @@
GNU Emacs wisi NEWS -- history of user-visible changes.
-Copyright (C) 2014 - 2022 Free Software Foundation, Inc.
+Copyright (C) 2014 - 2023 Free Software Foundation, Inc.
Please send wisi bug reports to bug-gnu-emacs@gnu.org, with
'wisi' in the subject. If possible, use M-x report-emacs-bug.
+* wisi 4.2.0
+3 Jan 2023
+
+** New user variables wisi-disable-completion,
+ wisi-disable-diagnostics, wisi-disable-indent, wisi-disable-parser,
+ wisi-disable-statement to control various features. Normally set by
+ the major mode when it chooses which backends to use.
+
+** New wisi project file statement; @code{import_env_var} - copies the
+ value of an environment variable from @code{process-environment} to
+ the project environment variables.
+
+** Case exception files declared in a wisi project file are now
+ searched for on the project file search path.
+
+** No longer displays right fringe marks, that were supposed to show
+ the location of erros within a file; too hard to get right and
+ maintain, not very useful.
+
+** No longer sets global value of skeleton-end-hook.
+
+** Several small bug fixes
+
+** parser process protocol version 7
+
+ Add commands dump_prev_tree, save_prev_auto; useful for debugging
+ incremental parse issues. Controlled by new user variable
+ wisi-save-text-tree.
+
* wisi 4.1.1
8 Oct 2022
diff --git a/README b/README
index 633727e4b8..715c4da796 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-Emacs wisi package 4.1.1
+Emacs wisi package 4.2.0
The wisi package provides utilities for using generalized
error-correcting LR parsers (in external processes) to do indentation,
diff --git a/alire_rules.make b/alire_rules.make
new file mode 100644
index 0000000000..e214496368
--- /dev/null
+++ b/alire_rules.make
@@ -0,0 +1,16 @@
+# gnu make rules for building with Alire.
+
+# alr must be started in the directory holding alire.toml
+alire-build : force
+ GPR_PROJECT_PATH= ; alr --no-tty --no-color $(ALIRE_ARGS) build
$(ALIRE_BUILD_ARGS)
+
+alire-env :
+ GPR_PROJECT_PATH= ; alr $(ALIRE_ARGS) printenv
+
+alire-clean :
+ alr clean
+ rm -rf alire build/obj/release build/obj/development
+
+.PHONY : force
+
+# end of file
diff --git a/emacs_wisi_common_parse.adb b/emacs_wisi_common_parse.adb
index 6c1c80a228..5fc3877ee7 100644
--- a/emacs_wisi_common_parse.adb
+++ b/emacs_wisi_common_parse.adb
@@ -249,6 +249,7 @@ package body Emacs_Wisi_Common_Parse is
Language_Protocol_Version : in String;
Params : in Process_Start_Params;
Factory : in WisiToken.Parse.Factory;
+ Free_Parser : in WisiToken.Parse.Free_Parser;
Trace : in WisiToken.Trace_Access)
is
use Ada.Text_IO;
@@ -349,7 +350,7 @@ package body Emacs_Wisi_Common_Parse is
Reset_Content_On_Free => False);
elsif Match ("kill-context") then
- Wisi.Parse_Context.Kill (File_Name => Wisi.Get_String
(Command_Line, Last));
+ Wisi.Parse_Context.Kill (File_Name => Wisi.Get_String
(Command_Line, Last), Free_Parser => Free_Parser);
elsif Match ("memory_report_reset") then
-- Args: <none>
diff --git a/emacs_wisi_common_parse.ads b/emacs_wisi_common_parse.ads
index e6852cf422..a5fb95840b 100644
--- a/emacs_wisi_common_parse.ads
+++ b/emacs_wisi_common_parse.ads
@@ -24,7 +24,7 @@ with WisiToken.Parse;
with Wisi.Parse_Context;
package Emacs_Wisi_Common_Parse is
- Protocol_Version : constant String := "6";
+ Protocol_Version : constant String := "7";
-- Protocol_Version defines the data sent between elisp and the
-- background process, except for the language-specific parameters,
-- which are defined by the Language_Protocol_Version parameter to
@@ -67,6 +67,7 @@ package Emacs_Wisi_Common_Parse is
Language_Protocol_Version : in String;
Params : in Process_Start_Params;
Factory : in WisiToken.Parse.Factory;
+ Free_Parser : in WisiToken.Parse.Free_Parser;
Trace : in WisiToken.Trace_Access);
----------
diff --git a/gen_emacs_wisi_lr_parse.adb b/gen_emacs_wisi_lr_parse.adb
index 72638d68bf..b4f59111a1 100644
--- a/gen_emacs_wisi_lr_parse.adb
+++ b/gen_emacs_wisi_lr_parse.adb
@@ -36,7 +36,17 @@ is
Language_Matching_Begin_Tokens => Language_Matching_Begin_Tokens,
Language_String_ID_Set => Language_String_ID_Set));
end Factory;
+
+ procedure Free_Parser (Object : in out WisiToken.Parse.Base_Parser_Access)
+ is
+ LR_Parser : WisiToken.Parse.LR.Parser.Parser_Access :=
WisiToken.Parse.LR.Parser.Parser_Access (Object);
+ begin
+ WisiToken.Parse.LR.Parser.Free (LR_Parser);
+ Object := null;
+ end Free_Parser;
+
begin
Process_Stream
- (Name, Language_Protocol_Version, Params, Factory'Unrestricted_Access,
Trace'Unchecked_Access);
+ (Name, Language_Protocol_Version, Params,
+ Factory'Unrestricted_Access, Free_Parser'Unrestricted_Access,
Trace'Unchecked_Access);
end Gen_Emacs_Wisi_LR_Parse;
diff --git a/gen_emacs_wisi_lr_text_rep_parse.adb
b/gen_emacs_wisi_lr_text_rep_parse.adb
index c3a73ca565..ac7c2117ea 100644
--- a/gen_emacs_wisi_lr_text_rep_parse.adb
+++ b/gen_emacs_wisi_lr_text_rep_parse.adb
@@ -41,7 +41,17 @@ is
Language_String_ID_Set => Language_String_ID_Set,
Text_Rep_File_Name => Text_Rep_File_Name_Full));
end Factory;
+
+ procedure Free_Parser (Object : in out WisiToken.Parse.Base_Parser_Access)
+ is
+ LR_Parser : WisiToken.Parse.LR.Parser.Parser_Access :=
WisiToken.Parse.LR.Parser.Parser_Access (Object);
+ begin
+ WisiToken.Parse.LR.Parser.Free (LR_Parser);
+ Object := null;
+ end Free_Parser;
+
begin
Process_Stream
- (Name, Language_Protocol_Version, Params, Factory'Unrestricted_Access,
Trace'Unchecked_Access);
+ (Name, Language_Protocol_Version, Params,
+ Factory'Unrestricted_Access, Free_Parser'Unrestricted_Access,
Trace'Unchecked_Access);
end Gen_Emacs_Wisi_LR_Text_Rep_Parse;
diff --git a/gen_run_wisi_lr_parse.adb b/gen_run_wisi_lr_parse.adb
index 31477aa0dd..c96ecc789d 100644
--- a/gen_run_wisi_lr_parse.adb
+++ b/gen_run_wisi_lr_parse.adb
@@ -34,6 +34,16 @@ is
Language_Matching_Begin_Tokens => Language_Matching_Begin_Tokens,
Language_String_ID_Set => Language_String_ID_Set));
end Factory;
+
+ procedure Free_Parser (Object : in out WisiToken.Parse.Base_Parser_Access)
+ is
+ LR_Parser : WisiToken.Parse.LR.Parser.Parser_Access :=
WisiToken.Parse.LR.Parser.Parser_Access (Object);
+ begin
+ WisiToken.Parse.LR.Parser.Free (LR_Parser);
+ Object := null;
+ end Free_Parser;
+
begin
- Run_Wisi_Common_Parse.Parse_File (Factory'Unrestricted_Access,
Trace'Unchecked_Access);
+ Run_Wisi_Common_Parse.Parse_File
+ (Factory'Unrestricted_Access, Free_Parser'Unrestricted_Access,
Trace'Unchecked_Access);
end Gen_Run_Wisi_LR_Parse;
diff --git a/gen_run_wisi_lr_text_rep_parse.adb
b/gen_run_wisi_lr_text_rep_parse.adb
index a426cdc144..4bc934f10e 100644
--- a/gen_run_wisi_lr_text_rep_parse.adb
+++ b/gen_run_wisi_lr_text_rep_parse.adb
@@ -40,6 +40,16 @@ is
Language_String_ID_Set => Language_String_ID_Set,
Text_Rep_File_Name => Text_Rep_File_Name_Full));
end Factory;
+
+ procedure Free_Parser (Object : in out WisiToken.Parse.Base_Parser_Access)
+ is
+ LR_Parser : WisiToken.Parse.LR.Parser.Parser_Access :=
WisiToken.Parse.LR.Parser.Parser_Access (Object);
+ begin
+ WisiToken.Parse.LR.Parser.Free (LR_Parser);
+ Object := null;
+ end Free_Parser;
+
begin
- Run_Wisi_Common_Parse.Parse_File (Factory'Unrestricted_Access,
Trace'Unchecked_Access);
+ Run_Wisi_Common_Parse.Parse_File
+ (Factory'Unrestricted_Access, Free_Parser'Unrestricted_Access,
Trace'Unchecked_Access);
end Gen_Run_Wisi_LR_Text_Rep_Parse;
diff --git a/install.sh b/install.sh
old mode 100644
new mode 100755
index 202d6a1e8b..886fc94eed
--- a/install.sh
+++ b/install.sh
@@ -6,7 +6,7 @@
# $1 : optional --prefix=<dir>
#
# If you don't have write permission in the GNAT installation
-# directory, you need to use --prefix=<dir>, or run with root privileges.
+# directory, you need to use --prefix=<dir>, or run with root priviledges.
WISI_DIR=`ls -d ../wisi-3.1.?`
diff --git a/prj-alire.el b/prj-alire.el
new file mode 100644
index 0000000000..773c435d3f
--- /dev/null
+++ b/prj-alire.el
@@ -0,0 +1,11 @@
+;; Set up building with Alire -*- no-byte-compile : t -*-
+
+(wisi-prj-select-cache
+ "prj-alire.el"
+ (create-alire-prj
+ :name "wisi stephe-3 Alire eglot"
+ :gpr-file gpr-file
+ :xref-label 'gpr_query)
+ "Makefile")
+
+;; end of file
diff --git a/prj-wisi.el b/prj-wisi.el
new file mode 100644
index 0000000000..f8e41afdbf
--- /dev/null
+++ b/prj-wisi.el
@@ -0,0 +1,30 @@
+;; Set up building with gprbuild in elpa -*- no-byte-compile : t -*-
+;;
+;; Copyright (C) 2021, 2022 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU Emacs.
+;;
+;; GNU Emacs 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.
+;;
+;; GNU Emacs 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. If not, see <https://www.gnu.org/licenses/>.
+
+(wisi-prj-select-cache
+ "wisi.gpr"
+ (create-ada-prj
+ :name "wisi main"
+ :compile-env
+ (list
+ (concat "SAL=" (expand-file-name "../../org.stephe_leake.sal"))
+ (concat "WISITOKEN=" (expand-file-name "../../org.wisitoken"))
+ ))
+ "Makefile"
+ )
diff --git a/run_wisi_common_parse.adb b/run_wisi_common_parse.adb
index cd9609c98c..a3ece4cabf 100644
--- a/run_wisi_common_parse.adb
+++ b/run_wisi_common_parse.adb
@@ -404,6 +404,7 @@ package body Run_Wisi_Common_Parse is
procedure Process_Command
(Parse_Context : in out Wisi.Parse_Context.Parse_Context_Access;
Factory : in WisiToken.Parse.Factory;
+ Free_Parser : in WisiToken.Parse.Free_Parser;
Line : in String;
Trace : in WisiToken.Trace_Access)
is
@@ -466,7 +467,7 @@ package body Run_Wisi_Common_Parse is
if Source_File_Name = -Parse_Context.File_Name then
Parse_Context := null;
end if;
- Wisi.Parse_Context.Kill (Source_File_Name);
+ Wisi.Parse_Context.Kill (Source_File_Name, Free_Parser);
end;
when Language_Params =>
@@ -684,7 +685,10 @@ package body Run_Wisi_Common_Parse is
end case;
end Process_Command;
- procedure Parse_File (Factory : in WisiToken.Parse.Factory; Trace : in
WisiToken.Trace_Access)
+ procedure Parse_File
+ (Factory : in WisiToken.Parse.Factory;
+ Free_Parser : in WisiToken.Parse.Free_Parser;
+ Trace : in WisiToken.Trace_Access)
is
use Ada.Text_IO;
use WisiToken;
@@ -953,7 +957,7 @@ package body Run_Wisi_Common_Parse is
if Line (1 .. 2) = "--" then
null;
else
- Process_Command (Parse_Context, Factory, Line,
Trace);
+ Process_Command (Parse_Context, Factory,
Free_Parser, Line, Trace);
Trace.New_Line;
end if;
end if;
diff --git a/run_wisi_common_parse.ads b/run_wisi_common_parse.ads
index 67a5b8c3e1..d4f3cad148 100644
--- a/run_wisi_common_parse.ads
+++ b/run_wisi_common_parse.ads
@@ -22,7 +22,10 @@ with Wisi;
with WisiToken.Parse;
package Run_Wisi_Common_Parse is
- procedure Parse_File (Factory : in WisiToken.Parse.Factory; Trace : in
WisiToken.Trace_Access);
+ procedure Parse_File
+ (Factory : in WisiToken.Parse.Factory;
+ Free_Parser : in WisiToken.Parse.Free_Parser;
+ Trace : in WisiToken.Trace_Access);
-- Reads command line, processes command(s).
end Run_Wisi_Common_Parse;
diff --git a/standard_common.gpr b/standard_common.gpr
index 520c5f6e6e..6553e9559b 100644
--- a/standard_common.gpr
+++ b/standard_common.gpr
@@ -170,4 +170,11 @@ project Standard_Common is
end Linker;
-- In project files, no linker package is needed.
+
+ package Pretty_Printer is
+ -- Used by ada_language_server and gnatpp. Projects will need
+ -- to add "--dictionary=<case exceptions file>".
+ for Default_Switches ("Ada") use ("--source-line-breaks");
+ end Pretty_Printer;
+
end Standard_Common;
diff --git a/wisi-fringe.el b/wisi-fringe.el
index d928f38bda..875d4437e8 100644
--- a/wisi-fringe.el
+++ b/wisi-fringe.el
@@ -33,60 +33,18 @@
(require 'wisi-parse-common) ;For `wisi-debug'
-(defun wisi-fringe-create-bitmaps ()
- "Return an array of bitmap symbols containing the fringe bitmaps."
- ;; First create the ’!!’ bitmap.
- (define-fringe-bitmap 'wisi-fringe--double-exclaim-bmp
- (vector
- #b00000000
- #b01100110
- #b01100110
- #b01100110
- #b01100110
- #b01100110
- #b00000000
- #b01100110
- #b01010110
- #b00000000))
-
- ;; In condensing the entire buffer to the current window height, we
- ;; assume a 10 point font, which allows 6 distinct line positions
- ;; each one pixel high, with one blank pixel between.
-
- (let ((result (make-vector 64 nil))
- (i 1))
- (while (<= i (length result))
- (aset result (1- i)
- (define-fringe-bitmap (intern (format "wisi-fringe--line-%d-bmp" i))
- (vector
- (if (>= i 32) #b11111111 #b00000000)
- #b00000000
- (if (>= (% i 32) 16) #b11111111 #b00000000)
- #b00000000
- (if (>= (% i 16) 8) #b11111111 #b00000000)
- #b00000000
- (if (>= (% i 8) 4) #b11111111 #b00000000)
- #b00000000
- (if (>= (% i 4) 2) #b11111111 #b00000000)
- #b00000000
- (if (>= (% i 2) 1) #b11111111 #b00000000)
- )))
- (setq i (1+ i)))
- result))
-
-(defconst wisi-fringe-bitmaps (wisi-fringe-create-bitmaps)
- "Array of 64 bitmap symbols.")
-
-(defun wisi-fringe--put-right (line bitmap-index)
- (save-excursion
- (goto-char (point-min))
- (forward-line (1- line))
- (let* ((endpos (line-end-position))
- (ov (make-overlay endpos (1+ endpos)))
- (bmp (aref wisi-fringe-bitmaps bitmap-index)))
- (overlay-put ov 'after-string (propertize "-" 'display (list
'right-fringe bmp 'compilation-error)))
- (overlay-put ov 'wisi-fringe t)
- )))
+(define-fringe-bitmap 'wisi-fringe--double-exclaim-bmp
+ (vector
+ #b00000000
+ #b01100110
+ #b01100110
+ #b01100110
+ #b01100110
+ #b01100110
+ #b00000000
+ #b01100110
+ #b01010110
+ #b00000000))
(defun wisi-fringe--put-left (line)
(save-excursion
@@ -103,26 +61,6 @@
(overlay-put ov 'wisi-fringe t)
)))
-(defun wisi-fringe--scale (error-line buffer-lines window-line-first
window-lines)
- "Return a cons (LINE . BIN) for ERROR-LINE,
-where LINE is the line to display the error bar on, and BIN is a
-6-bit bit vector giving the relative position in that line.
-BUFFER-LINES is the count of lines in the buffer.
-WINDOW-LINE-FIRST is the first and last lines of the buffer
-visible in the window. WINDOW-LINES is the count of lines visible
-in the window."
- ;; If the end of buffer is inside the window, and this calculation
- ;; puts a mark after that, it will actually be put on the last real
- ;; line. That’s good enough for our purposes.
-
- ;; partial-lines / window-line = 6
- ;; buffer-lines / window-line = 1/scale
- ;; buffer-lines / partial-line = (window-line / partial-lines) *
(buffer-lines / window-line) = 1/6 * 1/scale
- (let* ((scale (/ window-lines (float buffer-lines)))
- (line (floor (* scale error-line)))
- (rem (- error-line (floor (/ line scale)))))
- (cons (+ window-line-first line) (ash 1 (min 5 (floor (* rem (* 6
scale))))))))
-
(defun wisi-fringe-clean ()
"Remove all wisi-fringe marks."
(remove-overlays (point-min) (point-max) 'wisi-fringe t))
@@ -131,17 +69,10 @@ in the window."
"Display markers in the fringe for each buffer position in POSITIONS.
The buffer containing POSITIONS must be current, and the window
displaying that buffer must be current."
- ;; We don't recompute fringe display on scroll, because the user
- ;; will probably have edited the code by then, triggering a new
- ;; parse. FIXME: use flymake.
(wisi-fringe-clean)
(when positions
- (let (scaled-posns
- (buffer-lines (line-number-at-pos (point-max) t))
- (window-lines (window-height))
- (window-pos-first (window-start))
- (window-pos-last (window-end))
- (window-line-first (line-number-at-pos (window-start) t)))
+ (let ((window-pos-first (window-start))
+ (window-pos-last (window-end)))
(when (< 1 wisi-debug)
(wisi-parse-log-message wisi-parser-shared
@@ -151,19 +82,11 @@ displaying that buffer must be current."
window-pos-last)))
(dolist (pos positions)
- (let* ((line (line-number-at-pos (max (point-min) (min (point-max)
pos)) t))
- (scaled-pos (wisi-fringe--scale line buffer-lines
window-line-first window-lines)))
+ (let* ((line (line-number-at-pos (max (point-min) (min (point-max)
pos)) t)))
(when (and (>= pos window-pos-first)
(<= pos window-pos-last))
(wisi-fringe--put-left line))
- (if (and scaled-posns
- (= (caar scaled-posns) (car scaled-pos)))
- (setcdr (car scaled-posns) (logior (cdar scaled-posns) (cdr
scaled-pos)))
- (push scaled-pos scaled-posns))
))
-
- (dolist (pos scaled-posns)
- (wisi-fringe--put-right (car pos) (1- (cdr pos))))
)))
(provide 'wisi-fringe)
diff --git a/wisi-parse_context.adb b/wisi-parse_context.adb
index 62654c0a0c..97c13bdce3 100644
--- a/wisi-parse_context.adb
+++ b/wisi-parse_context.adb
@@ -161,7 +161,7 @@ package body Wisi.Parse_Context is
end;
end Find;
- procedure Kill (File_Name : in String)
+ procedure Kill (File_Name : in String; Free_Parser : in
WisiToken.Parse.Free_Parser)
is begin
if File_Name'Length = 0 then
raise Wisi.Protocol_Error with "no file name given";
@@ -181,6 +181,7 @@ package body Wisi.Parse_Context is
begin
Map.Delete (File_Name);
Ada.Strings.Unbounded.Free (Context.Text_Buffer);
+ Free_Parser (Context.Parser);
Free (Context);
end;
end if;
diff --git a/wisi-parse_context.ads b/wisi-parse_context.ads
index 136a62a3e1..40f354ce6d 100644
--- a/wisi-parse_context.ads
+++ b/wisi-parse_context.ads
@@ -89,7 +89,7 @@ package Wisi.Parse_Context is
-- Raise Not_Found if no context found for File_Name.
-- If Have_Text, raise Not_Found if Text_Buffer is empty.
- procedure Kill (File_Name : in String);
+ procedure Kill (File_Name : in String; Free_Parser : in
WisiToken.Parse.Free_Parser);
procedure Clear;
-- Delete all contexts.
diff --git a/wisi-prj.el b/wisi-prj.el
index 75ed467e94..69ecc132a2 100644
--- a/wisi-prj.el
+++ b/wisi-prj.el
@@ -55,7 +55,7 @@
;;
;; New exceptions may be added interactively via
;; `wisi-case-create-exception'. If an exception is defined in
- ;; multiple files, the first occurrence is used.
+ ;; multiple files, the first occurence is used.
;;
;; The file format is one word per line, which gives the casing to be
;; used for that word in source code. If the line starts with
@@ -166,6 +166,11 @@ If NOT-FULL is non-nil, very slow refresh operations may
be skipped.")
;; modes don't have a language-specific compiler (eg java-wisi) or
;; xref process (eg gpr-mode).
+;;;###autoload
+(defun wisi-prj-make-compiler (label)
+ ;; We assume the constructor is autoloaded
+ (funcall (intern (format "create-%s-compiler" (symbol-name label)))))
+
(cl-defgeneric wisi-compiler-parse-one (compiler project name value)
"Set NAME, VALUE in COMPILER, if recognized by COMPILER.
PROJECT is an `wisi-prj' object; COMPILER is `wisi-prj-compiler'.")
@@ -196,6 +201,10 @@ SOURCE-BUFFER contains the source code referenced in the
error message.")
(cl-defgeneric wisi-compiler-root-dir (compiler)
"Return a meaningful root directory; nil if none.")
+(defun wisi-prj-make-xref (label)
+ ;; We assume the constructor is autoloaded
+ (funcall (intern (format "create-%s-xref" (symbol-name label)))))
+
(cl-defgeneric wisi-xref-parse-one (_xref _project _name _value)
"If recognized by XREF, set NAME, VALUE in XREF, return non-nil.
Else return nil."
@@ -534,7 +543,7 @@ With prefix, keep previous references in output buffer."
))
(defun wisi-show-local-references (&optional append)
- "Show all references of identifier at point occurring in current file.
+ "Show all references of identifier at point occuring in current file.
With prefix, keep previous references in output buffer."
(interactive "P")
(let* ((project (wisi-check-current-project (buffer-file-name)))
@@ -612,6 +621,9 @@ COLUMN - Emacs column of the start of the identifier")
(wisi-compiler-root-dir (wisi-prj-compiler project)))
(car (wisi-prj-source-path project))))
+(cl-defmethod project-name ((project wisi-prj))
+ (wisi-prj-name project))
+
(cl-defmethod project-files ((project wisi-prj) &optional dirs)
(let (result)
(dolist (dir (or dirs
@@ -998,7 +1010,7 @@ Return (cons full-exceptions partial-exceptions)."
))
(defun wisi--case-merge-exceptions (result new)
- "Merge NEW exceptions into RESULT.
+ "Merge NEW exeptions into RESULT.
An item in both lists has the RESULT value."
(dolist (item new)
(unless (assoc-string (car item) result t)
@@ -1429,7 +1441,11 @@ For `xref-backend-functions'."
(let ((prj (project-current)))
(when (and (wisi-prj-p prj)
(wisi-prj-xref prj))
- prj)))
+ (cond
+ ((eq (wisi-prj-xref prj) 'eglot)
+ 'eglot)
+ (t prj))
+ )))
;;;; project-find-functions alternatives
diff --git a/wisi-process-parse.el b/wisi-process-parse.el
index 4a209d987f..def4ce9c6e 100644
--- a/wisi-process-parse.el
+++ b/wisi-process-parse.el
@@ -1,6 +1,6 @@
;;; wisi-process-parse.el --- interface to external parse program -*-
lexical-binding: t; -*-
;;
-;; Copyright (C) 2014, 2017 - 2022 Free Software Foundation, Inc.
+;; Copyright (C) 2014, 2017 - 2023 Free Software Foundation, Inc.
;;
;; Author: Stephen Leake <stephen_leake@member.fsf.org>
;;
@@ -22,7 +22,7 @@
(require 'cl-lib)
(require 'wisi-parse-common)
-(defconst wisi-process-parse-protocol-version "6"
+(defconst wisi-process-parse-protocol-version "7"
"Defines data exchanged between this package and the background process.
Must match emacs_wisi_common_parse.ads Protocol_Version.")
@@ -153,10 +153,7 @@ Otherwise add PARSER to `wisi-process--alist', return it."
(with-current-buffer (car wisi-parse-full-active)
(read-only-mode -1)
(let ((region (cdr wisi-parse-full-active)))
- (when (and (>= (cdr region) (car region))
- (>= (cdr region) (point-min))
- (<= (car region) (point-max)))
- (font-lock-flush (car region) (cdr region))))
+ (font-lock-flush (max (point-min) (car region)) (min
(point-max) (cdr region))))
(set-process-filter process nil)
@@ -172,9 +169,9 @@ Otherwise add PARSER to `wisi-process--alist', return it."
)
(setq wisi-parse-full-active nil)
))))
- ))))
+ ))))
-(cl-defmethod wisi-parse-require-process (parser &key nowait)
+(cl-defmethod wisi-parse-require-process ((parser wisi-process--parser) &key
nowait)
(unless (process-live-p (wisi-process--parser-process parser))
(let ((process-connection-type nil) ;; use a pipe, not a pty; avoid
line-by-line reads
(process-name (format " *%s_wisi_parse*" (wisi-process--parser-label
parser))))
@@ -192,7 +189,9 @@ Otherwise add PARSER to `wisi-process--alist', return it."
(erase-buffer));; delete any previous messages, prompt
(when (or (not nowait) (>= wisi-debug 2))
- (message "starting parser %s ..." (wisi-process--parser-label parser)))
+ (message "starting wisi parser %s in buffer %s ..."
+ (wisi-process--parser-label parser)
+ (current-buffer)))
(wisi-parse-log-message parser "create process")
(setf (wisi-process--parser-version-checked parser) nil)
@@ -219,7 +218,7 @@ Otherwise add PARSER to `wisi-process--alist', return it."
(unless nowait
(wisi-process-parse--wait parser)
- (message "starting parser ... done"))
+ (message "starting wisi parser ... done"))
)))
(defun wisi-process-parse--wait (parser)
@@ -258,7 +257,7 @@ Otherwise add PARSER to `wisi-process--alist', return it."
(defun wisi-process-parse--add-cmd-length (cmd)
"Return CMD (a string) with length prefixed."
;; Characters in cmd length must match emacs_wisi_common_parse.adb
- ;; Get_Command_Length. If the actual length overflows the allotted
+ ;; Get_Command_Length. If the actual length overflows the alloted
;; space, we will get a protocol_error from the parser
;; eventually. Caller should prevent that and send an alternate
;; command.
@@ -324,6 +323,10 @@ complete. PARSE-END is end of desired parse region."
;; we don't log the buffer text; may be huge
(process-send-string process (buffer-substring-no-properties begin
send-end))
+ ;; We don't set wisi-process--parser-update-fringe; partial parse
+ ;; almost always has bogus errors at the start and end of the
+ ;; parse.
+ ;;
;; We don't wait for the send to complete here.
))
@@ -390,7 +393,7 @@ complete."
)))
(process (wisi-process--parser-process parser)))
- (setf (wisi-process--parser-update-fringe parser) t)
+ (setf (wisi-process--parser-update-fringe parser) (not
wisi-disable-diagnostics))
(with-current-buffer (wisi-process--parser-buffer parser)
(erase-buffer))
@@ -819,6 +822,7 @@ Source buffer is current."
(cl-defmethod wisi-parse-reset ((parser wisi-process--parser))
(setf (wisi-process--parser-busy parser) nil)
+ (setq wisi-parse-full-active nil)
(wisi-parse-require-process parser)
(wisi-process--kill-context parser)
(wisi-process-parse--wait parser))
@@ -838,6 +842,10 @@ Source buffer is current."
(cl-defun wisi-process-parse--prepare (parser parse-action &key nowait)
"Check for parser busy and startup, mark parser busy, require parser
process."
+ (unless (process-live-p (wisi-process--parser-process parser))
+ (wisi-parse-log-message parser "process died")
+ (error "parser process died"))
+
(when (wisi-process--parser-busy parser)
(when (< 1 wisi-debug)
(wisi-parse-log-message parser (format "parse--prepare %s in %s parser
busy" parse-action (current-buffer))))
@@ -1177,17 +1185,19 @@ Source buffer is current."
;; The parser process has not finished starting up, or has not yet
;; been started. If this is the very first Ada file in the current
;; project, and there is more text in the file than the process
- ;; send buffer holds, w-p-p--send-* hangs waiting for the process
+ ;; send buffer holds, w-p-p--send-* waits for the process
;; to start reading, which is after it loads the parse table,
;; which can take noticeable time for Ada.
- (message "starting parser %s ..." (wisi-process--parser-label parser)))
+ (message "waiting for wisi parser %s start in buffer %s ..."
+ (wisi-process--parser-label parser)
+ (current-buffer)))
(wisi-process-parse--prepare parser parse-action :nowait nowait)
(setf (wisi-parser-local-lexer-errors wisi-parser-local) nil)
(setf (wisi-parser-local-parse-errors wisi-parser-local) nil)
(cond
((and full nowait)
(set-process-filter (wisi-process--parser-process parser)
#'wisi-process-parse--filter)
- (setq wisi-parse-full-active (cons (current-buffer) (cons (point-max)
(point-min))))
+ (setq wisi-parse-full-active (cons (current-buffer) (cons (point-min)
(point-max))))
(read-only-mode 1)
(wisi-process-parse--send-incremental-parse parser full))
(t
diff --git a/wisi-run-indent-test.el b/wisi-run-indent-test.el
index b3a52bfcca..0f3090c4c0 100644
--- a/wisi-run-indent-test.el
+++ b/wisi-run-indent-test.el
@@ -36,6 +36,10 @@ text, after each edit in an incremental parse, and before
each partial parse.")
(defun test-in-comment-p ()
(nth 4 (syntax-ppss)))
+(defun wisi-wait-parser()
+ (while (wisi-process--parser-busy wisi-parser-shared)
+ (accept-process-output nil wisi-process-time-out)))
+
(defvar test-face-wait-fn nil
"Function to call after `font-lock-ensure' to wait for face to actually be
set.")
@@ -52,10 +56,12 @@ FACE may be a list."
(error "can't find '%s'" token)))
(when (not skip-recase-test) ;; should be t when wisi-disable-face is t
- (let ((token (match-string 0))
+ (let ((token (match-string-no-properties 0))
(test-pos (match-beginning 0)))
(when wisi-parser-shared
+ ;; it may be busy doing initial parse in another file opened by an
xref command.
+ (wisi-wait-parser)
(wisi-validate-cache (line-beginning-position) (line-end-position)
nil 'face))
(font-lock-ensure (line-beginning-position) (line-end-position))
@@ -93,9 +99,7 @@ FACE may be a list."
(when (text-property-not-all test-pos (+ test-pos (length token)) key
token-face)
(error "mixed faces, expecting %s for '%s'" face token))
- (unless (or (and (listp face)
- (memq token-face face))
- (eq token-face face))
+ (unless (equal token-face face)
(error "found face %s, expecting %s for '%s'" token-face face
token))
)))))
@@ -212,13 +216,24 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END
EDIT-BEGIN)")
(wisi-test-save-log-1 (get-buffer (nth 0 item)) (nth 1 item))))
))
+(defvar eglot-send-changes-idle-time)
+(declare-function jsonrpc--debug "jsonrpc.el")
+
(defun run-test-here ()
"Run an indentation and casing test on the current buffer."
(interactive)
- (condition-case-unless-debug err
+ (when wisi-incremental-parse-enable
+ ;; wait for the parser to finish the initial parse
+ (wisi-wait-parser))
+
+ (condition-case err
(progn
(setq indent-tabs-mode nil)
- (setq jit-lock-context-time 0.0);; for test-face
+
+ ;; for test-face
+ (setq jit-lock-context-time 0.0)
+ (setq-local font-lock-ensure-function 'jit-lock-fontify-now) ;; it's
not at all clear what's resetting this
+ (setq-local eglot-send-changes-idle-time 0.0) ;; FIXME: did not help
test-face
;; Test files use wisi-prj-select-cached to parse and select a project
file.
(setq project-find-functions (list #'wisi-prj-current-cached))
@@ -230,6 +245,7 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END
EDIT-BEGIN)")
(wisi-process-parse-save-text wisi-parser-shared save-edited-text t))
(let ((error-count 0)
+ (error-lines '())
(pass-count 0)
(test-buffer (current-buffer))
cmd-line
@@ -263,10 +279,13 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END
EDIT-BEGIN)")
((string= (match-string 1) "CMD")
(looking-at ".*$")
(setq cmd-line (line-number-at-pos)
- last-cmd (match-string 0))
+ last-cmd (match-string-no-properties 0)
+ force-fail nil)
(let ((msg (format "%s:%d: test %s" (buffer-file-name) cmd-line
last-cmd)))
(when wisi-parser-shared (wisi-parse-log-message
wisi-parser-shared msg))
(message "%s" msg)
+ (when (and (fboundp 'eglot-current-server)
(eglot-current-server))
+ (jsonrpc--debug (eglot-current-server) msg))
(save-excursion
(setq last-result
(condition-case-unless-debug err
@@ -278,12 +297,15 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END
EDIT-BEGIN)")
(message msg)))
((error wisi-parse-error)
(setq error-count (1+ error-count))
+ (push cmd-line error-lines)
(setq msg (concat msg " ... signaled"))
(setq force-fail t)
(when wisi-parser-shared (wisi-parse-log-message
wisi-parser-shared msg))
(message msg)
(setq msg (format "... %s: %s" (car err) (cdr err)))
(when wisi-parser-shared (wisi-parse-log-message
wisi-parser-shared msg))
+ (when (and (fboundp 'eglot-current-server)
(eglot-current-server))
+ (jsonrpc--debug (eglot-current-server) msg))
(message msg)
nil)))
))
@@ -307,6 +329,7 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END
EDIT-BEGIN)")
(message msg))
(setq error-count (1+ error-count))
+ (push (line-number-at-pos) error-lines)
(let ((msg (concat
(format "error: %s:%d:\n" (buffer-file-name)
(line-number-at-pos))
@@ -317,8 +340,7 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END
EDIT-BEGIN)")
last-result
expected-result)))))
(when wisi-parser-shared (wisi-parse-log-message
wisi-parser-shared msg))
- (message "%s" msg))
- (setq force-fail nil)))
+ (message "%s" msg))))
((string= (match-string 1) "RESULT_START")
(looking-at ".*$")
@@ -339,6 +361,7 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END
EDIT-BEGIN)")
((string= (match-string 1) "RESULT_FINISH")
(unless (equal (length expected-result) (length last-result))
(setq error-count (1+ error-count))
+ (push (line-number-at-pos) error-lines)
;; this is used for gpr-query tests, not parser tests,
;; so we don't write to the parser log.
(message
@@ -353,6 +376,7 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END
EDIT-BEGIN)")
(while (< i (length expected-result))
(unless (equal (nth i expected-result) (nth i last-result))
(setq error-count (1+ error-count))
+ (push (line-number-at-pos) error-lines)
(message
(concat
(format "error: %s:%d:\n" (buffer-file-name)
(line-number-at-pos))
@@ -383,6 +407,7 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END
EDIT-BEGIN)")
(t
(setq error-count (1+ error-count))
+ (push (line-number-at-pos) error-lines)
(error (concat "Unexpected EMACS test command " (match-string
1))))))
(let ((msg (format "%s:%d tests passed %d"
@@ -391,6 +416,7 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END
EDIT-BEGIN)")
(message msg))
(when (> error-count 0)
+ (message "errors on lines: %s" error-lines)
(error
"%s:%d: aborting due to previous errors (%d)"
(buffer-file-name) (line-number-at-pos (point)) error-count))
@@ -435,9 +461,9 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END
EDIT-BEGIN)")
(cl-case system-type
(gnu/linux
(list
- (cons 'font "DejaVu Sans Mono-8")
+ (cons 'font "DejaVu Sans Mono-11")
(cons 'width 120) ;; characters; fringe extra
- (cons 'height 94) ;; characters
+ (cons 'height 73) ;; characters
(cons 'left 0)
(cons 'top 0)))
(windows-nt
@@ -462,12 +488,14 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END
EDIT-BEGIN)")
(other-window -1))
(define-key global-map [M-C-up] 'wisi-prev-window)
(define-key global-map [M-C-down] 'other-window)
+(define-key global-map [f11] 'switch-to-buffer)
(defun run-test (file-name)
"Run an indentation and casing test on FILE-NAME."
(interactive "f")
(setq-default indent-tabs-mode nil) ;; no tab chars in files
+ (setq message-log-max most-positive-fixnum)
;; we'd like to run emacs from a makefile as:
;;
@@ -483,12 +511,7 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END
EDIT-BEGIN)")
;;
;; emacs -Q -l runtest.el --eval '(progn (run-test
"<filename>")(kill-emacs))'
;;
- ;; Then we have problems with font lock defaulting to jit-lock; that
- ;; screws up font-lock tests because the test runs before jit-lock
- ;; does. This forces default font-lock, which fontifies the whole
- ;; buffer when (font-lock-fontify-buffer) is called, which tests
- ;; that rely on font-lock do explicitly.
- (setq font-lock-support-mode nil)
+ ;; Then we must use (font-lock-ensure) to force immediate fontification.
(setq xref-prompt-for-identifier nil)
diff --git a/wisi-skel.el b/wisi-skel.el
index dacbc6c433..79e9a65a12 100644
--- a/wisi-skel.el
+++ b/wisi-skel.el
@@ -78,7 +78,8 @@ separated by `|', with trailing `...' if there are more keys."
)
(defun wisi-skel-enable-parse ()
- (setq wisi-inhibit-parse nil));
+ (setq wisi-inhibit-parse nil)
+ (remove-hook 'skeleton-end-hook #'wisi-skel-enable-parse t));
(defun wisi-skel-expand (&optional name)
"Expand the token or placeholder before point to a skeleton.
@@ -106,6 +107,8 @@ before that as the token."
(skel (assoc-string token wisi-skel-token-alist))
(handled nil))
+ (add-hook 'skeleton-end-hook #'wisi-skel-enable-parse 90 t)
+
(if skel
(progn
(when (listp (cdr skel))
@@ -193,8 +196,5 @@ before that as the token."
(interactive)
(skip-syntax-backward "^!"))
-;;;###autoload
-(add-hook 'skeleton-end-hook #'wisi-skel-enable-parse 90)
-
(provide 'wisi-skel)
;;; wisi-skel.el ends here
diff --git a/wisi.el b/wisi.el
index c67c353749..ff517456a6 100644
--- a/wisi.el
+++ b/wisi.el
@@ -1,13 +1,13 @@
;;; wisi.el --- Utilities for implementing an indentation/navigation engine
using a generalized LR parser -*- lexical-binding:t -*-
;;
-;; Copyright (C) 2012 - 2022 Free Software Foundation, Inc.
+;; Copyright (C) 2012 - 2023 Free Software Foundation, Inc.
;;
;; Author: Stephen Leake <stephen_leake@stephe-leake.org>
;; Maintainer: Stephen Leake <stephen_leake@stephe-leake.org>
;; Keywords: parser
;; indentation
;; navigation
-;; Version: 4.1.1
+;; Version: 4.2.0
;; package-requires: ((emacs "25.3") (seq "2.20"))
;; URL: https://stephe-leake.org/ada/wisitoken.html
;;
@@ -142,35 +142,51 @@ Increasing this will give better results when in the
middle of a
deeply nested statement, but worse in some situations."
:type 'integer
:safe #'integerp)
+(make-variable-buffer-local 'wisi-indent-context-lines)
-(defcustom wisi-disable-face nil
- "When non-nil, `wisi-setup' does not enable use of parser for font-lock.
-Useful when debugging parser or parser actions."
+(defcustom wisi-disable-completion nil
+ "When non-nil, `wisi-setup' does not enable use of wisi xref for completion.
+Useful when using wisi in parallel with eglot."
:type 'boolean
:safe #'booleanp)
+(make-variable-buffer-local 'wisi-disable-completion)
-(defcustom wisi-disable-completion nil
- "When non-nil, `wisi-setup' does not enable use of wisi xref for completion
+(defcustom wisi-disable-diagnostics nil
+ "When non-nil, `wisi-setup' does not enable reporting diagnostics.
Useful when using wisi in parallel with eglot."
:type 'boolean
:safe #'booleanp)
+(make-variable-buffer-local 'wisi-disable-diagnostics)
+
+(defcustom wisi-disable-face nil
+ "When non-nil, `wisi-setup' does not enable use of parser for font-lock."
+ :type 'boolean
+ :safe #'booleanp)
+(make-variable-buffer-local 'wisi-disable-face)
(defcustom wisi-disable-indent nil
- "When non-nil, `wisi-setup' does not enable use of parser for indent.
-Useful when using wisi in parallel with eglot."
+ "When non-nil, `wisi-setup' does not enable use of parser for indent."
:type 'boolean
:safe #'booleanp)
+(make-variable-buffer-local 'wisi-disable-indent)
(defcustom wisi-disable-parser nil
- "When non-nil, `wisi-setup' does not enable use of parser for any purpose.
-Useful when using wisi in parallel with eglot."
+ "When non-nil, `wisi-setup' does not enable use of parser for any purpose."
+ :type 'boolean
+ :safe #'booleanp)
+(make-variable-buffer-local 'wisi-disable-parser)
+
+(defcustom wisi-disable-statement nil
+ "When non-nil, the wisi parser should not be enabled for statement motion."
:type 'boolean
:safe #'booleanp)
+(make-variable-buffer-local 'wisi-disable-statement)
(defcustom wisi-parse-full-background t
"If non-nil, do initial full parse in background."
:type 'boolean
:safe #'booleanp)
+(make-variable-buffer-local 'wisi-parse-full-background)
(defconst wisi-error-buffer-name "*wisi syntax errors*"
"Name of buffer for displaying syntax errors.")
@@ -859,14 +875,13 @@ Run the parser first if needed."
(wisi-set-last-parse-region begin parse-end parse-action)
- (unless (eq parse-action 'face)
- (when (buffer-live-p wisi-error-buffer)
- (with-current-buffer wisi-error-buffer
- (setq buffer-read-only nil)
- (erase-buffer)
- (setq buffer-read-only t)
- (when (get-buffer-window wisi-error-buffer)
- (delete-window (get-buffer-window wisi-error-buffer))))))
+ (when (buffer-live-p wisi-error-buffer)
+ (with-current-buffer wisi-error-buffer
+ (setq buffer-read-only nil)
+ (erase-buffer)
+ (setq buffer-read-only t)
+ (when (get-buffer-window wisi-error-buffer)
+ (delete-window (get-buffer-window wisi-error-buffer)))))
(condition-case err
(save-excursion
@@ -898,10 +913,7 @@ Run the parser first if needed."
(wisi-parse-error
(cl-ecase parse-action
(face
- ;; Caches set by failed elisp parse are ok, but some parse
- ;; failures return 'nil' in parse-region.
- (when (cdr parsed-region)
- (wisi--delete-face-cache (cdr parsed-region))))
+ (wisi--delete-face-cache (car parsed-region)))
(navigate
;; don't trust parse result
@@ -956,7 +968,7 @@ Run the parser first if needed."
(defun wisi-validate-cache (begin end error-on-fail parse-action)
"Ensure cached data for PARSE-ACTION is valid in region BEGIN END"
- ;; Tolerate (point) +- size exceeding buffer limits.
+ ;; Tolerate (point) +- size exeeding buffer limits.
(setq begin (max begin (point-min)))
(setq end (min end (point-max)))
@@ -1044,8 +1056,8 @@ fails."
(wisi-validate-cache parse-begin parse-end error-on-fail parse-action)))
-(defun wisi-fontify-region (begin end)
- "For `jit-lock-functions'."
+(defun wisi-fontify-region (begin end &optional _contextual)
+ "For `jit-lock-register'."
(remove-text-properties begin end '(font-lock-face nil))
(if wisi-parse-full-active
@@ -1220,7 +1232,7 @@ Return start cache."
(defun wisi-goto-statement-start ()
"Move point to token at start of statement point is in or after.
-Return start cache."
+Return start cache (nil if point is before first statement)."
(interactive)
(wisi-validate-cache-current-statement t 'navigate)
(wisi-goto-start (or (wisi-get-cache (point))
@@ -1818,7 +1830,11 @@ with incremental parse after each key event."
"Set up a buffer for parsing files with wisi."
;; wisi-disable-* should be set in a find-file-hook such as
;; ada-eglot-setup, not in local variables.
- (when (and (not wisi-disable-parser) parser)
+ (when (and (not wisi-disable-parser)
+ parser
+ ;; indirect buffers handled below.
+ ;; We don't insist on (null wisi-parser-shared), so we can re-run
ada-mode
+ )
(setq wisi-parser-shared parser)
(setq wisi-parser-local (make-wisi-parser-local))
@@ -1850,7 +1866,14 @@ with incremental parse after each key event."
(add-hook 'kill-buffer-hook #'wisi-parse-kill-buf 90 t)
+ (when (not wisi-disable-completion)
+ (add-hook 'completion-at-point-functions #'wisi-completion-at-point -90
t))
+
+ ;; wisi-disable-diagnostics is handled in wisi-process-parse.el
+
(when (not wisi-disable-face)
+ ;; font-lock complains about not working in indirect buffers,
+ ;; but we need to set all the local variables for mmm-mode.
(jit-lock-register #'wisi-fontify-region))
(when (not wisi-disable-indent)
@@ -1858,8 +1881,8 @@ with incremental parse after each key event."
(setq-local indent-region-function #'wisi-indent-region)
(setq-local comment-indent-function #'wisi-comment-indent))
- (when (not wisi-disable-completion) ;; FIXME; check that (wisi-prj-xref
prj) is valid?
- (add-hook 'completion-at-point-functions #'wisi-completion-at-point -90
t))
+ ;; wisi-disable-statement just affects whether to start the
+ ;; parser.
(setq-local forward-sexp-function #'wisi-forward-sexp)
@@ -1867,11 +1890,19 @@ with incremental parse after each key event."
(when wisi-save-all-changes
(setf (wisi-parser-local-all-changes wisi-parser-local) nil))
- ;; We don't wait for this to complete here, so users can scroll
- ;; around while the initial parse runs. font-lock will not work
- ;; during that time (the parser is busy, the buffer is read-only).
- (when (< 0 wisi-debug) (message "start initial full parse in %s"
(current-buffer)))
- (wisi-parse-incremental wisi-parser-shared 'none :full t :nowait
wisi-parse-full-background)
+ (unless (buffer-base-buffer)
+ ;; If are in an indirect buffer (ie mmm-temp-buffer), We need
+ ;; to set all the local variables above, but _not_ start a
+ ;; parse; that would duplicate and conflict with the parse in
+ ;; the main buffer.
+
+ ;; We don't wait for this to complete here, so users can scroll
+ ;; around while the initial parse runs. font-lock will not work
+ ;; during that time (the parser is busy, the buffer is read-only).
+ (when (< 0 wisi-debug) (message "starting initial full parse; parser %s
buffer %s"
+ (wisi-process--parser-label parser)
+ (current-buffer)))
+ (wisi-parse-incremental wisi-parser-shared 'none :full t :nowait
wisi-parse-full-background))
(when wisi-save-text-tree
(wisi-parse-save-text-tree-auto wisi-parser-shared t))
diff --git a/wisi.texi b/wisi.texi
index 29c8e79ff1..9949c5b1e1 100644
--- a/wisi.texi
+++ b/wisi.texi
@@ -2,7 +2,7 @@
@settitle Wisi
@copying
-Copyright @copyright{} 1999 - 2022 Free Software Foundation, Inc.
+Copyright @copyright{} 1999 - 2023 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -25,7 +25,7 @@ developing GNU and promoting software freedom.''
@titlepage
@sp 10
-@title Wisi Version 4.1.1
+@title Wisi Version 4.2.0
@page
@vskip 0pt plus 1filll
@insertcopying
@@ -37,7 +37,7 @@ developing GNU and promoting software freedom.''
@node Top
@top Top
-Wisi Version 4.1.1
+Wisi Version 4.2.0
@end ifnottex
@menu
@@ -231,7 +231,7 @@ some other purpose. It is good style to indicate the
purpose in a
comment.
For example, ada-mode uses a 'misc' property on left parentheses that
-start a subprogram parameter list; this distinguishes them from other
+start a subprogram parameter list; this distinquishes them from other
left parentheses, and makes it possible to automatically call
@code{ada-format-paramlist} to format the
parameter list, instead of using the standard Emacs @code{align}.
@@ -338,7 +338,7 @@ Indent for comments are computed in the same way, except
that the
delta that applies to a comment that follows a token is given by the
indent action entry for the next token. If a token is the last in a
production, the comment indent is @code{nil}. These rules often give
-the wrong indent for a comment, so they can be overridden by specifying
+the wrong indent for a comment, so they can be overridden by specifing
a comment indent for a token using @code{[CODE-INDENT
COMMENT-INDENT]}; see below. Indent functions can also modify how
comments are indented.
@@ -517,7 +517,7 @@ expression_list : expression | expression_list ','
expression
statements : statement | statements statement
-statement : function_call ';' | assignment | if_statment
+statement : function_call ';' | assigment | if_statment
assign_value : ':=' expression
diff --git a/wisitoken-bnf-generate.adb b/wisitoken-bnf-generate.adb
index b401e8e523..9c45c28e41 100644
--- a/wisitoken-bnf-generate.adb
+++ b/wisitoken-bnf-generate.adb
@@ -3,7 +3,7 @@
-- Parser for Wisi grammar files, producing Ada source
-- files for a parser.
--
--- Copyright (C) 2012 - 2015, 2017 - 2022 Free Software Foundation, Inc.
+-- Copyright (C) 2012 - 2015, 2017 - 2023 Free Software Foundation, Inc.
--
-- The WisiToken package is free software; you can redistribute it
-- and/or modify it under terms of the GNU General Public License as
@@ -29,7 +29,6 @@ with Ada.Strings.Maps;
with Ada.Strings.Unbounded;
with Ada.Text_IO;
with GNAT.Traceback.Symbolic;
-with System.Multiprocessors;
with WisiToken.BNF.Generate_Utils;
with WisiToken.BNF.Output_Ada;
with WisiToken.BNF.Output_Ada_Common;
@@ -55,7 +54,7 @@ is
use Ada.Text_IO;
First : Boolean := True;
begin
- Put_Line (Standard_Error, "version 4.0"); -- matches release version in
Docs/wisitoken.html
+ Put_Line (Standard_Error, "version 4.1"); -- matches release version in
Docs/wisitoken.html
Put_Line (Standard_Error, "wisitoken-bnf-generate [options] {wisi
grammar file}");
Put_Line (Standard_Error, "Generate source code implementing a parser
for the grammar.");
New_Line (Standard_Error);
@@ -121,9 +120,6 @@ is
Put_Line (Standard_Error, " --ignore_conflicts; ignore excess/unknown
conflicts");
Put_Line (Standard_Error,
" --test_main; generate standalone main program for running
the generated parser, modify file names");
- Put_Line (Standard_Error,
- " --task_count n; number of tasks used to compute LR1 items;
0 means CPU count." &
- " Default 1.");
Put_Line (Standard_Error, "verbosity keys:");
Enable_Trace_Help;
end Put_Usage;
@@ -134,8 +130,6 @@ is
Output_BNF : Boolean := False;
Ignore_Conflicts : Boolean := False;
Test_Main : Boolean := False;
- Generate_Task_Count : System.Multiprocessors.CPU_Range := 1;
- Generate_Task_Count_Set : Boolean := False;
Command_Generate_Set : Generate_Set_Access; -- override grammar file
declarations
@@ -250,19 +244,6 @@ begin
Suffix := +Argument (Arg_Next);
Arg_Next := Arg_Next + 1;
- elsif Argument (Arg_Next) = "--task_count" then
- Arg_Next := @ + 1;
- Generate_Task_Count_Set := True;
- declare
- use System.Multiprocessors;
- begin
- Generate_Task_Count := CPU_Range'Value (Argument (Arg_Next));
- if Generate_Task_Count = 0 then
- Generate_Task_Count := Number_Of_CPUs;
- end if;
- end;
- Arg_Next := @ + 1;
-
elsif Argument (Arg_Next) = "--test_main" then
Arg_Next := Arg_Next + 1;
Test_Main := True;
@@ -522,10 +503,6 @@ begin
Parser => Tuple.Gen_Alg,
Phase => WisiToken_Grammar_Runtime.Other);
- if not Generate_Task_Count_Set then
- Generate_Task_Count := System.Multiprocessors.Number_Of_CPUs;
- end if;
-
declare
use all type WisiToken.Parse.LR.Parse_Table_Ptr;
use Ada.Real_Time;
@@ -548,9 +525,6 @@ begin
Parse_Table_File_Name : constant String :=
(if Tuple.Gen_Alg in LALR .. Packrat_Proc
then -Output_File_Name_Root & "_" & To_Lower
(Tuple.Gen_Alg'Image) &
- (if Tuple.Gen_Alg = LR1 and Test_Main
- then "_t" & Ada.Strings.Fixed.Trim
(Generate_Task_Count'Image, Ada.Strings.Both)
- else "") &
(if Input_Data.If_Lexer_Present
then "_" & Lexer_Image (Input_Data.User_Lexer).all
else "") &
@@ -651,7 +625,6 @@ begin
Include_Extra => Test_Main,
Ignore_Conflicts => Ignore_Conflicts,
Recursion_Strategy =>
Input_Data.Language_Params.Recursion_Strategy,
- Task_Count => Generate_Task_Count,
Use_Cached_Recursions => not
(Input_Data.If_Lexer_Present or Input_Data.If_Parser_Present),
Recursions => Cached_Recursions);
@@ -713,8 +686,7 @@ begin
if Tuple.Text_Rep then
WisiToken.Generate.LR.Put_Text_Rep
(Generate_Data.LR_Parse_Table.all,
- Text_Rep_File_Name
- (-Output_File_Name_Root, Tuple, Generate_Task_Count,
Input_Data.If_Lexer_Present, Test_Main));
+ Text_Rep_File_Name (-Output_File_Name_Root, Tuple,
Input_Data.If_Lexer_Present));
end if;
when others =>
@@ -729,7 +701,7 @@ begin
WisiToken.BNF.Output_Ada
(Input_Data, Grammar_Parser.Tree.Lexer.File_Name,
-Output_File_Name_Root, Generate_Data,
- Packrat_Data, Tuple, Test_Main, Multiple_Tuples,
Generate_Task_Count);
+ Packrat_Data, Tuple, Test_Main, Multiple_Tuples);
when Ada_Emacs_Lang =>
if Trace_Generate > Outline then
diff --git a/wisitoken-bnf-output_ada.adb b/wisitoken-bnf-output_ada.adb
index bf30759c27..6069c84291 100644
--- a/wisitoken-bnf-output_ada.adb
+++ b/wisitoken-bnf-output_ada.adb
@@ -23,7 +23,6 @@ pragma License (Modified_GPL);
with Ada.Strings.Fixed;
with Ada.Text_IO; use Ada.Text_IO;
with GNAT.Regexp;
-with System.Multiprocessors;
with WisiToken.BNF.Generate_Packrat;
with WisiToken.BNF.Generate_Utils;
with WisiToken.BNF.Output_Ada_Common; use WisiToken.BNF.Output_Ada_Common;
@@ -37,18 +36,14 @@ procedure WisiToken.BNF.Output_Ada
Packrat_Data : in WisiToken.Generate.Packrat.Data;
Tuple : in Generate_Tuple;
Test_Main : in Boolean;
- Multiple_Tuples : in Boolean;
- Generate_Task_Count : in System.Multiprocessors.CPU_Range)
+ Multiple_Tuples : in Boolean)
is
Common_Data : Output_Ada_Common.Common_Data :=
WisiToken.BNF.Output_Ada_Common.Initialize
(Input_Data, Tuple, Grammar_File_Name, Output_File_Name_Root,
Check_Interface => False);
Gen_Alg_Name : constant String :=
(if Test_Main or Multiple_Tuples
- then "_" & Generate_Algorithm_Image (Common_Data.Generate_Algorithm).all
&
- (if Common_Data.Generate_Algorithm = LR1
- then "_t" & Ada.Strings.Fixed.Trim (Generate_Task_Count'Image,
Ada.Strings.Both)
- else "")
+ then "_" & Generate_Algorithm_Image (Common_Data.Generate_Algorithm).all
else "");
function Symbol_Regexp (Item : in String) return String
@@ -436,8 +431,7 @@ is
if Common_Data.Text_Rep then
Put_Line
(" """ &
- Text_Rep_File_Name
- (Output_File_Name_Root, Tuple, Generate_Task_Count,
Input_Data.If_Lexer_Present, Test_Main) & """,");
+ Text_Rep_File_Name (Output_File_Name_Root, Tuple,
Input_Data.If_Lexer_Present) & """,");
end if;
if Input_Data.Language_Params.Error_Recover then
if Input_Data.Language_Params.Use_Language_Runtime then
diff --git a/wisitoken-bnf.adb b/wisitoken-bnf.adb
index c5157ebf59..ee98bf4dbf 100644
--- a/wisitoken-bnf.adb
+++ b/wisitoken-bnf.adb
@@ -21,6 +21,7 @@ pragma License (GPL);
with Ada.Command_Line;
with Ada.Directories;
with Ada.Environment_Variables;
+with Ada.Strings.Fixed;
with Ada.Text_IO;
package body WisiToken.BNF is
diff --git a/wisitoken-bnf.ads b/wisitoken-bnf.ads
index d5c9dc73a7..5275e2cc95 100644
--- a/wisitoken-bnf.ads
+++ b/wisitoken-bnf.ads
@@ -31,10 +31,8 @@ with Ada.Containers.Doubly_Linked_Lists;
with Ada.Containers.Indefinite_Doubly_Linked_Lists;
with Ada.Containers.Ordered_Maps;
with Ada.Containers.Vectors;
-with Ada.Strings.Fixed;
with Ada.Strings.Unbounded;
with Ada.Unchecked_Deallocation;
-with System.Multiprocessors;
with WisiToken.Parse.LR;
with WisiToken.Syntax_Trees;
package WisiToken.BNF is
@@ -129,17 +127,12 @@ package WisiToken.BNF is
Tuple : in Generate_Tuple);
function Text_Rep_File_Name
- (File_Name_Root : in String;
- Tuple : in Generate_Tuple;
- Generate_Task_Count : in System.Multiprocessors.CPU_Range;
- If_Lexer_Present : in Boolean;
- Test_Main : in Boolean)
+ (File_Name_Root : in String;
+ Tuple : in Generate_Tuple;
+ If_Lexer_Present : in Boolean)
return String
is (File_Name_Root & "_" &
Ada.Characters.Handling.To_Lower (Generate_Algorithm_Image
(Tuple.Gen_Alg).all) &
- (if Tuple.Gen_Alg = LR1 and Test_Main
- then "_t" & Ada.Strings.Fixed.Trim (Generate_Task_Count'Image,
Ada.Strings.Both)
- else "") &
(if If_Lexer_Present
then "_" & Lexer_Image (Tuple.Lexer).all
else "") &
diff --git a/wisitoken-generate-lr-lr1_generate.adb
b/wisitoken-generate-lr-lr1_generate.adb
index 016baa9284..2226fc2d25 100644
--- a/wisitoken-generate-lr-lr1_generate.adb
+++ b/wisitoken-generate-lr-lr1_generate.adb
@@ -22,9 +22,8 @@ pragma License (Modified_GPL);
with Ada.Calendar;
with Ada.Containers;
-with Ada.Exceptions;
with Ada.Text_IO;
-with System.Address_To_Access_Conversions;
+with WisiToken.Generate.LR1_Items;
package body WisiToken.Generate.LR.LR1_Generate is
function LR1_Goto_Transitions
@@ -68,7 +67,7 @@ package body WisiToken.Generate.LR.LR1_Generate is
return Closure (Goto_Set, Has_Empty_Production, First_Terminal_Sequence,
Grammar, Descriptor);
end LR1_Goto_Transitions;
- function LR1_Item_Sets_Single
+ function LR1_Item_Sets
(Has_Empty_Production : in Token_ID_Set;
First_Terminal_Sequence : in Token_Sequence_Arrays.Vector;
Grammar : in WisiToken.Productions.Prod_Arrays.Vector;
@@ -197,618 +196,7 @@ package body WisiToken.Generate.LR.LR1_Generate is
end if;
return C;
- end LR1_Item_Sets_Single;
-
- function LR1_Item_Sets_Parallel
- (Has_Empty_Production : in Token_ID_Set;
- First_Terminal_Sequence : in Token_Sequence_Arrays.Vector;
- Grammar : in WisiToken.Productions.Prod_Arrays.Vector;
- Descriptor : in WisiToken.Descriptor;
- Task_Count : in System.Multiprocessors.CPU_Range;
- Hash_Table_Size : in Positive :=
LR1_Items.Item_Set_Trees.Default_Rows)
- return LR1_Items.Item_Set_List
- is
- use LR1_Items;
- use all type Ada.Containers.Count_Type;
- use all type SAL.Base_Peek_Type;
- use all type System.Multiprocessors.CPU_Range;
-
- -- [dragon] algorithm 4.9 pg 231; figure 4.38 pg 232; procedure
- -- "items", with some optimizations.
-
- type Base_Worker_ID is range 0 .. Positive'Last;
- subtype Worker_ID is Base_Worker_ID range 1 .. Base_Worker_ID'Last;
-
- package Item_Set_Tree_Node_Arrays is new
SAL.Gen_Unbounded_Definite_Vectors
- (Positive, Item_Set_Tree_Node, (others => <>));
-
- package Worker_Array_State_Index_Arrays is new
SAL.Gen_Unbounded_Definite_Vectors
- (Worker_ID, State_Index_Arrays.Vector,
State_Index_Arrays.Empty_Vector);
-
- type Worker_Data is record
- -- All data produced by one worker from one state, except New_C,
- -- which doesn't need to be split by supervisor state.
- From_State : State_Index := State_Index'Last;
- New_States : State_Index_Arrays.Vector;
- Existing_Goto_Items : Goto_Item_Arrays.Vector;
- New_Goto_Items : Goto_Item_Arrays.Vector;
- end record;
-
- package State_Array_Worker_Data is new SAL.Gen_Unbounded_Definite_Vectors
- (State_Index, Worker_Data, (others => <>));
-
- protected Supervisor is
-
- procedure Initialize
- (Worker_Count : in LR1_Item_Sets_Parallel.Worker_ID;
- First_Item_Set : in out Item_Set);
-
- entry Get
- (Worker_ID : in LR1_Item_Sets_Parallel.Worker_ID;
- Sets_To_Check : out Item_Set_List;
- Keys_To_Store : out Item_Set_Tree_Node_Arrays.Vector)
- with Pre => Sets_To_Check.Is_Empty and Keys_To_Store.Is_Empty;
- -- Set Sets_To_Check to new states to check, _not_ indexed by state;
- -- they may be discontinuous. Available when there are states to
- -- check, or when all states have been checked and all workers are
- -- inactive; then Sets_To_Check is empty.
- --
- -- If Sets_To_Check is not empty, Keys_To_Store contains keys from
- -- other workers to store in worker's C_Tree; increment active worker
- -- count.
-
- procedure Update
- (Worker_ID : in LR1_Item_Sets_Parallel.Worker_ID;
- New_C : in out Item_Set_Arrays.Vector;
- Worker_Data : in out State_Array_Worker_Data.Vector);
- -- New_C: New states found by worker, indexed by worker new state
- -- number (1 origin); add to supervisor C. States are updated to
supervisor
- -- state numbers; worker should add those to worker's C_Tree.
- --
- -- Worker_Data : Indexed by supervisor state number I. Contains:
- --
- -- New_States: Worker new state numbers for states derived from C
(I);
- -- sets are in New_C.
- --
- -- Existing_Goto_Items: Gotos from C (I) to some state in
supervisor
- -- C (which worker found in C_Tree); add to supervisor C (I).
- --
- -- New_Goto_Items: From C (I) to some state in New_C (given by
- -- worker new state number). Add to supervisor C (I).
- --
- -- Decrement active worker count.
-
- procedure Fatal_Error
- (Exception_ID : in Ada.Exceptions.Exception_Id;
- Message : in String);
- -- Worker encountered an exception; record it for Done, decrement
- -- active worker count.
-
- entry Done
- (ID : out Ada.Exceptions.Exception_Id;
- Message : out Ada.Strings.Unbounded.Unbounded_String);
- -- Available when all states have been checked, and all workers
- -- inactive.
-
- function Get_C return Item_Set_List;
-
- private
- C : Item_Set_List; -- result
- C_Tree : Item_Set_Tree; -- for fast find
- States_To_Check : State_Index_Queues.Queue;
- -- [dragon] specifies 'until no more items can be added', but we use
- -- a queue to avoid checking unecessary states. Ada LR1 has over
- -- 100,000 states, so this is a significant gain (reduced time from
- -- 600 seconds to 40).
-
- Worker_Count : LR1_Item_Sets_Parallel.Worker_ID;
- Active_Workers : Natural := 0;
- Fatal : Boolean := False;
-
- New_States_For_Worker : Worker_Array_State_Index_Arrays.Vector;
- -- Indexed by worker ID
-
- Error_ID : Ada.Exceptions.Exception_Id :=
Ada.Exceptions.Null_Id;
- Error_Message : Ada.Strings.Unbounded.Unbounded_String;
-
- Min_States_Get : SAL.Peek_Type := 10;
-
- Net_Time : Duration := 0.0; -- Time spent in Get,
Update.
- Found_States : Integer := 0; -- States found in Update;
counts duplicate states found by workers
- Summary_Last_Output : State_Index := 0;
- end Supervisor;
-
- function Image (Node_Ref : Item_Set_Trees.Variable_Reference_Type)
return String
- is
- package Convert is new System.Address_To_Access_Conversions
(Item_Set_Tree_Node);
- begin
- return Convert.To_Address (Convert.Object_Pointer (Node_Ref))'Image &
":" &
- Node_Ref.Hash'Image & ":" & Node_Ref.State'Image;
- end Image;
-
- protected body Supervisor is
-
- procedure Initialize
- (Worker_Count : in LR1_Item_Sets_Parallel.Worker_ID;
- First_Item_Set : in out Item_Set)
- is
- First_State_Index : constant State_Index :=
First_Item_Set.Tree_Node.State;
- begin
- Supervisor.Worker_Count := Worker_Count;
-
- New_States_For_Worker.Set_First_Last (1, Worker_Count);
-
- C.Set_First_Last (First_State_Index, First_State_Index - 1);
- C_Tree.Set_Rows (Hash_Table_Size);
-
- First_Item_Set.Dot_IDs := Get_Dot_IDs (Grammar,
First_Item_Set.Set, Descriptor);
- Compute_Key_Hash (First_Item_Set, C_Tree.Rows, Grammar,
Descriptor, True);
-
- C.Append (First_Item_Set);
- C_Tree.Insert (First_Item_Set.Tree_Node, Duplicate => SAL.Error);
-
- States_To_Check.Put (First_State_Index);
- end Initialize;
-
- entry Get
- (Worker_ID : in LR1_Item_Sets_Parallel.Worker_ID;
- Sets_To_Check : out Item_Set_List;
- Keys_To_Store : out Item_Set_Tree_Node_Arrays.Vector)
- when Fatal or States_To_Check.Length > 0 or Active_Workers = 0
- is
- use all type Ada.Calendar.Time;
-
- Time_Start : constant Ada.Calendar.Time := Ada.Calendar.Clock;
- begin
- if States_To_Check.Length > 0 then
- for I in 1 ..
- (if States_To_Check.Length / SAL.Peek_Type (Worker_Count) <
Min_States_Get
- then States_To_Check.Length
- else States_To_Check.Length / SAL.Peek_Type (Worker_Count))
- loop
- Sets_To_Check.Append (C (States_To_Check.Get));
- end loop;
-
- if not New_States_For_Worker (Worker_ID).Is_Empty then
- Keys_To_Store.Set_Capacity
- (New_States_For_Worker (Worker_ID).First_Index,
New_States_For_Worker (Worker_ID).Last_Index);
- for State of New_States_For_Worker (Worker_ID) loop
- pragma Assert (C (State).Tree_Node.State = State);
- Keys_To_Store.Append (C (State).Tree_Node);
- end loop;
- New_States_For_Worker (Worker_ID).Clear;
- end if;
-
- if Trace_Generate_Table > Detail then
- Ada.Text_IO.Put
- ("(worker" & Worker_ID'Image & ") Checking" &
Sets_To_Check.Length'Image & " states");
- for Set of Sets_To_Check loop
- Ada.Text_IO.Put (Set.Tree_Node.State'Image);
- end loop;
- Ada.Text_IO.New_Line;
- if Trace_Generate_Table > Extra then
- for Set of Sets_To_Check loop
- Put (Grammar, Descriptor, Set, Show_Lookaheads =>
False, Kernel_Only => True);
- end loop;
- end if;
-
- Ada.Text_IO.Put
- ("(worker" & Worker_ID'Image & ") storing" &
Keys_To_Store.Length'Image & " states");
- for Node of Keys_To_Store loop
- Ada.Text_IO.Put (Node.State'Image);
- end loop;
- Ada.Text_IO.New_Line;
- end if;
-
- Active_Workers := @ + 1;
-
- Net_Time := @ + (Ada.Calendar.Clock - Time_Start);
- end if;
-
- if Trace_Time and C.Last_Index > Summary_Last_Output +
- (if C_Tree.Rows < 15_053 then 500 else 10_000) -- 500 for
ada_lite.wy, 10_000 for ada.wy
- then
- Ada.Text_IO.Put_Line
- ("(super) time:" & Net_Time'Image &
- " states:" & C.Last_Index'Image &
- " States_To_Check:" & States_To_Check.Length'Image &
- " Found_States:" & Found_States'Image);
- Summary_Last_Output := C.Last_Index;
- end if;
- end Get;
-
- procedure Update
- (Worker_ID : in LR1_Item_Sets_Parallel.Worker_ID;
- New_C : in out Item_Set_Arrays.Vector;
- Worker_Data : in out State_Array_Worker_Data.Vector)
- is
- use all type Ada.Calendar.Time;
- Time_Start : constant Ada.Calendar.Time := Ada.Calendar.Clock;
-
- State_Map : array (New_C.First_Index .. New_C.Last_Index) of
State_Index;
- -- Indexed by worker new state number, contains super state number
- begin
- if Trace_Generate_Table > Detail then
- Ada.Text_IO.Put ("(super) Update from worker" & Worker_ID'Image
& "; new states:");
- for Data of Worker_Data loop
- for Node of Data.New_Goto_Items loop
- Ada.Text_IO.Put
- (Data.From_State'Image & "." & Image (Node.Symbol,
Descriptor) & "." &
- Trimmed_Image (Node.State));
- end loop;
- Ada.Text_IO.Put (" | ");
- end loop;
- Ada.Text_IO.New_Line;
- end if;
-
- for Worker_Data of Update.Worker_Data loop
- for Worker_New_State of Worker_Data.New_States loop
- declare
- use Item_Set_Trees;
-
- Super_New_State : constant State_Index := C.Last_Index +
1;
-
- Found : Boolean;
- Found_Ref : constant
Item_Set_Trees.Variable_Reference_Type := C_Tree.Find_Or_Insert_Var
- (New_C (Worker_New_State).Tree_Node, Found);
- begin
- if Found then
- State_Map (Worker_New_State) := Found_Ref.State;
- Found_States := @ + 1;
- New_C (Worker_New_State).Tree_Node.State :=
Found_Ref.State;
-
- else
- Found_Ref.State := Super_New_State;
- New_C (Worker_New_State).Tree_Node.State :=
Super_New_State;
-
- States_To_Check.Put (Super_New_State);
-
- State_Map (Worker_New_State) := Super_New_State;
-
- C.Append (New_C (Worker_New_State));
- pragma Assert (C.Last_Index = Super_New_State);
-
- for ID in New_States_For_Worker.First_Index ..
New_States_For_Worker.Last_Index loop
- if ID /= Worker_ID then
- New_States_For_Worker (ID).Append
(Super_New_State);
- end if;
- end loop;
-
- if Trace_Generate_Table > Extra then
- Ada.Text_IO.Put_Line
- ("from state" & Worker_Data.From_State'Image &
"." & Trimmed_Image (Worker_New_State));
- Put (Grammar, Descriptor, New_C (Worker_New_State),
- Show_Lookaheads => False,
- Kernel_Only => True);
- end if;
- end if;
- end;
- end loop;
-
- -- Now we have State_Map, we can process the gotos.
- declare
- use Goto_Item_Lists;
- From_State : constant State_Index := Worker_Data.From_State;
- begin
- for Item of Worker_Data.Existing_Goto_Items loop
- if Trace_Generate_Table > Extra and then
- not Has_Element (C (From_State).Goto_List.Find
(Item.Symbol))
- then
- Ada.Text_IO.Put_Line
- (" state" & From_State'Image & " adding goto on "
&
- Image (Item.Symbol, Descriptor) & " to existing
state" & Item.State'Image);
- end if;
-
- C (From_State).Goto_List.Insert (Item, Duplicate =>
SAL.Ignore);
- end loop;
-
- for Item of Worker_Data.New_Goto_Items loop
- Item.State := State_Map (Item.State);
-
- if Trace_Generate_Table > Extra and then
- not Goto_Item_Lists.Has_Element
- (C (From_State).Goto_List.Find (Item.Symbol))
- then
- Ada.Text_IO.Put_Line
- (" state" & From_State'Image & " adding goto on "
&
- Image (Item.Symbol, Descriptor) & " to new state"
& Item.State'Image);
- end if;
-
- C (From_State).Goto_List.Insert (Item, Duplicate =>
SAL.Ignore);
- end loop;
- end;
- end loop;
-
- Active_Workers := @ - 1;
-
- Net_Time := @ + (Ada.Calendar.Clock - Time_Start);
- exception
- when E : others =>
-
- Active_Workers := @ - 1;
- Fatal := True;
- States_To_Check.Clear; -- force an early end.
- declare
- use Ada.Text_IO;
- use Ada.Exceptions;
- begin
- Error_ID := Exception_Identity (E);
- Error_Message := +Exception_Message (E);
- Put_Line
- (Standard_Error, "(super) Update exception: " &
Exception_Name (E) & ": " & Exception_Message (E));
- end;
- end Update;
-
- procedure Fatal_Error
- (Exception_ID : in Ada.Exceptions.Exception_Id;
- Message : in String)
- is begin
- Supervisor.Error_ID := Exception_ID;
- Supervisor.Error_Message := +Message;
-
- States_To_Check.Clear; -- force an early end.
- Fatal := True;
- Active_Workers := @ - 1;
- end Fatal_Error;
-
- entry Done
- (ID : out Ada.Exceptions.Exception_Id;
- Message : out Ada.Strings.Unbounded.Unbounded_String)
- when Fatal or (Active_Workers = 0 and States_To_Check.Is_Empty)
- is begin
- if Trace_Time then
- Ada.Text_IO.Put_Line
- ("(super) net time:" & Net_Time'Image &
- " states:" & C.Last_Index'Image &
- " States_To_Check:" & States_To_Check.Length'Image &
- " Found_States:" & Found_States'Image);
- end if;
-
- ID := Supervisor.Error_ID;
- Message := Supervisor.Error_Message;
- end Done;
-
- function Get_C return Item_Set_List
- is begin
- return C;
- end Get_C;
-
- end Supervisor;
-
- task type Worker_Task
- is
- entry Start (ID : in LR1_Item_Sets_Parallel.Worker_ID);
- -- Start states from Supervisor. Stop when Supervisor returns
- -- Invalid_State_Index;
- end Worker_Task;
-
- task body Worker_Task
- is
- use all type Ada.Calendar.Time;
-
- ID : LR1_Item_Sets_Parallel.Worker_ID;
-
- Time_Start : Ada.Calendar.Time;
- Net_Time : Duration := 0.0; -- Time spent outside Supervisor
- States_Checked : Integer := 0;
- States_Found : Integer := 0;
-
- C_Tree : Item_Set_Tree; -- Local copy for fast find
- C : Item_Set_Arrays.Vector; -- Local copy of subset of C to
search; from Supervisor
-
- Local_New_State : State_Index := 1;
-
- -- See Supervisor Get, Update for definitions of these.
- New_C : Item_Set_Arrays.Vector;
- New_C_Tree : Item_Set_Tree;
- Worker_Data : State_Array_Worker_Data.Vector;
-
- procedure Check_State (C_Index : in State_Index)
- is
- C_I : Item_Set renames C (C_Index);
- Worker_Data : LR1_Item_Sets_Parallel.Worker_Data renames
Worker_Task.Worker_Data (C_Index);
- begin
- States_Checked := @ + 1;
- Worker_Data.From_State := C_I.Tree_Node.State;
- Worker_Data.New_States.Clear;
- Worker_Data.Existing_Goto_Items.Clear;
- Worker_Data.New_Goto_Items.Clear;
-
- for Dot_ID_I in C_I.Dot_IDs.First_Index .. C_I.Dot_IDs.Last_Index
loop
- -- [dragon] has 'for each grammar symbol X', but
LR1_Goto_Transitions
- -- rejects Symbol that is not in Dot_IDs, so we iterate over
that.
-
- declare
- Symbol : Token_ID renames C_I.Dot_IDs (Dot_ID_I);
- New_Item_Set : Item_Set := LR1_Goto_Transitions
- (C_I, Symbol, Has_Empty_Production,
First_Terminal_Sequence, Grammar, Descriptor);
- begin
- Compute_Key_Hash (New_Item_Set, C_Tree.Rows, Grammar,
Descriptor, True);
- declare
- use Item_Set_Trees;
-
- -- First search in Worker.C_Tree
- Found_Cur : Cursor := C_Tree.Find
(New_Item_Set.Tree_Node);
-
- Found_State : constant Unknown_State_Index :=
- (if Has_Element (Found_Cur)
- then C_Tree.Constant_Ref (Found_Cur).State
- else Unknown_State);
- begin
- if Found_State = Unknown_State then
- Found_Cur := New_C_Tree.Find (New_Item_Set.Tree_Node);
-
- if Has_Element (Found_Cur) then
- -- Local_New_State was previously generated from
some other state we
- -- are checking.
- Worker_Data.New_Goto_Items.Append ((Symbol,
C_Tree.Constant_Ref (Found_Cur).State));
-
- else
- Worker_Data.New_Goto_Items.Append ((Symbol,
Local_New_State));
-
- New_Item_Set.Tree_Node.State := Local_New_State;
- New_Item_Set.Dot_IDs := Get_Dot_IDs (Grammar,
New_Item_Set.Set, Descriptor);
- New_C.Append (New_Item_Set);
- pragma Assert (New_C.Last_Index = Local_New_State);
- Worker_Data.New_States.Append (Local_New_State);
-
- New_C_Tree.Insert (New_Item_Set.Tree_Node,
Duplicate => SAL.Error);
-
- Local_New_State := Local_New_State + 1;
- end if;
- else
- States_Found := @ + 1;
- pragma Assert (C_I.Goto_List.Count = 0);
- Worker_Data.Existing_Goto_Items.Append ((Symbol,
Found_State));
- if Trace_Generate_Table > Extra then
- Ada.Text_IO.Put_Line
- ("(worker" & ID'Image & ") state" &
Worker_Data.From_State'Image & " adding goto on " &
- Image (Symbol, Descriptor) & " to existing
state" & Image
- (C_Tree.Variable_Ref (Found_Cur)));
- end if;
- end if;
- end;
- end;
- end loop;
- end Check_State;
- begin
- select
- accept Start (ID : in LR1_Item_Sets_Parallel.Worker_ID)
-
- do
- Worker_Task.ID := ID;
- end Start;
- or
- terminate;
- end select;
-
- C_Tree.Set_Rows (Hash_Table_Size);
- New_C_Tree.Set_Rows (Hash_Table_Size);
-
- loop
- declare
- Keys_To_Store : Item_Set_Tree_Node_Arrays.Vector;
- begin
- Supervisor.Get (ID, C, Keys_To_Store);
- exit when C.Length = 0;
-
- Time_Start := Ada.Calendar.Clock;
-
- for Set of C loop
- -- C are all new states to check, but they may
- -- have been in a previous Keys_To_Store.
- C_Tree.Insert (Set.Tree_Node, Duplicate => SAL.Ignore);
- end loop;
- for Node of Keys_To_Store loop
- -- States are added to Keys_To_Store when they are new in
- -- Supervisor.C_Tree, before they are given to any worker
to check;
- -- they may also be in C
- C_Tree.Insert (Node, Duplicate => SAL.Ignore);
- end loop;
- end;
-
- Local_New_State := 1;
- New_C.Set_First_Last (First => Local_New_State, Last =>
Local_New_State - 1);
- New_C_Tree.Clear; -- IMPROVEME: new_c_tree red_black should use
vector store, not allocate each node
-
- Worker_Data.Set_First_Last (C.First_Index, C.Last_Index);
-
- for I in C.First_Index .. C.Last_Index loop
- Check_State (I);
- end loop;
- C.Clear;
-
- Net_Time := @ + (Ada.Calendar.Clock - Time_Start);
- Supervisor.Update (ID, New_C, Worker_Data);
- Time_Start := Ada.Calendar.Clock;
-
- -- New_C.Tree_Node.State updated; insert into C_Tree.
- for Item of New_C loop
- C_Tree.Insert (Item.Tree_Node, Duplicate => SAL.Error);
- end loop;
- Net_Time := @ + (Ada.Calendar.Clock - Time_Start);
- end loop;
-
- if Trace_Time then
- declare
- Elements, Max_Row_Depth, Average_Row_Depth :
Ada.Containers.Count_Type;
- Rows, Empty_Rows : Integer;
- begin
- C_Tree.Sizes (Elements, Rows, Max_Row_Depth, Average_Row_Depth,
Empty_Rows);
-
- Ada.Text_IO.Put_Line
- ("(worker" & ID'Image & ") net time" & Net_Time'Image &
- " states checked:" & States_Checked'Image & " states
found:" & States_Found'Image &
- " hash table states:" & Elements'Image &
- " rows:" & Rows'Image &
- " max_row_depth:" & Max_Row_Depth'Image &
- " average_row_depth:" & Average_Row_Depth'Image &
- " empty_rows:" & Empty_Rows'Image);
- end;
- end if;
-
- if Trace_Generate_Table > Outline then
- Ada.Text_IO.Put_Line ("(worker" & ID'Image & ") terminate");
- end if;
- exception
- when E : others =>
- Supervisor.Fatal_Error (Ada.Exceptions.Exception_Identity (E),
Ada.Exceptions.Exception_Message (E));
- if Trace_Generate_Table > Outline then
- Ada.Text_IO.Put_Line ("(worker" & ID'Image & ") terminate on
exception");
- end if;
- end Worker_Task;
-
- Worker_Tasks : array
- (1 .. System.Multiprocessors.CPU_Range'Min
- (Task_Count,
- System.Multiprocessors.CPU_Range'Max (1,
System.Multiprocessors.Number_Of_CPUs)))
- of Worker_Task;
-
- First_State_Index : constant State_Index := 0;
-
- First_Item_Set : Item_Set := Closure
- ((Set => Item_Lists.To_List
- ((Prod => (Grammar.First_Index, 0),
- Dot => Grammar (Grammar.First_Index).RHSs
(0).Tokens.First_Index,
- Lookaheads => To_Lookahead (Descriptor.EOI_ID))),
- Tree_Node =>
- (State => First_State_Index,
- others => <>),
- others => <>),
- Has_Empty_Production, First_Terminal_Sequence, Grammar, Descriptor);
- begin
- Supervisor.Initialize (LR1_Item_Sets_Parallel.Worker_ID
(Worker_Tasks'Last), First_Item_Set);
-
- if Trace_Generate_Table > Outline then
- Ada.Text_IO.Put_Line (Worker_Tasks'Length'Image & " lr1_items worker
tasks");
- end if;
-
- for I in Worker_Tasks'Range loop
- Worker_Tasks (I).Start (LR1_Item_Sets_Parallel.Worker_ID (I));
- end loop;
-
- declare
- use Ada.Exceptions;
- ID : Exception_Id;
- Message : Ada.Strings.Unbounded.Unbounded_String;
- begin
- Supervisor.Done (ID, Message); -- Wait for all states to be checked
-
- if ID /= Null_Id then
- for I in Worker_Tasks'Range loop
- if not Worker_Tasks (I)'Terminated then
- abort Worker_Tasks (I);
- end if;
- end loop;
- Raise_Exception (ID, -Message);
- else
- if Trace_Generate_Table > Outline then
- Ada.Text_IO.Put_Line ("super reports done");
- end if;
- end if;
- end;
- return Supervisor.Get_C;
- end LR1_Item_Sets_Parallel;
+ end LR1_Item_Sets;
procedure Add_Actions
(Item_Sets : in LR1_Items.Item_Set_List;
@@ -846,13 +234,10 @@ package body WisiToken.Generate.LR.LR1_Generate is
Include_Extra : in Boolean := False;
Ignore_Conflicts : in Boolean := False;
Recursion_Strategy : in WisiToken.Recursion_Strategy := Full;
- Task_Count : in System.Multiprocessors.CPU_Range := 1;
Use_Cached_Recursions : in Boolean := False;
Recursions : in out WisiToken.Generate.Recursions)
return Parse_Table_Ptr
is
- use all type System.Multiprocessors.CPU_Range;
-
Time_Start : constant Ada.Calendar.Time := Ada.Calendar.Clock;
Add_Actions_Time : Ada.Calendar.Time;
Minimal_Actions_Time : Ada.Calendar.Time;
@@ -881,12 +266,8 @@ package body WisiToken.Generate.LR.LR1_Generate is
First_Terminal_Sequence : constant Token_Sequence_Arrays.Vector :=
WisiToken.Generate.To_Terminal_Sequence_Array (First_Nonterm_Set,
Descriptor);
- Item_Sets : constant LR1_Items.Item_Set_List :=
- (if Task_Count = 1
- then LR1_Item_Sets_Single
- (Has_Empty_Production, First_Terminal_Sequence, Grammar, Descriptor)
- else LR1_Item_Sets_Parallel
- (Has_Empty_Production, First_Terminal_Sequence, Grammar,
Descriptor, Task_Count));
+ Item_Sets : constant LR1_Items.Item_Set_List := LR1_Item_Sets
+ (Has_Empty_Production, First_Terminal_Sequence, Grammar,
Descriptor);
Unknown_Conflicts : Conflict_Lists.Tree;
Known_Conflicts_Edit : Conflict_Lists.Tree := Known_Conflicts;
diff --git a/wisitoken-generate-lr-lr1_generate.ads
b/wisitoken-generate-lr-lr1_generate.ads
index 32f618f941..42004e7f2a 100644
--- a/wisitoken-generate-lr-lr1_generate.ads
+++ b/wisitoken-generate-lr-lr1_generate.ads
@@ -25,8 +25,6 @@
pragma License (Modified_GPL);
-with System.Multiprocessors;
-with WisiToken.Generate.LR1_Items;
with WisiToken.Productions;
package WisiToken.Generate.LR.LR1_Generate is
@@ -42,7 +40,6 @@ package WisiToken.Generate.LR.LR1_Generate is
Include_Extra : in Boolean := False;
Ignore_Conflicts : in Boolean := False;
Recursion_Strategy : in WisiToken.Recursion_Strategy := Full;
- Task_Count : in System.Multiprocessors.CPU_Range := 1;
Use_Cached_Recursions : in Boolean := False;
Recursions : in out WisiToken.Generate.Recursions)
return Parse_Table_Ptr
@@ -63,14 +60,11 @@ package WisiToken.Generate.LR.LR1_Generate is
--
-- Unless Ignore_Unknown_Conflicts is True, raise Grammar_Error if there
-- are unknown conflicts.
- --
- -- Use Task_Count tasks in computing LR1 items. Default is 1 so unit
- -- tests return repeatable results.
----------
-- visible for unit test
- function LR1_Item_Sets_Single
+ function LR1_Item_Sets
(Has_Empty_Production : in Token_ID_Set;
First_Terminal_Sequence : in Token_Sequence_Arrays.Vector;
Grammar : in WisiToken.Productions.Prod_Arrays.Vector;
@@ -79,14 +73,4 @@ package WisiToken.Generate.LR.LR1_Generate is
return LR1_Items.Item_Set_List;
-- [dragon] algorithm 4.9 pg 231; figure 4.38 pg 232; procedure "items",
no tasking
- function LR1_Item_Sets_Parallel
- (Has_Empty_Production : in Token_ID_Set;
- First_Terminal_Sequence : in Token_Sequence_Arrays.Vector;
- Grammar : in WisiToken.Productions.Prod_Arrays.Vector;
- Descriptor : in WisiToken.Descriptor;
- Task_Count : in System.Multiprocessors.CPU_Range;
- Hash_Table_Size : in Positive :=
LR1_Items.Item_Set_Trees.Default_Rows)
- return LR1_Items.Item_Set_List;
- -- With tasking; used if State_Count known.
-
end WisiToken.Generate.LR.LR1_Generate;
diff --git a/wisitoken-lexer-re2c.ads b/wisitoken-lexer-re2c.ads
index 6c1d8c7e02..a57d677c2c 100644
--- a/wisitoken-lexer-re2c.ads
+++ b/wisitoken-lexer-re2c.ads
@@ -4,7 +4,7 @@
--
-- References:
--
--- [1] https://re2c.org/
+-- [1] http://re2c.org/
--
-- Copyright (C) 2017 - 2022 Free Software Foundation, Inc.
--
diff --git a/wisitoken-parse-lr-parser-parse.adb
b/wisitoken-parse-lr-parser-parse.adb
index ea3c5d7b13..e9cd8f2df9 100644
--- a/wisitoken-parse-lr-parser-parse.adb
+++ b/wisitoken-parse-lr-parser-parse.adb
@@ -348,7 +348,8 @@ begin
Recover_Duration : constant Duration := Clock - Start;
begin
Trace.Put_Clock
- ("post-recover" & Shared_Parser.Parsers.Count'Img & "
active," & Recover_Duration'Image);
+ ("post-recover" & Shared_Parser.Parsers.Count'Img & "
parsers active," &
+ Recover_Duration'Image & " seconds");
end;
end if;
diff --git a/wisitoken-parse-lr-parser.adb b/wisitoken-parse-lr-parser.adb
index 5736c89f63..914d08bbab 100644
--- a/wisitoken-parse-lr-parser.adb
+++ b/wisitoken-parse-lr-parser.adb
@@ -1090,6 +1090,12 @@ package body WisiToken.Parse.LR.Parser is
----------
-- Public subprograms, declaration order
+ overriding
+ procedure Finalize (Object : in out Parser)
+ is begin
+ Free_Table (Object.Table);
+ end Finalize;
+
procedure New_Parser
(Parser : out LR.Parser.Parser;
Lexer : in WisiToken.Lexer.Handle;
diff --git a/wisitoken-parse-lr-parser.ads b/wisitoken-parse-lr-parser.ads
index da9495faf5..eb0a1ea164 100644
--- a/wisitoken-parse-lr-parser.ads
+++ b/wisitoken-parse-lr-parser.ads
@@ -23,6 +23,7 @@
pragma License (Modified_GPL);
+with Ada.Unchecked_Deallocation;
with WisiToken.Parse.LR.Parser_Lists;
with WisiToken.Lexer;
with WisiToken.Syntax_Trees;
@@ -94,12 +95,10 @@ package WisiToken.Parse.LR.Parser is
Parsers : aliased Parser_Lists.List;
end record;
- type Parser_Access is access Parser;
+ type Parser_Access is access all Parser;
- -- It is tempting to declare Finalize here, to free Parser.Table. But
- -- Wisi.Parse_Context reuses the table between parser instances, so
- -- we can't do that. Other applications must explicitly free
- -- Parser.Table if they care.
+ overriding procedure Finalize (Object : in out Parser);
+ -- Free Table.
procedure New_Parser
(Parser : out LR.Parser.Parser;
@@ -127,4 +126,7 @@ package WisiToken.Parse.LR.Parser is
Edits : in KMN_Lists.List := KMN_Lists.Empty_List;
Pre_Edited : in Boolean := False);
+ procedure Free is new Ada.Unchecked_Deallocation (Parser, Parser_Access);
+ -- Declared last to avoid freezing rules.
+
end WisiToken.Parse.LR.Parser;
diff --git a/wisitoken-parse.ads b/wisitoken-parse.ads
index 95094c6dfe..b9c5b54b1a 100644
--- a/wisitoken-parse.ads
+++ b/wisitoken-parse.ads
@@ -507,6 +507,7 @@ package WisiToken.Parse is
type Base_Parser_Access is access all Base_Parser'Class;
type Factory is access function return Base_Parser_Access;
+ type Free_Parser is access procedure (Object : in out Base_Parser_Access);
function Source_File_Name (Item : in Base_Parser'Class) return String
is (Item.Tree.Lexer.File_Name);
diff --git a/wisitoken-parse_table-mode.el b/wisitoken-parse_table-mode.el
index 0ec43a3f7b..7685b38fdb 100644
--- a/wisitoken-parse_table-mode.el
+++ b/wisitoken-parse_table-mode.el
@@ -7,7 +7,7 @@
;; Keywords: parser
;; Version: 1.0
;; package-requires: ((emacs "25.1"))
-;; URL: http://www.nongnu.org/ada-mode/wisi/wisi.html
+;; URL: https://www.nongnu.org/ada-mode/wisi/wisi.html
;;
;; This file is part of GNU Emacs.
;;
@@ -116,7 +116,8 @@ Symbol can be a nonterminal name, or a state number."
(defun wisitok-p_t-conflict-alist ()
(let ((conflicts nil)
(nonterms (wisitok-p_t-nonterm-alist))
- line)
+ line
+ (count 0))
(save-excursion
(goto-char (point-min))
@@ -148,7 +149,10 @@ Symbol can be a nonterminal name, or a state number."
(setq conflict (concat conflict " on token " on-token))
(push (cons conflict (list (buffer-file-name) line 0)) conflicts)
- )))
+ )
+ ;; Let user know we are not hung; can take a long time in large buffers.
+ (setq count (1+ count))
+ (message "conflict %d" count)))
conflicts))
(defconst wisitok-p_t-action-nonterm-regexp "\\(?:SHIFT\\|REDUCE\\)
[[:alnum:]_]+")
diff --git a/wisitoken-user_guide.texinfo b/wisitoken-user_guide.texinfo
index fac55a8e16..a0b41c57dc 100644
--- a/wisitoken-user_guide.texinfo
+++ b/wisitoken-user_guide.texinfo
@@ -5,7 +5,7 @@
@settitle WisiToken User Guide
@copying
-Copyright @copyright{} 2014-2015, 2017-2018, 2020-2022 Stephen Leake.
+Copyright @copyright{} 2014-2015, 2017-2018, 2020-2023 Stephen Leake.
@quotation
Permission is granted to copy, distribute and/or modify this
@@ -33,7 +33,7 @@ section entitled "GNU Free Documentation License".
@contents
@node Top
-@top WisiToken User Guide version 4.0
+@top WisiToken User Guide version 4.1
@ifnottex
@insertcopying
@@ -73,7 +73,7 @@ available in the GNU ELPA package @code{wisi}.
You will also need to install a lexer generator. WisiToken supports
re2c, and other lexers can be added.
-re2c is available from @url{https://re2c.org/}; it is also packaged in
+re2c is available from @url{http://re2c.org/}; it is also packaged in
Mingw64 and Debian. WisiToken requires at least version 1.3.
The WisiToken makefile assumes the executable @code{re2c} is in
@code{$PATH}.
diff --git a/wisitoken_grammar_actions.adb b/wisitoken_grammar_actions.adb
index 8fa99c8be9..9c53fba32d 100644
--- a/wisitoken_grammar_actions.adb
+++ b/wisitoken_grammar_actions.adb
@@ -19,7 +19,7 @@
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
--- along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+-- along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
with WisiToken_Grammar_Runtime; use WisiToken_Grammar_Runtime;
diff --git a/wisitoken_grammar_actions.ads b/wisitoken_grammar_actions.ads
index 8220a1e96b..f8a7654b7b 100644
--- a/wisitoken_grammar_actions.ads
+++ b/wisitoken_grammar_actions.ads
@@ -19,7 +19,7 @@
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
--- along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+-- along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
with WisiToken.Syntax_Trees;
package Wisitoken_Grammar_Actions is
diff --git a/wisitoken_grammar_main.adb b/wisitoken_grammar_main.adb
index 38fbafa1b8..4816a20407 100644
--- a/wisitoken_grammar_main.adb
+++ b/wisitoken_grammar_main.adb
@@ -19,7 +19,7 @@
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
--- along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+-- along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
with SAL;
with WisiToken.Lexer.re2c;
diff --git a/wisitoken_grammar_main.ads b/wisitoken_grammar_main.ads
index 68a76445e2..1e7b6f937a 100644
--- a/wisitoken_grammar_main.ads
+++ b/wisitoken_grammar_main.ads
@@ -19,7 +19,7 @@
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
--- along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+-- along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
with WisiToken.Syntax_Trees;
with WisiToken.Parse.LR.Parser_No_Recover;
diff --git a/wisitoken_grammar_re2c.c b/wisitoken_grammar_re2c.c
index 29e815ffa3..712d5eb487 100644
--- a/wisitoken_grammar_re2c.c
+++ b/wisitoken_grammar_re2c.c
@@ -21,7 +21,7 @@
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
-// along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+// along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
#include <stddef.h>
#include <stdio.h>
diff --git a/wisitoken_grammar_re2c_c.ads b/wisitoken_grammar_re2c_c.ads
index bcc487b828..c9d4c55b40 100644
--- a/wisitoken_grammar_re2c_c.ads
+++ b/wisitoken_grammar_re2c_c.ads
@@ -19,7 +19,7 @@
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
--- along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+-- along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
with Interfaces.C;
with WisiToken;