branch: externals/wisi commit 511d382b2be240a601c7e5807532d8b09e37785c Author: Stephen Leake <stephen_le...@stephe-leake.org> Commit: Stephen Leake <stephen_le...@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-em...@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_le...@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_le...@stephe-leake.org> ;; Maintainer: Stephen Leake <stephen_le...@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;