emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/wisi 8ee3847f8c 1/2: Update to wisi 4.1.1


From: Stephen Leake
Subject: [elpa] externals/wisi 8ee3847f8c 1/2: Update to wisi 4.1.1
Date: Tue, 1 Nov 2022 17:24:23 -0400 (EDT)

branch: externals/wisi
commit 8ee3847f8c561050d1ab89abb1f3da88c8710c81
Author: Stephen Leake <stephen_leake@stephe-leake.org>
Commit: Stephen Leake <stephen_leake@stephe-leake.org>

    Update to wisi 4.1.1
---
 NEWS                                            |   16 +
 README                                          |    9 +-
 emacs_wisi_common_parse.adb                     |  109 +-
 emacs_wisi_common_parse.ads                     |    3 +-
 gen_emacs_wisi_lr_parse.adb                     |   21 +-
 gen_emacs_wisi_lr_parse.ads                     |   14 +-
 gen_emacs_wisi_lr_text_rep_parse.adb            |   86 +-
 gen_emacs_wisi_lr_text_rep_parse.ads            |   15 +-
 gen_run_wisi_lr_parse.adb                       |   38 +-
 gen_run_wisi_lr_parse.ads                       |   14 +-
 gen_run_wisi_lr_text_rep_parse.adb              |   41 +-
 gen_run_wisi_lr_text_rep_parse.ads              |   15 +-
 run_wisi_common_parse.adb                       |  177 +-
 run_wisi_common_parse.ads                       |    5 +-
 sal-gen_definite_doubly_linked_lists.adb        |    4 +-
 sal-gen_definite_doubly_linked_lists.ads        |    3 +-
 sal-gen_indefinite_doubly_linked_lists.adb      |   41 +-
 sal-gen_indefinite_doubly_linked_lists.ads      |    5 +-
 sal.adb                                         |    2 +-
 standard_common.gpr                             |    3 +-
 wisi-fringe.el                                  |   10 +-
 wisi-parse-common.el                            |   59 +-
 wisi-parse_context.adb                          |   84 +-
 wisi-parse_context.ads                          |   51 +-
 wisi-prj.el                                     |  295 +-
 wisi-process-parse.el                           |  265 +-
 wisi-run-indent-test.el                         |  173 +-
 wisi-skel.el                                    |    8 +-
 wisi.adb                                        |   73 +-
 wisi.ads                                        |   13 +-
 wisi.el                                         |  315 +-
 wisi.texi                                       |   24 +-
 wisitoken-bnf-generate.adb                      |   47 +-
 wisitoken-bnf-generate_packrat.adb              |   75 +-
 wisitoken-bnf-generate_utils.adb                |   18 +-
 wisitoken-bnf-output_ada.adb                    |   41 +-
 wisitoken-bnf-output_ada_common.adb             |  232 +-
 wisitoken-bnf-output_ada_common.ads             |   12 +-
 wisitoken-bnf-output_ada_emacs.adb              |   23 +-
 wisitoken-bnf.ads                               |    3 +-
 wisitoken-generate-lr-lalr_generate.adb         |   25 +-
 wisitoken-generate-lr-lalr_generate.ads         |   19 +-
 wisitoken-generate-lr-lr1_generate.adb          |   27 +-
 wisitoken-generate-lr-lr1_generate.ads          |    6 +-
 wisitoken-lexer-re2c.adb                        |    6 +-
 wisitoken-lexer.adb                             |    4 +-
 wisitoken-parse-lr-mckenzie_recover-explore.adb |    7 +-
 wisitoken-parse-lr-mckenzie_recover.adb         |   10 +-
 wisitoken-parse-lr-parser-parse.adb             |    6 +-
 wisitoken-parse-lr-parser.adb                   |  188 +-
 wisitoken-parse-lr-parser.ads                   |   16 +-
 wisitoken-parse-lr-parser_no_recover.adb        |   72 +-
 wisitoken-parse-lr-parser_no_recover.ads        |   12 -
 wisitoken-parse-lr.adb                          |   13 +
 wisitoken-parse-lr.ads                          |    6 +-
 wisitoken-parse-packrat-generated.adb           |   43 +-
 wisitoken-parse-packrat-generated.ads           |   41 +-
 wisitoken-parse-packrat-procedural.adb          |  258 +-
 wisitoken-parse-packrat-procedural.ads          |   40 +-
 wisitoken-parse-packrat.adb                     |  212 +-
 wisitoken-parse-packrat.ads                     |  114 +-
 wisitoken-parse.adb                             |  104 +-
 wisitoken-parse.ads                             |   20 +-
 wisitoken-parse_table-mode.el                   |    1 +
 wisitoken-productions.ads                       |    4 +-
 wisitoken-syntax_trees.adb                      |  610 +-
 wisitoken-syntax_trees.ads                      |  198 +-
 wisitoken-user_guide.texinfo                    |    2 +-
 wisitoken.ads                                   |    4 +
 wisitoken_grammar_actions.ads                   |    2 +
 wisitoken_grammar_editing.adb                   |    2 +-
 wisitoken_grammar_main.adb                      |   18 +-
 wisitoken_grammar_main.ads                      |   12 +-
 wisitoken_grammar_re2c.c                        | 9457 +++++++++++------------
 wisitoken_grammar_runtime.adb                   |    9 +-
 75 files changed, 7343 insertions(+), 6667 deletions(-)

diff --git a/NEWS b/NEWS
index 336b9eb7b9..478b6f91ef 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,22 @@ 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.1.1
+8 Oct 2022
+
+** Ada code builds with alire.
+
+** gnat-compiler split out into separate ELPA package.
+
+** A bug in updating the fringe error marks is fixed.
+
+** Support using eglot to replace some wisi functions; new user
+   configuration variables wisi-disable-face, wisi-disable-completion,
+   wisi-disable-indent, wisi-disable-parser.
+
+** In wisi project files, import_env_var=<name> can be used to inherit
+   an environment variable from the Emacs process.
+
 * wisi 4.0.beta
 9 Jul 2022 beta testing
 
diff --git a/README b/README
index 4375ad58c4..633727e4b8 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-Emacs wisi package 4.0.beta
+Emacs wisi package 4.1.1
 
 The wisi package provides utilities for using generalized
 error-correcting LR parsers (in external processes) to do indentation,
@@ -8,7 +8,6 @@ See ada-mode for an example of its use.
 It also provides wisitoken-parse_table-mode, for navigating the
 diagnostic parse tables output by wisitoken-bnf-generate.
 
-The generated code is in Ada; it requires the AdaCore gnat compiler
-that you may not have installed. It is available in many packaging
-systems, or as a binary download from
-https://www.adacore.com/download.
+The generated code is in Ada; it can be built via Alire
+(https://alire.ada.dev/). Normally this is done by a package that uses
+wisi, such as ada-mode.
diff --git a/emacs_wisi_common_parse.adb b/emacs_wisi_common_parse.adb
index fb751b3dc3..6c1c80a228 100644
--- a/emacs_wisi_common_parse.adb
+++ b/emacs_wisi_common_parse.adb
@@ -28,7 +28,6 @@ with GNAT.Traceback.Symbolic;
 with GNATCOLL.Memory;
 with SAL;
 with System.Storage_Elements;
-with WisiToken.Lexer;
 with WisiToken.Parse.LR.Parser;
 with WisiToken.Syntax_Trees;
 package body Emacs_Wisi_Common_Parse is
@@ -249,7 +248,7 @@ package body Emacs_Wisi_Common_Parse is
      (Name                      : in String;
       Language_Protocol_Version : in String;
       Params                    : in Process_Start_Params;
-      Language                  : in Wisi.Parse_Context.Language;
+      Factory                   : in WisiToken.Parse.Factory;
       Trace                     : in WisiToken.Trace_Access)
    is
       use Ada.Text_IO;
@@ -318,10 +317,25 @@ package body Emacs_Wisi_Common_Parse is
             end if;
 
             if Match ("create-context") then
-               Wisi.Parse_Context.Create_No_Text (Wisi.Get_String 
(Command_Line, Last), Language, Trace);
+               Wisi.Parse_Context.Create_No_Text (Wisi.Get_String 
(Command_Line, Last), Factory, Trace);
 
-            elsif Match ("kill-context") then
-               Wisi.Parse_Context.Kill (File_Name => Wisi.Get_String 
(Command_Line, Last));
+            elsif Match ("dump_prev_tree") then
+               --  Args: source_file_name save_file_root
+               --  Input: <none>
+               --  Response:
+               --  (message "prev_tree dumped")
+               --  prompt
+               declare
+                  Source_File_Name : constant String := Wisi.Get_String 
(Command_Line, Last);
+                  Save_File_Name   : constant String := Wisi.Get_String 
(Command_Line, Last);
+
+                  Parse_Context : constant 
Wisi.Parse_Context.Parse_Context_Access := Wisi.Parse_Context.Find
+                    (Source_File_Name);
+               begin
+                  Check_Command_Length (Command_Length, Last);
+
+                  Parse_Context.Dump_Prev_Tree (Save_File_Name);
+               end;
 
             elsif Match ("enable_memory_report") then
                --  Args: <none>
@@ -334,6 +348,9 @@ package body Emacs_Wisi_Common_Parse is
                   Stack_Trace_Depth     => 0,
                   Reset_Content_On_Free => False);
 
+            elsif Match ("kill-context") then
+               Wisi.Parse_Context.Kill (File_Name => Wisi.Get_String 
(Command_Line, Last));
+
             elsif Match ("memory_report_reset") then
                --  Args: <none>
                --  Input: <none>
@@ -368,21 +385,31 @@ package body Emacs_Wisi_Common_Parse is
                   Parse_Context : constant 
Wisi.Parse_Context.Parse_Context_Access :=
                     (case Params.Kind is
                      when Full | Partial => Wisi.Parse_Context.Find_Create
-                       (-Params.Source_File_Name, Language, Trace),
+                       (-Params.Source_File_Name, Factory, Trace),
                      when Incremental => Wisi.Parse_Context.Find
-                       (-Params.Source_File_Name, Language, Have_Text => 
True));
+                       (-Params.Source_File_Name, Have_Text => True));
 
-                  Parser     : Parse.LR.Parser.Parser renames 
Parse_Context.Parser;
+                  Parser     : WisiToken.Parse.Base_Parser'Class renames 
Parse_Context.Parser.all;
                   Parse_Data : Wisi.Parse_Data_Type'Class renames 
Wisi.Parse_Data_Type'Class (Parser.User_Data.all);
                begin
-                  if Params.Zombie_Limit > 0 then
-                     Parser.Table.McKenzie_Param.Zombie_Limit := 
Params.Zombie_Limit;
-                  end if;
-                  if Params.Enqueue_Limit > 0 then
-                     Parser.Table.McKenzie_Param.Enqueue_Limit := 
Params.Enqueue_Limit;
+                  if Parse_Context.Frozen then
+                     raise WisiToken.Parse_Error with "parse_context frozen";
                   end if;
-                  if Params.Max_Parallel > 0 then
-                     Parser.Table.Max_Parallel := SAL.Base_Peek_Type 
(Params.Max_Parallel);
+
+                  if Parser in WisiToken.Parse.LR.Parser.Parser then
+                     declare
+                        LR_Parser : WisiToken.Parse.LR.Parser.Parser renames 
WisiToken.Parse.LR.Parser.Parser (Parser);
+                     begin
+                        if Params.Zombie_Limit > 0 then
+                           LR_Parser.Table.McKenzie_Param.Zombie_Limit := 
Params.Zombie_Limit;
+                        end if;
+                        if Params.Enqueue_Limit > 0 then
+                           LR_Parser.Table.McKenzie_Param.Enqueue_Limit := 
Params.Enqueue_Limit;
+                        end if;
+                        if Params.Max_Parallel > 0 then
+                           LR_Parser.Table.Max_Parallel := SAL.Base_Peek_Type 
(Params.Max_Parallel);
+                        end if;
+                     end;
                   end if;
 
                   case Params.Kind is
@@ -439,6 +466,14 @@ package body Emacs_Wisi_Common_Parse is
                      declare
                         KMN_List : Parse.KMN_Lists.List;
                      begin
+                        if Parse_Context.Save_Prev_Text_Tree then
+                           Parse_Context.Save_Text (-Parse_Context.File_Name & 
"-wisi-prev-text");
+                           if Parser.Tree.Editable then
+                              Parser.Tree.Copy_Tree
+                                (Parse_Context.Prev_Tree, 
Syntax_Trees.User_Data_Access_Constant (Parser.User_Data));
+                           end if;
+                        end if;
+
                         Wisi.Parse_Context.Edit_Source (Trace.all, 
Parse_Context.all, Params.Changes, KMN_List);
 
                         if Ada.Strings.Unbounded.Length 
(Parse_Context.Root_Save_Edited_Name) /= 0 then
@@ -505,8 +540,20 @@ package body Emacs_Wisi_Common_Parse is
                   Wisi.Put_Errors (Parser.Tree);
                   raise;
 
+               when WisiToken.Validate_Error =>
+                  Wisi.Put_Errors (Parser.Tree);
+                  if WisiToken.Debug_Mode then
+                     --  Ensure we don't lose the debug state
+                     Parse_Context.Frozen := True;
+                  end if;
+                  raise WisiToken.Parse_Error with "validate error; 
parse_context frozen";
+
                when others =>
                   Parser.Tree.Lexer.Discard_Rest_Of_Input;
+                  if WisiToken.Debug_Mode then
+                     --  Ensure we don't lose the debug state
+                     Parse_Context.Frozen := True;
+                  end if;
                   raise;
                end;
 
@@ -521,9 +568,9 @@ package body Emacs_Wisi_Common_Parse is
                   Params : constant Post_Parse_Params := Get_Post_Parse_Params 
(Command_Line, Last);
 
                   Parse_Context : constant 
Wisi.Parse_Context.Parse_Context_Access := Wisi.Parse_Context.Find
-                    (-Params.Source_File_Name, Language, Have_Text => True);
+                    (-Params.Source_File_Name, Have_Text => True);
 
-                  Parser     : Parse.LR.Parser.Parser renames 
Parse_Context.Parser;
+                  Parser     : WisiToken.Parse.Base_Parser'Class renames 
Parse_Context.Parser.all;
                   Parse_Data : Wisi.Parse_Data_Type'Class renames 
Wisi.Parse_Data_Type'Class (Parser.User_Data.all);
                begin
                   Parse_Data.Reset_Post_Parse
@@ -550,7 +597,7 @@ package body Emacs_Wisi_Common_Parse is
                   Params : constant Refactor_Params := Get_Refactor_Params 
(Command_Line, Last);
 
                   Parse_Context : constant 
Wisi.Parse_Context.Parse_Context_Access := Wisi.Parse_Context.Find
-                    (-Params.Source_File_Name, Language);
+                    (-Params.Source_File_Name);
 
                   Parse_Data : Wisi.Parse_Data_Type'Class renames 
Wisi.Parse_Data_Type'Class
                     (Parse_Context.Parser.User_Data.all);
@@ -572,7 +619,7 @@ package body Emacs_Wisi_Common_Parse is
                   Label : constant Wisi.Query_Label := Wisi.Query_Label'Val 
(Wisi.Get_Integer (Command_Line, Last));
 
                   Parse_Context : constant 
Wisi.Parse_Context.Parse_Context_Access := Wisi.Parse_Context.Find
-                    (-Source_File_Name, Language);
+                    (-Source_File_Name);
 
                   Parse_Data : constant Wisi.Parse_Data_Access_Constant :=
                     Wisi.Parse_Data_Access_Constant 
(Parse_Context.Parser.User_Data);
@@ -627,6 +674,26 @@ package body Emacs_Wisi_Common_Parse is
                   end case;
                end;
 
+            elsif Match ("save_prev_auto") then
+               --  Args: source_file_name enable
+               --  Input: <none>
+               --  Response:
+               --  (message "save_prev_auto enabled")
+               --  prompt
+               declare
+                  Source_File_Name : constant String  := Wisi.Get_String 
(Command_Line, Last);
+                  Enable           : constant Boolean := 1 = Wisi.Get_Integer 
(Command_Line, Last);
+
+                  --  This command is often the first command for a source 
file, from
+                  --  wisi-reset-parser.
+                  Parse_Context : constant 
Wisi.Parse_Context.Parse_Context_Access := Wisi.Parse_Context.Find_Create
+                    (Source_File_Name, Factory, Trace);
+               begin
+                  Check_Command_Length (Command_Length, Last);
+
+                  Parse_Context.Save_Prev_Text_Tree := Enable;
+               end;
+
             elsif Match ("save_text") then
                --  Args: source_file_name save_file_name
                --  Input: <none>
@@ -638,7 +705,7 @@ package body Emacs_Wisi_Common_Parse is
                   Save_File_Name   : constant String := Wisi.Get_String 
(Command_Line, Last);
 
                   Parse_Context : constant 
Wisi.Parse_Context.Parse_Context_Access := Wisi.Parse_Context.Find
-                    (Source_File_Name, Language);
+                    (Source_File_Name);
                begin
                   Check_Command_Length (Command_Length, Last);
 
@@ -660,7 +727,7 @@ package body Emacs_Wisi_Common_Parse is
 
                   --  We need "create" here for partial parse.
                   Parse_Context : constant 
Wisi.Parse_Context.Parse_Context_Access := Wisi.Parse_Context.Find_Create
-                    (Source_File_Name, Language, Trace);
+                    (Source_File_Name, Factory, Trace);
                begin
                   Check_Command_Length (Command_Length, Last);
 
diff --git a/emacs_wisi_common_parse.ads b/emacs_wisi_common_parse.ads
index fb10f469a9..e6852cf422 100644
--- a/emacs_wisi_common_parse.ads
+++ b/emacs_wisi_common_parse.ads
@@ -20,7 +20,6 @@ pragma License (GPL);
 
 with Ada.Strings.Unbounded;
 with System;
-with Wisi;
 with WisiToken.Parse;
 with Wisi.Parse_Context;
 package Emacs_Wisi_Common_Parse is
@@ -67,7 +66,7 @@ package Emacs_Wisi_Common_Parse is
      (Name                      : in String;
       Language_Protocol_Version : in String;
       Params                    : in Process_Start_Params;
-      Language                  : in Wisi.Parse_Context.Language;
+      Factory                   : in WisiToken.Parse.Factory;
       Trace                     : in WisiToken.Trace_Access);
 
    ----------
diff --git a/gen_emacs_wisi_lr_parse.adb b/gen_emacs_wisi_lr_parse.adb
index 34a83df130..72638d68bf 100644
--- a/gen_emacs_wisi_lr_parse.adb
+++ b/gen_emacs_wisi_lr_parse.adb
@@ -23,15 +23,20 @@ with WisiToken.Parse.LR.Parser;
 with WisiToken.Text_IO_Trace;
 procedure Gen_Emacs_Wisi_LR_Parse
 is
-   Trace               : aliased WisiToken.Text_IO_Trace.Trace;
-   Parse_Data_Template : aliased Parse_Data_Type;
-
+   Trace  : aliased WisiToken.Text_IO_Trace.Trace;
    Params : constant Process_Start_Params := Get_Process_Start_Params;
+
+   function Factory return WisiToken.Parse.Base_Parser_Access
+   is begin
+      return new WisiToken.Parse.LR.Parser.Parser'
+        (Create_Parser
+           (Trace'Unrestricted_Access,
+            User_Data                      => new Parse_Data_Type,
+            Language_Fixes                 => Language_Fixes,
+            Language_Matching_Begin_Tokens => Language_Matching_Begin_Tokens,
+            Language_String_ID_Set         => Language_String_ID_Set));
+   end Factory;
 begin
    Process_Stream
-     (Name, Language_Protocol_Version, Params,
-      (Descriptor, Create_Lexer (Trace'Unchecked_Access), Create_Parse_Table, 
Create_Productions,
-       Partial_Parse_Active, Partial_Parse_Byte_Goal, Language_Fixes, 
Language_Matching_Begin_Tokens,
-       Language_String_ID_Set, Parse_Data_Template'Unchecked_Access),
-      Trace'Unchecked_Access);
+     (Name, Language_Protocol_Version, Params, Factory'Unrestricted_Access, 
Trace'Unchecked_Access);
 end Gen_Emacs_Wisi_LR_Parse;
diff --git a/gen_emacs_wisi_lr_parse.ads b/gen_emacs_wisi_lr_parse.ads
index 71d5e8afbb..4dd3ea9575 100644
--- a/gen_emacs_wisi_lr_parse.ads
+++ b/gen_emacs_wisi_lr_parse.ads
@@ -31,7 +31,6 @@
 pragma License (GPL);
 
 with Wisi;
-with WisiToken.Lexer;
 with WisiToken.Parse.LR.Parser;
 with WisiToken.Syntax_Trees;
 generic
@@ -39,15 +38,16 @@ generic
 
    Name                           : in String; --  for Usage, error messages.
    Language_Protocol_Version      : in String; --  Defines language-specific 
parse parameters.
-   Descriptor                     : in WisiToken.Descriptor_Access_Constant;
-   Partial_Parse_Active           : in WisiToken.Boolean_Access;
-   Partial_Parse_Byte_Goal        : in WisiToken.Buffer_Pos_Access;
    Language_Fixes                 : in 
WisiToken.Parse.LR.Parser.Language_Fixes_Access;
    Language_Matching_Begin_Tokens : in 
WisiToken.Parse.LR.Parser.Language_Matching_Begin_Tokens_Access;
    Language_String_ID_Set         : in 
WisiToken.Parse.LR.Parser.Language_String_ID_Set_Access;
 
-   with function Create_Lexer (Trace : in WisiToken.Trace_Access) return 
WisiToken.Lexer.Handle;
-   with function Create_Parse_Table return WisiToken.Parse.LR.Parse_Table_Ptr;
-   with function Create_Productions return 
WisiToken.Syntax_Trees.Production_Info_Trees.Vector;
+   with function Create_Parser
+     (Trace                          : in WisiToken.Trace_Access;
+      User_Data                      : in 
WisiToken.Syntax_Trees.User_Data_Access;
+      Language_Fixes                 : in 
WisiToken.Parse.LR.Parser.Language_Fixes_Access;
+      Language_Matching_Begin_Tokens : in 
WisiToken.Parse.LR.Parser.Language_Matching_Begin_Tokens_Access;
+      Language_String_ID_Set         : in 
WisiToken.Parse.LR.Parser.Language_String_ID_Set_Access)
+     return WisiToken.Parse.LR.Parser.Parser;
 
 procedure 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 f2211954ea..c3a73ca565 100644
--- a/gen_emacs_wisi_lr_text_rep_parse.adb
+++ b/gen_emacs_wisi_lr_text_rep_parse.adb
@@ -1,39 +1,47 @@
---  Abstract :
---
---  See spec.
---
---  Copyright (C) 2014, 2017 - 2020, 2022 All Rights Reserved.
---
---  This program is free software; you can redistribute it and/or
---  modify it under terms of the GNU General Public License as
---  published by the Free Software Foundation; either version 3, or (at
---  your option) any later version. This program is distributed in the
---  hope that it will be useful, but WITHOUT ANY WARRANTY; without even
---  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
---  PURPOSE. See the GNU General Public License for more details. You
---  should have received a copy of the GNU General Public License
---  distributed with this program; see file COPYING. If not, write to
---  the Free Software Foundation, 51 Franklin Street, Suite 500, Boston,
---  MA 02110-1335, USA.
-
-pragma License (GPL);
-
-with Ada.Command_Line;
-with Ada.Directories;
-with Emacs_Wisi_Common_Parse; use Emacs_Wisi_Common_Parse;
-with WisiToken.Text_IO_Trace;
-procedure Gen_Emacs_Wisi_LR_Text_Rep_Parse
-is
-   Trace               : aliased WisiToken.Text_IO_Trace.Trace;
-   Parse_Data_Template : aliased Parse_Data_Type;
-
-   Params : constant Process_Start_Params := Get_Process_Start_Params;
-begin
-   Process_Stream
-     (Name, Language_Protocol_Version, Params,
-      (Descriptor, Create_Lexer (Trace'Unchecked_Access), Create_Parse_Table
-         (Ada.Directories.Containing_Directory (Ada.Command_Line.Command_Name) 
& "/" & Text_Rep_File_Name),
-       Create_Productions, Partial_Parse_Active, Partial_Parse_Byte_Goal, 
Language_Fixes,
-       Language_Matching_Begin_Tokens, Language_String_ID_Set, 
Parse_Data_Template'Unchecked_Access),
-     Trace'Unchecked_Access);
-end Gen_Emacs_Wisi_LR_Text_Rep_Parse;
+--  Abstract :
+--
+--  See spec.
+--
+--  Copyright (C) 2014, 2017 - 2020, 2022 All Rights Reserved.
+--
+--  This program is free software; you can redistribute it and/or
+--  modify it under terms of the GNU General Public License as
+--  published by the Free Software Foundation; either version 3, or (at
+--  your option) any later version. This program is distributed in the
+--  hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+--  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+--  PURPOSE. See the GNU General Public License for more details. You
+--  should have received a copy of the GNU General Public License
+--  distributed with this program; see file COPYING. If not, write to
+--  the Free Software Foundation, 51 Franklin Street, Suite 500, Boston,
+--  MA 02110-1335, USA.
+
+pragma License (GPL);
+
+with Ada.Command_Line;
+with Ada.Directories;
+with Emacs_Wisi_Common_Parse; use Emacs_Wisi_Common_Parse;
+with WisiToken.Text_IO_Trace;
+procedure Gen_Emacs_Wisi_LR_Text_Rep_Parse
+is
+   Trace  : aliased WisiToken.Text_IO_Trace.Trace;
+   Params : constant Process_Start_Params := Get_Process_Start_Params;
+
+   Text_Rep_File_Name_Full : constant String := 
Ada.Directories.Containing_Directory
+     (Ada.Command_Line.Command_Name) & "/" & Text_Rep_File_Name;
+
+   function Factory return WisiToken.Parse.Base_Parser_Access
+   is begin
+      return new WisiToken.Parse.LR.Parser.Parser'
+        (Create_Parser
+           (Trace                          => Trace'Unchecked_Access,
+            User_Data                      => new Parse_Data_Type,
+            Language_Fixes                 => Language_Fixes,
+            Language_Matching_Begin_Tokens => Language_Matching_Begin_Tokens,
+            Language_String_ID_Set         => Language_String_ID_Set,
+            Text_Rep_File_Name             => Text_Rep_File_Name_Full));
+   end Factory;
+begin
+   Process_Stream
+     (Name, Language_Protocol_Version, Params, Factory'Unrestricted_Access, 
Trace'Unchecked_Access);
+end Gen_Emacs_Wisi_LR_Text_Rep_Parse;
diff --git a/gen_emacs_wisi_lr_text_rep_parse.ads 
b/gen_emacs_wisi_lr_text_rep_parse.ads
index 83487a72d2..da0b5e07a7 100644
--- a/gen_emacs_wisi_lr_text_rep_parse.ads
+++ b/gen_emacs_wisi_lr_text_rep_parse.ads
@@ -24,7 +24,6 @@
 pragma License (GPL);
 
 with Wisi;
-with WisiToken.Lexer;
 with WisiToken.Parse.LR.Parser;
 with WisiToken.Syntax_Trees;
 generic
@@ -32,16 +31,18 @@ generic
 
    Name                           : in String; --  for Usage, error messages. 
"_wisi_parse" will be appended
    Language_Protocol_Version      : in String; --  Defines language-specific 
parse parameters.
-   Descriptor                     : in WisiToken.Descriptor_Access_Constant;
-   Partial_Parse_Active           : in WisiToken.Boolean_Access;
-   Partial_Parse_Byte_Goal        : in WisiToken.Buffer_Pos_Access;
    Language_Fixes                 : in 
WisiToken.Parse.LR.Parser.Language_Fixes_Access;
    Language_Matching_Begin_Tokens : in 
WisiToken.Parse.LR.Parser.Language_Matching_Begin_Tokens_Access;
    Language_String_ID_Set         : in 
WisiToken.Parse.LR.Parser.Language_String_ID_Set_Access;
    Text_Rep_File_Name             : in String;
 
-   with function Create_Lexer (Trace : in WisiToken.Trace_Access) return 
WisiToken.Lexer.Handle;
-   with function Create_Parse_Table (Text_Rep_File_Name : in String) return 
WisiToken.Parse.LR.Parse_Table_Ptr;
-   with function Create_Productions return 
WisiToken.Syntax_Trees.Production_Info_Trees.Vector;
+   with function Create_Parser
+     (Trace                          : in WisiToken.Trace_Access;
+      User_Data                      : in 
WisiToken.Syntax_Trees.User_Data_Access;
+      Language_Fixes                 : in 
WisiToken.Parse.LR.Parser.Language_Fixes_Access;
+      Language_Matching_Begin_Tokens : in 
WisiToken.Parse.LR.Parser.Language_Matching_Begin_Tokens_Access;
+      Language_String_ID_Set         : in 
WisiToken.Parse.LR.Parser.Language_String_ID_Set_Access;
+      Text_Rep_File_Name             : in String)
+     return WisiToken.Parse.LR.Parser.Parser;
 
 procedure Gen_Emacs_Wisi_LR_Text_Rep_Parse;
diff --git a/gen_run_wisi_lr_parse.adb b/gen_run_wisi_lr_parse.adb
index 803ddb8213..31477aa0dd 100644
--- a/gen_run_wisi_lr_parse.adb
+++ b/gen_run_wisi_lr_parse.adb
@@ -18,34 +18,22 @@
 
 pragma License (GPL);
 
-with GNATCOLL.Memory;
 with Run_Wisi_Common_Parse;
 with WisiToken.Text_IO_Trace;
 procedure Gen_Run_Wisi_LR_Parse
 is
-   Trace               : aliased WisiToken.Text_IO_Trace.Trace;
-   Parse_Data_Template : aliased Parse_Data_Type;
-begin
-   --  FIXME: report memory during lexer, parser create
-   --  WisiToken.Trace_Memory            := 2;
-   --  WisiToken.Trace_Incremental_Parse := 1;
-   GNATCOLL.Memory.Configure
-     (Activate_Monitor      => True,
-      Stack_Trace_Depth     => 10,
-      Reset_Content_On_Free => False);
-
-   declare
-      Lexer : constant WisiToken.Lexer.Handle := Create_Lexer 
(Trace'Unchecked_Access);
-      --  No point in reporting lexer memory; it's very small
-      Parse_Table : constant WisiToken.Parse.LR.Parse_Table_Ptr := 
Create_Parse_Table;
-   begin
-      Trace.Put_Line ("parse table created");
-      WisiToken.Report_Memory (Trace, Prefix => True);
+   Trace : aliased WisiToken.Text_IO_Trace.Trace;
 
-      Run_Wisi_Common_Parse.Parse_File
-        ((Descriptor, Lexer, Parse_Table, Create_Productions, 
Partial_Parse_Active,
-          Partial_Parse_Byte_Goal, Language_Fixes, 
Language_Matching_Begin_Tokens, Language_String_ID_Set,
-          Parse_Data_Template'Unchecked_Access),
-         Trace'Unchecked_Access);
-   end;
+   function Factory return WisiToken.Parse.Base_Parser_Access
+   is begin
+      return new WisiToken.Parse.LR.Parser.Parser'
+        (Create_Parser
+           (Trace'Unrestricted_Access,
+            User_Data                      => new Parse_Data_Type,
+            Language_Fixes                 => Language_Fixes,
+            Language_Matching_Begin_Tokens => Language_Matching_Begin_Tokens,
+            Language_String_ID_Set         => Language_String_ID_Set));
+   end Factory;
+begin
+   Run_Wisi_Common_Parse.Parse_File (Factory'Unrestricted_Access, 
Trace'Unchecked_Access);
 end Gen_Run_Wisi_LR_Parse;
diff --git a/gen_run_wisi_lr_parse.ads b/gen_run_wisi_lr_parse.ads
index 34b73fa171..65c03c337d 100644
--- a/gen_run_wisi_lr_parse.ads
+++ b/gen_run_wisi_lr_parse.ads
@@ -21,21 +21,21 @@
 pragma License (GPL);
 
 with Wisi;
-with WisiToken.Lexer;
 with WisiToken.Parse.LR.Parser;
 with WisiToken.Syntax_Trees;
 generic
    type Parse_Data_Type is new Wisi.Parse_Data_Type with private;
 
-   Descriptor                     : in WisiToken.Descriptor_Access_Constant;
-   Partial_Parse_Active           : in WisiToken.Boolean_Access;
-   Partial_Parse_Byte_Goal        : in WisiToken.Buffer_Pos_Access;
    Language_Fixes                 : in 
WisiToken.Parse.LR.Parser.Language_Fixes_Access;
    Language_Matching_Begin_Tokens : in 
WisiToken.Parse.LR.Parser.Language_Matching_Begin_Tokens_Access;
    Language_String_ID_Set         : in 
WisiToken.Parse.LR.Parser.Language_String_ID_Set_Access;
 
-   with function Create_Lexer (Trace : in WisiToken.Trace_Access) return 
WisiToken.Lexer.Handle;
-   with function Create_Parse_Table return WisiToken.Parse.LR.Parse_Table_Ptr;
-   with function Create_Productions return 
WisiToken.Syntax_Trees.Production_Info_Trees.Vector;
+   with function Create_Parser
+     (Trace                          : in WisiToken.Trace_Access;
+      User_Data                      : in 
WisiToken.Syntax_Trees.User_Data_Access;
+      Language_Fixes                 : in 
WisiToken.Parse.LR.Parser.Language_Fixes_Access;
+      Language_Matching_Begin_Tokens : in 
WisiToken.Parse.LR.Parser.Language_Matching_Begin_Tokens_Access;
+      Language_String_ID_Set         : in 
WisiToken.Parse.LR.Parser.Language_String_ID_Set_Access)
+     return WisiToken.Parse.LR.Parser.Parser;
 
 procedure 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 6c2196e83f..a426cdc144 100644
--- a/gen_run_wisi_lr_text_rep_parse.adb
+++ b/gen_run_wisi_lr_text_rep_parse.adb
@@ -20,35 +20,26 @@ pragma License (GPL);
 
 with Ada.Command_Line;
 with Ada.Directories;
-with GNATCOLL.Memory;
 with Run_Wisi_Common_Parse;
 with WisiToken.Text_IO_Trace;
 procedure Gen_Run_Wisi_LR_Text_Rep_Parse
 is
-   Trace               : aliased WisiToken.Text_IO_Trace.Trace;
-   Parse_Data_Template : aliased Parse_Data_Type;
-begin
-   --  FIXME: report memory during lexer, parser create
-   --  WisiToken.Trace_Memory            := 1;
-   --  WisiToken.Trace_Incremental_Parse := 1;
-   GNATCOLL.Memory.Configure
-     (Activate_Monitor      => True,
-      Stack_Trace_Depth     => 0,
-      Reset_Content_On_Free => False);
+   Trace : aliased WisiToken.Text_IO_Trace.Trace;
 
-   declare
-      Lexer : constant WisiToken.Lexer.Handle := Create_Lexer 
(Trace'Unchecked_Access);
-      --  No point in reporting lexer memory; it's very small
-      Parse_Table : constant WisiToken.Parse.LR.Parse_Table_Ptr := 
Create_Parse_Table
-        (Ada.Directories.Containing_Directory (Ada.Command_Line.Command_Name) 
& "/" & Text_Rep_File_Name);
-   begin
-      Trace.Put_Line ("parse table created");
-      WisiToken.Report_Memory (Trace, Prefix => True);
+   Text_Rep_File_Name_Full : constant String := 
Ada.Directories.Containing_Directory
+     (Ada.Command_Line.Command_Name) & "/" & Text_Rep_File_Name;
 
-      Run_Wisi_Common_Parse.Parse_File
-        ((Descriptor, Lexer, Parse_Table,
-          Create_Productions, Partial_Parse_Active, Partial_Parse_Byte_Goal, 
Language_Fixes,
-          Language_Matching_Begin_Tokens, Language_String_ID_Set, 
Parse_Data_Template'Unchecked_Access),
-         Trace'Unchecked_Access);
-   end;
+   function Factory return WisiToken.Parse.Base_Parser_Access
+   is begin
+      return new WisiToken.Parse.LR.Parser.Parser'
+        (Create_Parser
+           (Trace'Unchecked_Access,
+            User_Data                      => new Parse_Data_Type,
+            Language_Fixes                 => Language_Fixes,
+            Language_Matching_Begin_Tokens => Language_Matching_Begin_Tokens,
+            Language_String_ID_Set         => Language_String_ID_Set,
+            Text_Rep_File_Name             => Text_Rep_File_Name_Full));
+   end Factory;
+begin
+   Run_Wisi_Common_Parse.Parse_File (Factory'Unrestricted_Access, 
Trace'Unchecked_Access);
 end Gen_Run_Wisi_LR_Text_Rep_Parse;
diff --git a/gen_run_wisi_lr_text_rep_parse.ads 
b/gen_run_wisi_lr_text_rep_parse.ads
index dea8f54048..405013da2e 100644
--- a/gen_run_wisi_lr_text_rep_parse.ads
+++ b/gen_run_wisi_lr_text_rep_parse.ads
@@ -21,22 +21,23 @@
 pragma License (GPL);
 
 with Wisi;
-with WisiToken.Lexer;
 with WisiToken.Parse.LR.Parser;
 with WisiToken.Syntax_Trees;
 generic
    type Parse_Data_Type is new Wisi.Parse_Data_Type with private;
 
-   Descriptor                     : in WisiToken.Descriptor_Access_Constant;
-   Partial_Parse_Active           : in WisiToken.Boolean_Access;
-   Partial_Parse_Byte_Goal        : in WisiToken.Buffer_Pos_Access;
    Language_Fixes                 : in 
WisiToken.Parse.LR.Parser.Language_Fixes_Access;
    Language_Matching_Begin_Tokens : in 
WisiToken.Parse.LR.Parser.Language_Matching_Begin_Tokens_Access;
    Language_String_ID_Set         : in 
WisiToken.Parse.LR.Parser.Language_String_ID_Set_Access;
    Text_Rep_File_Name             : in String;
 
-   with function Create_Lexer (Trace : in WisiToken.Trace_Access) return 
WisiToken.Lexer.Handle;
-   with function Create_Parse_Table (Text_Rep_File_Name : in String) return 
WisiToken.Parse.LR.Parse_Table_Ptr;
-   with function Create_Productions return 
WisiToken.Syntax_Trees.Production_Info_Trees.Vector;
+   with function Create_Parser
+     (Trace                          : in WisiToken.Trace_Access;
+      User_Data                      : in 
WisiToken.Syntax_Trees.User_Data_Access;
+      Language_Fixes                 : in 
WisiToken.Parse.LR.Parser.Language_Fixes_Access;
+      Language_Matching_Begin_Tokens : in 
WisiToken.Parse.LR.Parser.Language_Matching_Begin_Tokens_Access;
+      Language_String_ID_Set         : in 
WisiToken.Parse.LR.Parser.Language_String_ID_Set_Access;
+      Text_Rep_File_Name             : in String)
+     return WisiToken.Parse.LR.Parser.Parser;
 
 procedure Gen_Run_Wisi_LR_Text_Rep_Parse;
diff --git a/run_wisi_common_parse.adb b/run_wisi_common_parse.adb
index 88d410f6db..cd9609c98c 100644
--- a/run_wisi_common_parse.adb
+++ b/run_wisi_common_parse.adb
@@ -30,8 +30,8 @@ with GNAT.Traceback.Symbolic;
 with GNATCOLL.Memory;
 with GNATCOLL.Mmap;
 with SAL;
+with Wisi.Parse_Context;
 with WisiToken.Lexer;
-with WisiToken.Parse.LR.McKenzie_Recover;
 with WisiToken.Parse.LR.Parser;
 with WisiToken.Syntax_Trees;
 with WisiToken.Text_IO_Trace;
@@ -46,7 +46,7 @@ package body Run_Wisi_Common_Parse is
 
       Source_File_Name : Ada.Strings.Unbounded.Unbounded_String;
       Language_Params  : Ada.Strings.Unbounded.Unbounded_String;
-      Repeat_Count     : Integer                    := 1;
+      Repeat_Count     : Integer := 1;
 
       case Command is
       when Parse_Partial =>
@@ -84,8 +84,9 @@ package body Run_Wisi_Common_Parse is
       end case;
    end record;
 
-   procedure Usage_1 (Parse_Data : in Wisi.Parse_Data_Type'Class)
+   procedure Usage (Parse_Table : in WisiToken.Parse.LR.Parse_Table_Ptr)
    is
+      use all type WisiToken.Parse.LR.Parse_Table_Ptr;
       use Ada.Text_IO;
    begin
       Put_Line ("usage: parse_partial <post_parse_action> <file_name> [partial 
parse params] [options]");
@@ -94,19 +95,8 @@ package body Run_Wisi_Common_Parse is
       Put_Line ("   or: refactor <refactor_action> <file_name> <edit_begin> 
[options]");
       Put_Line ("   or: command_file <command_file_name> [source_file_name]");
       Put_Line ("post_parse_action: {Navigate | Face | Indent}");
-      Put_Line ("refactor_action:");
-      Parse_Data.Refactor_Help;
       New_Line;
-   end Usage_1;
 
-   procedure Usage
-     (Parse_Data  : in Wisi.Parse_Data_Type'Class;
-      Parse_Table : in WisiToken.Parse.LR.Parse_Table_Ptr)
-   is
-      use all type WisiToken.Parse.LR.Parse_Table_Ptr;
-      use Ada.Text_IO;
-   begin
-      Usage_1 (Parse_Data);
       Put_Line ("partial parse params: begin_byte_pos end_byte_pos 
goal_byte_pos begin_char_pos end_char_pos" &
                   " begin_line begin_indent");
       Put_Line ("options:");
@@ -117,20 +107,10 @@ package body Run_Wisi_Common_Parse is
       Put_Line ("--max_parallel n  : set maximum count of parallel parsers" &
                   (if Parse_Table = null then ""
                    else "; default" & Parse_Table.Max_Parallel'Image));
-      Put_Line ("--mckenzie_check_limit n  : set error recover token check 
limit" &
-                  (if Parse_Table = null then ""
-                   else "; default" & 
Parse_Table.McKenzie_Param.Check_Limit'Image));
-      Put_Line ("--mckenzie_check_delta n  : set error recover delta check 
limit" &
-                  (if Parse_Table = null then ""
-                   else "; default" & 
Parse_Table.McKenzie_Param.Check_Delta_Limit'Image));
-      Put_Line ("--mckenzie_enqueue_limit n  : set error recover token enqueue 
limit" &
-                  (if Parse_Table = null then ""
-                   else "; default" & 
Parse_Table.McKenzie_Param.Enqueue_Limit'Image));
-      Put_Line ("--mckenzie_full_explore : force error recover explore all 
solutions");
-      Put_Line ("--mckenzie_high_cost : error recover report high cost 
solutions");
-      Put_Line ("--mckenzie_zombie_limit n  : set error recover token zombie 
limit" &
-                  (if Parse_Table = null then ""
-                   else "; default" & 
Parse_Table.McKenzie_Param.Zombie_Limit'Image));
+      Put_Line ("--mckenzie_options : set error recover parameters");
+      if Parse_Table /= null then
+         WisiToken.Parse.LR.Set_McKenzie_Help;
+      end if;
       Put_Line ("--repeat_count n : repeat parse count times, for profiling; 
default 1");
       Put_Line ("--log <file_name> : output verbosity trace to <file_name>");
       New_Line;
@@ -191,10 +171,7 @@ package body Run_Wisi_Common_Parse is
       Close (File);
    end Read_Source_File;
 
-   function Command_File_Name
-     (Parse_Data : in     Wisi.Parse_Data_Type'Class;
-      Next_Arg   :    out Integer)
-     return Command_Line_Params
+   function Command_File_Name (Next_Arg : out Integer) return 
Command_Line_Params
    --  Read command and source file name from command line.
    is
       use Ada.Command_Line;
@@ -202,7 +179,7 @@ package body Run_Wisi_Common_Parse is
       Command : Command_Type;
    begin
       if Argument_Count < 2 then
-         Usage (Parse_Data, null);
+         Usage (null);
          Set_Exit_Status (Failure);
          raise Finish;
       end if;
@@ -245,13 +222,13 @@ package body Run_Wisi_Common_Parse is
 
    when E : others =>
       Ada.Text_IO.Put_Line (Ada.Exceptions.Exception_Name (E) & ": " & 
Ada.Exceptions.Exception_Message (E));
-      Usage (Parse_Data, null);
+      Usage (null);
       Set_Exit_Status (Failure);
       raise SAL.Parameter_Error;
    end Command_File_Name;
 
    procedure Remaining_Command_Params
-     (Parser : in out WisiToken.Parse.LR.Parser.Parser;
+     (Parser : in out WisiToken.Parse.Base_Parser'Class;
       Params : in out Command_Line_Params;
       Arg    : in out Integer)
    --  Command_File_Name reads the first few command line arguments
@@ -260,7 +237,11 @@ package body Run_Wisi_Common_Parse is
       use WisiToken;
    begin
       if Argument_Count >= Arg and then Argument (Arg) = "--help" then
-         Usage (Wisi.Parse_Data_Type'Class (Parser.User_Data.all), 
Parser.Table);
+         Usage
+           (if Parser in WisiToken.Parse.LR.Parser.Parser
+            then WisiToken.Parse.LR.Parser.Parser (Parser).Table
+            else null);
+         Wisi.Parse_Data_Type (Parser.User_Data.all).Refactor_Help;
          raise Finish;
       end if;
 
@@ -310,18 +291,23 @@ package body Run_Wisi_Common_Parse is
 
    when E : others =>
       Ada.Text_IO.Put_Line (Ada.Exceptions.Exception_Name (E) & ": " & 
Ada.Exceptions.Exception_Message (E));
-      Usage (Wisi.Parse_Data_Type'Class (Parser.User_Data.all), Parser.Table);
+      Usage
+        (if Parser in WisiToken.Parse.LR.Parser.Parser
+         then WisiToken.Parse.LR.Parser.Parser (Parser).Table
+         else null);
+      Wisi.Parse_Data_Type (Parser.User_Data.all).Refactor_Help;
       Set_Exit_Status (Failure);
       raise SAL.Parameter_Error;
    end Remaining_Command_Params;
 
    procedure Command_Options
-     (Parser : in out WisiToken.Parse.LR.Parser.Parser;
+     (Parser : in out WisiToken.Parse.Base_Parser'Class;
       Params : in out Command_Line_Params;
       Arg    : in out Integer)
    is
       use Ada.Command_Line;
       use WisiToken;
+      use all type WisiToken.Parse.LR.Parse_Table_Ptr;
    begin
       loop
          exit when Arg > Argument_Count;
@@ -347,33 +333,14 @@ package body Run_Wisi_Common_Parse is
             Params.Language_Params := +Argument (Arg + 1);
             Arg := @ + 2;
 
-         elsif Argument (Arg) = "--max_parallel" then
-            Parser.Table.Max_Parallel := SAL.Base_Peek_Type'Value (Argument 
(Arg + 1));
-            Arg := @ + 2;
-
-         elsif Argument (Arg) = "--mckenzie_check_delta" then
-            Parser.Table.McKenzie_Param.Check_Delta_Limit := Integer'Value 
(Argument (Arg + 1));
-            Arg := @ + 2;
-
-         elsif Argument (Arg) = "--mckenzie_check_limit" then
-            Parser.Table.McKenzie_Param.Check_Limit := 
WisiToken.Syntax_Trees.Sequential_Index'Value
-              (Argument (Arg + 1));
-            Arg := @ + 2;
-
-         elsif Argument (Arg) = "--mckenzie_enqueue_limit" then
-            Parser.Table.McKenzie_Param.Enqueue_Limit := Integer'Value 
(Argument (Arg + 1));
-            Arg := @ + 2;
-
-         elsif Argument (Arg) = "--mckenzie_full_explore" then
-            WisiToken.Parse.LR.McKenzie_Recover.Force_Full_Explore := True;
-            Arg := @ + 1;
-
-         elsif Argument (Arg) = "--mckenzie_high_cost" then
-            WisiToken.Parse.LR.McKenzie_Recover.Force_High_Cost_Solutions := 
True;
-            Arg := @ + 1;
-
-         elsif Argument (Arg) = "--mckenzie_zombie_limit" then
-            Parser.Table.McKenzie_Param.Zombie_Limit := Integer'Value 
(Argument (Arg + 1));
+         elsif Argument (Arg) = "--mckenzie_options" then
+            if Parser in WisiToken.Parse.LR.Parser.Parser then
+               declare
+                  LR_Parser : WisiToken.Parse.LR.Parser.Parser renames 
WisiToken.Parse.LR.Parser.Parser (Parser);
+               begin
+                  WisiToken.Parse.LR.Set_McKenzie_Options 
(LR_Parser.Table.McKenzie_Param, Argument (Arg + 1));
+               end;
+            end if;
             Arg := @ + 2;
 
          elsif Argument (Arg) = "--repeat_count" then
@@ -391,7 +358,11 @@ package body Run_Wisi_Common_Parse is
 
          else
             Ada.Text_IO.Put_Line ("unrecognized option: '" & Argument (Arg) & 
"'");
-            Usage (Wisi.Parse_Data_Type'Class (Parser.User_Data.all), 
Parser.Table);
+            Usage
+              (if Parser in WisiToken.Parse.LR.Parser.Parser
+               then WisiToken.Parse.LR.Parser.Parser (Parser).Table
+               else null);
+            Wisi.Parse_Data_Type (Parser.User_Data.all).Refactor_Help;
             Set_Exit_Status (Failure);
             raise SAL.Parameter_Error;
          end if;
@@ -402,14 +373,23 @@ package body Run_Wisi_Common_Parse is
 
    when E : others =>
       Ada.Text_IO.Put_Line (Ada.Exceptions.Exception_Name (E) & ": " & 
Ada.Exceptions.Exception_Message (E));
-      Usage (Wisi.Parse_Data_Type'Class (Parser.User_Data.all), Parser.Table);
+      Usage
+        (if Parser in WisiToken.Parse.LR.Parser.Parser
+         then WisiToken.Parse.LR.Parser.Parser (Parser).Table
+         else null);
+      Wisi.Parse_Data_Type (Parser.User_Data.all).Refactor_Help;
       Set_Exit_Status (Failure);
       raise SAL.Parameter_Error;
    end Command_Options;
 
-   procedure Put_Errors (Parser : in WisiToken.Parse.LR.Parser.Parser)
-   is begin
-      if Parser.Tree.Stream_Count = 0 then
+   procedure Put_Errors (Parser : in WisiToken.Parse.Base_Parser_Access)
+   is
+      use all type SAL.Base_Peek_Type;
+      use WisiToken.Syntax_Trees;
+   begin
+      if Parser.Tree.Shared_Stream = Invalid_Stream_ID then
+         --  Parse completed. If Tree.Finalize raised an exception,
+         --  Tree.Stream_Count is unreliable.
          Parser.Put_Errors;
 
       elsif Parser.Tree.Stream_Count >= 2 then
@@ -423,7 +403,7 @@ package body Run_Wisi_Common_Parse is
 
    procedure Process_Command
      (Parse_Context : in out Wisi.Parse_Context.Parse_Context_Access;
-      Language      : in     Wisi.Parse_Context.Language;
+      Factory       : in     WisiToken.Parse.Factory;
       Line          : in     String;
       Trace         : in     WisiToken.Trace_Access)
    is
@@ -460,7 +440,7 @@ package body Run_Wisi_Common_Parse is
       when File =>
          if Ada.Strings.Unbounded.Length (Parse_Context.File_Name) > 0 then
             --  Changing files
-            Parse_Context := Wisi.Parse_Context.Create_No_File (Language, 
Trace);
+            Parse_Context := Wisi.Parse_Context.Create_No_File (Factory, 
Trace);
          end if;
 
          declare
@@ -494,8 +474,15 @@ package body Run_Wisi_Common_Parse is
            (Line (Last + 1 .. Line'Last));
 
       when McKenzie_Options =>
-         WisiToken.Parse.LR.Set_McKenzie_Options
-           (Parse_Context.Parser.Table.McKenzie_Param, Line (Last + 1 .. 
Line'Last));
+         if Parse_Context.Parser.all in WisiToken.Parse.LR.Parser.Parser then
+            declare
+               LR_Parser : WisiToken.Parse.LR.Parser.Parser renames 
WisiToken.Parse.LR.Parser.Parser
+                 (Parse_Context.Parser.all);
+            begin
+               WisiToken.Parse.LR.Set_McKenzie_Options
+                 (LR_Parser.Table.McKenzie_Param, Line (Last + 1 .. 
Line'Last));
+            end;
+         end if;
 
       when Memory_Report_Reset =>
          WisiToken.Memory_Baseline := 
GNATCOLL.Memory.Get_Ada_Allocations.Current;
@@ -557,6 +544,12 @@ package body Run_Wisi_Common_Parse is
             Ada.Text_IO.Put_Line
               ("(parse_error """ & Ada.Exceptions.Exception_Name (E) & " " &
                  Ada.Exceptions.Exception_Message (E) & """)");
+
+         when WisiToken.Validate_Error =>
+            Put_Errors (Parse_Context.Parser);
+            --  Ensure we don't lose the debug state
+            Parse_Context.Frozen := True;
+            raise WisiToken.Parse_Error with "validate error; parse_context 
frozen";
          end;
 
       when Post_Parse =>
@@ -589,7 +582,7 @@ package body Run_Wisi_Common_Parse is
                Report_Memory (Trace.all, Prefix => False);
             end if;
 
-            Wisi.Parse_Data_Type'Class 
(Parse_Context.Parser.User_Data.all).Put (Parse_Context.Parser);
+            Wisi.Parse_Data_Type'Class 
(Parse_Context.Parser.User_Data.all).Put (Parse_Context.Parser.all);
          end;
 
       when Read_Tree =>
@@ -691,7 +684,7 @@ package body Run_Wisi_Common_Parse is
       end case;
    end Process_Command;
 
-   procedure Parse_File (Language : in Wisi.Parse_Context.Language; Trace : in 
WisiToken.Trace_Access)
+   procedure Parse_File (Factory : in WisiToken.Parse.Factory; Trace : in 
WisiToken.Trace_Access)
    is
       use Ada.Text_IO;
       use WisiToken;
@@ -702,14 +695,14 @@ package body Run_Wisi_Common_Parse is
          use all type Wisi.Base_Post_Parse_Action_Type;
 
          Arg       : Integer;
-         Cl_Params : Command_Line_Params := Command_File_Name 
(Language.Parse_Data_Template.all, Arg);
+         Cl_Params : Command_Line_Params := Command_File_Name (Arg);
 
          Parse_Context : Wisi.Parse_Context.Parse_Context_Access :=
            (if Length (Cl_Params.Source_File_Name) > 0 -- can be empty for 
Command_File
-            then Wisi.Parse_Context.Find_Create (-Cl_Params.Source_File_Name, 
Language, Trace)
-            else Wisi.Parse_Context.Create_No_File (Language, Trace));
+            then Wisi.Parse_Context.Find_Create (-Cl_Params.Source_File_Name, 
Factory, Trace)
+            else Wisi.Parse_Context.Create_No_File (Factory, Trace));
 
-         Parser : WisiToken.Parse.LR.Parser.Parser renames 
Parse_Context.Parser;
+         Parser : WisiToken.Parse.Base_Parser'Class renames 
Parse_Context.Parser.all;
 
          Parse_Data : Wisi.Parse_Data_Type'Class renames 
Wisi.Parse_Data_Type'Class (Parser.User_Data.all);
       begin
@@ -745,14 +738,19 @@ package body Run_Wisi_Common_Parse is
          case Cl_Params.Command is
          when Parse_Partial =>
             if Cl_Params.Partial_Begin_Byte_Pos = WisiToken.Invalid_Buffer_Pos 
then
+               --  Actually a full parse.
                Cl_Params.Partial_Begin_Byte_Pos := WisiToken.Buffer_Pos'First;
                Cl_Params.Partial_Begin_Char_Pos := WisiToken.Buffer_Pos'First;
                Cl_Params.Partial_End_Byte_Pos   := Base_Buffer_Pos 
(Parse_Context.Text_Buffer_Byte_Last);
                Cl_Params.Partial_End_Char_Pos   := Base_Buffer_Pos 
(Parse_Context.Text_Buffer_Char_Last);
+
+               Cl_Params.Partial_Goal_Byte_Pos := 
Cl_Params.Partial_End_Byte_Pos;
+               Cl_Params.Partial_Goal_Char_Pos := 
Cl_Params.Partial_End_Char_Pos;
             else
                Parser.Partial_Parse_Active.all    := True;
                Parser.Partial_Parse_Byte_Goal.all := 
Cl_Params.Partial_Goal_Byte_Pos;
             end if;
+
          when Parse_Incremental =>
             if Cl_Params.Inc_Begin_Byte_Pos = WisiToken.Invalid_Buffer_Pos then
                Cl_Params.Inc_Begin_Byte_Pos := WisiToken.Buffer_Pos'First;
@@ -808,18 +806,19 @@ package body Run_Wisi_Common_Parse is
                   end if;
                exception
                when WisiToken.Syntax_Error =>
-                  Put_Errors (Parser);
+                  Put_Errors (Parse_Context.Parser);
                   Put_Line ("(parse_error)");
 
                when E : WisiToken.Parse_Error =>
-                  Put_Errors (Parser);
+                  Put_Errors (Parse_Context.Parser);
                   Put_Line ("(parse_error """ & Ada.Exceptions.Exception_Name 
(E) & " " &
                               Ada.Exceptions.Exception_Message (E) & """)");
 
                when E : others => -- includes Fatal_Error
-                  Put_Errors (Parser);
+                  Put_Errors (Parse_Context.Parser);
                   Put_Line ("(error """ & Ada.Exceptions.Exception_Name (E) & 
" " &
                               Ada.Exceptions.Exception_Message (E) & """)");
+                  raise;
                end;
             end loop;
 
@@ -854,11 +853,11 @@ package body Run_Wisi_Common_Parse is
 
             exception
             when WisiToken.Syntax_Error =>
-               Put_Errors (Parser);
+               Put_Errors (Parse_Context.Parser);
                Put_Line ("(parse_error)");
 
             when E : WisiToken.Parse_Error =>
-               Put_Errors (Parser);
+               Put_Errors (Parse_Context.Parser);
                Put_Line ("(parse_error """ & Ada.Exceptions.Exception_Name (E) 
& " " &
                            Ada.Exceptions.Exception_Message (E) & """)");
             end;
@@ -890,7 +889,7 @@ package body Run_Wisi_Common_Parse is
                     (Parse_Context.Text_Buffer, 
Parse_Context.Text_Buffer_Byte_Last, Cl_Params.Source_File_Name);
 
                   Parser.Parse (Log_File, KMN_List);
-                  Wisi.Put_Errors (Parse_Context.Parser.Tree);
+                  Wisi.Put_Errors (Parser.Tree);
 
                   if Cl_Params.Inc_Post_Parse_Action /= None then
                      Parse_Data.Reset_Post_Parse
@@ -912,11 +911,11 @@ package body Run_Wisi_Common_Parse is
 
                exception
                when WisiToken.Syntax_Error =>
-                  Put_Errors (Parser);
+                  Put_Errors (Parse_Context.Parser);
                   Put_Line ("(parse_error)");
 
                when E : WisiToken.Parse_Error =>
-                  Put_Errors (Parser);
+                  Put_Errors (Parse_Context.Parser);
                   Put_Line ("(parse_error """ & Ada.Exceptions.Exception_Name 
(E) & " " &
                               Ada.Exceptions.Exception_Message (E) & """)");
                end;
@@ -954,7 +953,7 @@ package body Run_Wisi_Common_Parse is
                         if Line (1 .. 2) = "--" then
                            null;
                         else
-                           Process_Command (Parse_Context, Language, Line, 
Trace);
+                           Process_Command (Parse_Context, Factory, Line, 
Trace);
                            Trace.New_Line;
                         end if;
                      end if;
diff --git a/run_wisi_common_parse.ads b/run_wisi_common_parse.ads
index b6023b04ff..67a5b8c3e1 100644
--- a/run_wisi_common_parse.ads
+++ b/run_wisi_common_parse.ads
@@ -19,11 +19,10 @@
 pragma License (GPL);
 
 with Wisi;
-with WisiToken;
-with Wisi.Parse_Context;
+with WisiToken.Parse;
 package Run_Wisi_Common_Parse is
 
-   procedure Parse_File (Language : in Wisi.Parse_Context.Language; Trace : in 
WisiToken.Trace_Access);
+   procedure Parse_File (Factory : in WisiToken.Parse.Factory; Trace : in 
WisiToken.Trace_Access);
    --  Reads command line, processes command(s).
 
 end Run_Wisi_Common_Parse;
diff --git a/sal-gen_definite_doubly_linked_lists.adb 
b/sal-gen_definite_doubly_linked_lists.adb
index a189399b79..2697aa9829 100644
--- a/sal-gen_definite_doubly_linked_lists.adb
+++ b/sal-gen_definite_doubly_linked_lists.adb
@@ -261,10 +261,10 @@ package body SAL.Gen_Definite_Doubly_Linked_Lists is
       null;
    end Insert;
 
-   function Persistent_Ref (Position : in Cursor) return access Element_Type
+   function Unchecked_Ref (Position : in Cursor) return access Element_Type
    is begin
       return Position.Ptr.Element'Access;
-   end Persistent_Ref;
+   end Unchecked_Ref;
 
    function Constant_Reference (Container : in List; Position : in Cursor) 
return Constant_Reference_Type
    is
diff --git a/sal-gen_definite_doubly_linked_lists.ads 
b/sal-gen_definite_doubly_linked_lists.ads
index 75016694f1..bf78d1b923 100644
--- a/sal-gen_definite_doubly_linked_lists.ads
+++ b/sal-gen_definite_doubly_linked_lists.ads
@@ -103,8 +103,9 @@ package SAL.Gen_Definite_Doubly_Linked_Lists is
      return Cursor;
    --  If Before is No_Element, insert after Last.
 
-   function Persistent_Ref (Position : in Cursor) return access Element_Type
+   function Unchecked_Ref (Position : in Cursor) return access Element_Type
    with Pre => Has_Element (Position);
+   --  For building higher level containers
 
    type Constant_Reference_Type (Element : not null access constant 
Element_Type) is private with
      Implicit_Dereference => Element;
diff --git a/sal-gen_indefinite_doubly_linked_lists.adb 
b/sal-gen_indefinite_doubly_linked_lists.adb
index fdfef03c33..86f0574507 100644
--- a/sal-gen_indefinite_doubly_linked_lists.adb
+++ b/sal-gen_indefinite_doubly_linked_lists.adb
@@ -24,6 +24,22 @@ pragma License (Modified_GPL);
 
 package body SAL.Gen_Indefinite_Doubly_Linked_Lists is
 
+   procedure Delete_Node (Container : in out List; Node : in out Node_Access)
+   is begin
+      if Node.Next = null then
+         Container.Tail := Node.Prev;
+      else
+         Node.Next.Prev := Node.Prev;
+      end if;
+      if Node.Prev = null then
+         Container.Head := Node.Next;
+      else
+         Node.Prev.Next := Node.Next;
+      end if;
+      Free (Node.Element);
+      Free (Node);
+   end Delete_Node;
+
    ---------
    --  Public operations, declaration order.
 
@@ -77,6 +93,14 @@ package body SAL.Gen_Indefinite_Doubly_Linked_Lists is
       return Container.Count;
    end Length;
 
+   procedure Delete_First (Container : in out List)
+   is
+      Node : Node_Access := Container.Head;
+   begin
+      Delete_Node (Container, Node);
+      Container.Count := Container.Count - 1;
+   end Delete_First;
+
    procedure Append (Container : in out List; Element : in Element_Type)
    is
       New_Node : constant Node_Access := new Node_Type'
@@ -190,21 +214,8 @@ package body SAL.Gen_Indefinite_Doubly_Linked_Lists is
    end Append;
 
    procedure Delete (Container : in out List; Position : in out Cursor)
-   is
-      Node : Node_Access renames Position.Ptr;
-   begin
-      if Node.Next = null then
-         Container.Tail := Node.Prev;
-      else
-         Node.Next.Prev := Node.Prev;
-      end if;
-      if Node.Prev = null then
-         Container.Head := Node.Next;
-      else
-         Node.Prev.Next := Node.Next;
-      end if;
-      Free (Node.Element);
-      Free (Node);
+   is begin
+      Delete_Node (Container, Position.Ptr);
       Position        := (Ptr => null);
       Container.Count := Container.Count - 1;
    end Delete;
diff --git a/sal-gen_indefinite_doubly_linked_lists.ads 
b/sal-gen_indefinite_doubly_linked_lists.ads
index b9d3022256..d8e9fad799 100644
--- a/sal-gen_indefinite_doubly_linked_lists.ads
+++ b/sal-gen_indefinite_doubly_linked_lists.ads
@@ -44,8 +44,12 @@ package SAL.Gen_Indefinite_Doubly_Linked_Lists is
    overriding procedure Finalize (Container : in out List);
    --  Free all items in List.
 
+   procedure Clear (Container : in out List) renames Finalize;
+
    function Length (Container : in List) return Base_Peek_Type;
 
+   procedure Delete_First (Container : in out List);
+
    procedure Append (Container : in out List; Element : in Element_Type);
 
    procedure Prepend (Container : in out List; Element : in Element_Type);
@@ -105,7 +109,6 @@ private
    type Node_Access is access Node_Type;
    type Element_Access is access Element_Type;
 
-
    type Node_Type is record
       Element : Element_Access;
       Prev    : Node_Access;
diff --git a/sal.adb b/sal.adb
index d90195600d..1cfe875633 100644
--- a/sal.adb
+++ b/sal.adb
@@ -28,7 +28,7 @@ package body SAL is
 
    function Version return String is
    begin
-      return "SAL 3.6";
+      return "SAL 3.7";
    end Version;
 
    function String_Compare (Left, Right : in String) return Compare_Result
diff --git a/standard_common.gpr b/standard_common.gpr
index 3d4652ee6c..520c5f6e6e 100644
--- a/standard_common.gpr
+++ b/standard_common.gpr
@@ -2,7 +2,7 @@
 --
 --  Standard settings for all of Stephe's Ada projects.
 --
---  Copyright (C) 2018 - 2021 Free Software Foundation, Inc.
+--  Copyright (C) 2018 - 2022 Free Software Foundation, Inc.
 --
 --  This program is free software; you can redistribute it and/or
 --  modify it under terms of the GNU General Public License as
@@ -18,6 +18,7 @@
 
 project Standard_Common is
    for Source_Dirs use ();
+   for Create_Missing_Dirs use "True";
 
    type Build_Type is ("Debug", "Normal");
    Build : Build_Type := External ("Standard_Common_Build", "Normal");
diff --git a/wisi-fringe.el b/wisi-fringe.el
index 54146a577e..4d43a07bb2 100644
--- a/wisi-fringe.el
+++ b/wisi-fringe.el
@@ -1,4 +1,4 @@
-;;; wisi-fringe.el --- show approximate error locations in the fringe
+;;; wisi-fringe.el --- show approximate error locations in the fringe  -*- 
lexical-binding: t; -*-
 ;;
 ;; Copyright (C) 2018 - 2019, 2021 - 2022  Free Software Foundation, Inc.
 ;;
@@ -17,7 +17,7 @@
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 ;;
-;; Design:
+;;; Design:
 ;;
 ;; Bitmaps are displayed in the fringe by putting a 'display property
 ;; on buffer text. However, just doing that also hides the buffer
@@ -29,6 +29,10 @@
 ;; single-pixel lines in the right fringe, and mark error lines with
 ;; ’!!’ in the left fringe.
 
+;;; Code:
+
+(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.
@@ -117,7 +121,7 @@ in the window."
   (let* ((scale (/ window-lines (float buffer-lines)))
         (line (floor (* scale error-line)))
         (rem (- error-line (floor (/ line scale)))))
-    (cons (+ window-line-first line) (lsh 1 (min 5 (floor (* rem (* 6 
scale))))))))
+    (cons (+ window-line-first line) (ash 1 (min 5 (floor (* rem (* 6 
scale))))))))
 
 (defun wisi-fringe-clean ()
   "Remove all wisi-fringe marks."
diff --git a/wisi-parse-common.el b/wisi-parse-common.el
index 28df0aa01b..65e5d1cb0e 100644
--- a/wisi-parse-common.el
+++ b/wisi-parse-common.el
@@ -22,6 +22,12 @@
 ;;; Code:
 (require 'cl-lib)
 
+(defcustom wisi-incremental-parse-enable nil
+  "If non-nil, use incremental parse when possible."
+  :type 'boolean
+  :group 'wisi
+  :safe #'booleanp)
+
 (defcustom wisi-partial-parse-threshold 100001
   "Minimum size that will be parsed by each call to the parser.
 A parse is always requested at a point (or on a region); the
@@ -33,7 +39,7 @@ is properly indented. Most navigate parses ignore this setting
 and parse the whole buffer."
   :type 'integer
   :group 'wisi
-  :safe 'integerp)
+  :safe #'integerp)
 (make-variable-buffer-local 'wisi-partial-parse-threshold)
 
 (defcustom wisi-save-all-changes nil
@@ -46,6 +52,16 @@ for the changes. The filename is the visited file name with
   :group 'wisi
   :safe 'booleanp)
 
+(defcustom wisi-save-text-tree nil
+  "When non-nil, save the parser's copy of the full text and the
+current parse tree before each change, to aid in reproducing
+bugs. The full text is written to a file whose name is the
+visited file name with \"-wisi-prev-text\"' appended. The tree
+can be dumped to a file via the tree query dump-prev."
+  :type 'boolean
+  :group 'wisi
+  :safe #'booleanp)
+
 (cl-defstruct (wisi--lexer-error)
   pos ;; position (integer) in buffer where error was detected.
   message  ;; string error message
@@ -146,6 +162,9 @@ region BEGIN END that starts and ends at points the parser 
can
 handle gracefully."
   (cons begin end))
 
+(cl-defgeneric wisi-parse-save-text-tree-auto (parser enable)
+  "Implement `wisi-save-text-tree'.")
+
 (defvar-local wisi-parser-shared nil
   "The current shared wisi parser; a ‘wisi-parser-shared’ object.
 There is one parser object per language; `wisi-parser-shared' is a
@@ -154,6 +173,13 @@ buffer-local reference to that shared object.")
 (defvar-local wisi-parser-local nil
   "Buffer-local values used by the wisi parser; a ‘wisi-parser-local’ object.")
 
+(defvar-local wisi--changes nil
+  "Cached list of args to wisi-after-change, for incremental parse.
+Each element is
+(INSERT-BEGIN-BYTE-POS INSERT-BEGIN-CHAR-POS
+ INSERT-END-BYTE-POS INSERT-END-CHAR-POS
+ DELETED-BYTE-COUNT DELETED-CHAR-COUNT INSERTED-TEXT)")
+
 (defconst wisi-post-parse-actions '(navigate face indent none refactor query 
debug)
   "Actions that the parser can perform after parsing.
 Only navigate thru indent are valid for partial parse.")
@@ -240,7 +266,7 @@ have been previously parsed by `wisi-parse-current' or
     (parent                .   3)
     (child                 .   4)
     (print                 .   5)
-    (dump                  .   6)
+    (dump                  .   6) ;; dump-prev is not here because it queries 
a different tree.
     )
   "Query values for `wisi-parse-tree-query'.")
 
@@ -436,7 +462,7 @@ Assumes the buffer is fully parsed."
 1 : report parse errors (for running tests)"
   :type 'integer
   :group 'wisi
-  :safe 'integerp)
+  :safe #'integerp)
 
 ;; The following parameters are easily changeable for debugging.
 (defcustom wisi-parser-verbosity ""
@@ -446,7 +472,7 @@ Examples:
 debug=1 lexer=1 parse=2 action=3"
   :type 'string
   :group 'wisi
-  :safe 'stringp)
+  :safe #'stringp)
 (make-variable-buffer-local 'wisi-parser-verbosity)
 
 (defcustom wisi-mckenzie-zombie-limit nil
@@ -457,7 +483,7 @@ value gives better solutions, but may cause too many 
parsers to
 be active at once.  If nil, uses %mckenzie_zombie_limit value from grammar 
file."
   :type 'integer
   :group 'wisi
-  :safe 'integerp)
+  :safe #'integerp)
 (make-variable-buffer-local 'wisi-mckenzie-zombie-limit)
 
 (defcustom wisi-mckenzie-enqueue-limit nil
@@ -467,7 +493,7 @@ Higher value has more recover power, but will be slower to 
fail.
 If nil, uses %mckenzie_enqueue_limit value from grammar file."
   :type 'integer
   :group 'wisi
-  :safe 'integerp)
+  :safe #'integerp)
 (make-variable-buffer-local 'wisi-mckenzie-enqueue-limit)
 
 (defcustom wisi-parse-max-parallel nil
@@ -478,7 +504,7 @@ the grammar has excessive conflicts. If nil, uses 
%max_parallel
 value from grammar file (default 15)"
   :type 'integer
   :group 'wisi
-  :safe 'integerp)
+  :safe #'integerp)
 (make-variable-buffer-local 'wisi-parse-max-parallel)
 
 ;; end of easily changeable parameters
@@ -504,7 +530,7 @@ Normally set from a language-specific option.")
      "%s:%d:%d: %s"
        (buffer-name) ;; buffer-file-name is sometimes nil here!?
        line col
-       (apply 'format message args))))
+       (apply #'format message args))))
 
 (defvar wisi-parse-error nil)
 (put 'wisi-parse-error
@@ -591,23 +617,6 @@ Signals an error if `wisi-incremental-parse-enable' is 
nil."
     (user-error "wisi-parse-incremental-none with 
wisi-incremental-parse-enable nil"))
   (save-excursion (wisi-parse-incremental wisi-parser-shared 'none)))
 
-(defun wisi-replay-kbd-macro (macro)
-  "Replay keyboard macro MACRO into current buffer,
-with incremental parse after each key event."
-  (unless wisi-incremental-parse-enable
-    (user-error "wisi-incremental-parse-enable nil; use EMACS_SKIP_UNLESS"))
-  (let ((i 0))
-    (while (< i  (length macro))
-      (execute-kbd-macro (make-vector 1 (aref macro i)))
-      (save-excursion
-       (condition-case err
-           (wisi-parse-incremental wisi-parser-shared 'none)
-         (wisi-parse-error
-          (when (< 0 wisi-debug)
-            ;; allow continuing when parser throws parse-error
-            (signal (car err) (cdr err))))))
-      (setq i (1+ i)))))
-
 (defun wisi-replay-undo (count)
   "Execute `undo' COUNT times, delaying in between each."
   (let ((i 0))
diff --git a/wisi-parse_context.adb b/wisi-parse_context.adb
index 5a908f0599..62654c0a0c 100644
--- a/wisi-parse_context.adb
+++ b/wisi-parse_context.adb
@@ -15,7 +15,6 @@ pragma License (GPL);
 
 with Ada.Directories;
 with Ada.Exceptions;
-with Ada.Finalization;
 with Ada.Tags;
 with GNAT.OS_Lib;
 with SAL.Gen_Unbounded_Definite_Red_Black_Trees;
@@ -33,37 +32,20 @@ package body Wisi.Parse_Context is
    Map : File_Parse_Context_Maps.Tree;
 
    function Create_No_File
-     (Language : in Wisi.Parse_Context.Language;
-      Trace    : in WisiToken.Trace_Access)
+     (Factory : in WisiToken.Parse.Factory;
+      Trace   : in WisiToken.Trace_Access)
      return Parse_Context_Access
    is
       use WisiToken;
    begin
-      return Result : constant Parse_Context_Access :=
-        (new Parse_Context'
-           (File_Name                         => +"",
-            Text_Buffer                       => null,
-            Text_Buffer_Byte_Last             => 0,
-            Text_Buffer_Char_Last             => 0,
-            Parser                            => 
WisiToken.Parse.LR.Parser.Parser'
-              (Ada.Finalization.Limited_Controlled with
-               User_Data                      => Wisi.New_User_Data 
(Language.Parse_Data_Template.all),
-               Table                          => Language.Table,
-               Productions                    => Language.Productions,
-               Language_Fixes                 => Language.Fixes,
-               Language_Matching_Begin_Tokens => 
Language.Matching_Begin_Tokens,
-               Language_String_ID_Set         => Language.String_ID_Set,
-               Partial_Parse_Active           => Language.Partial_Parse_Active,
-               Partial_Parse_Byte_Goal        => 
Language.Partial_Parse_Byte_Goal,
-               others                         => <>),
-            Root_Save_Edited_Name             => <>,
-            Save_Edited_Count                 => <>))
+      return Result : constant Parse_Context_Access := new Parse_Context
       do
-         Result.Parser.Tree.Lexer := Language.Lexer;
+         Result.Parser := Factory.all;
+
          if Trace_Incremental_Parse > Outline then
             Trace.Put_Line
               ("parse_context (no file) created, language " & 
Ada.Tags.Expanded_Name
-                 (Language.Parse_Data_Template.all'Tag));
+                 (Result.Parser.User_Data'Tag));
             if Trace_Memory > Outline then
                Report_Memory (Trace.all, Prefix => True);
             end if;
@@ -73,10 +55,10 @@ package body Wisi.Parse_Context is
 
    procedure Create_No_Text
      (File_Name : in String;
-      Language  : in Wisi.Parse_Context.Language;
+      Factory   : in WisiToken.Parse.Factory;
       Trace     : in WisiToken.Trace_Access)
    is
-      Temp : constant Parse_Context_Access := Create_No_File (Language, Trace);
+      Temp : constant Parse_Context_Access := Create_No_File (Factory, Trace);
    begin
       Set_File (File_Name, Temp);
    end Create_No_Text;
@@ -97,7 +79,7 @@ package body Wisi.Parse_Context is
 
    function Find_Create
      (File_Name : in String;
-      Language  : in Wisi.Parse_Context.Language;
+      Factory   : in WisiToken.Parse.Factory;
       Trace     : in WisiToken.Trace_Access)
      return Parse_Context_Access
    is begin
@@ -113,40 +95,29 @@ package body Wisi.Parse_Context is
       begin
          if Has_Element (Found) then
             return Result : constant Parse_Context_Access := Element (Found) do
-               if Language.Descriptor /= Result.Parser.Tree.Lexer.Descriptor 
then
-                  raise WisiToken.User_Error with "language does not match for 
buffer '" & File_Name & "'";
-               end if;
                if Trace_Incremental_Parse > Outline then
                   Trace.Put_Line ("parse_context found");
                end if;
             end return;
          end if;
 
-         return Result : constant Parse_Context_Access :=
-           (new Parse_Context'
-              (File_Name                         => +File_Name,
-               Text_Buffer                       => null,
-               Text_Buffer_Byte_Last             => 0,
-               Text_Buffer_Char_Last             => 0,
-               Parser                            => 
WisiToken.Parse.LR.Parser.Parser'
-                 (Ada.Finalization.Limited_Controlled with
-                  User_Data                      => Wisi.New_User_Data 
(Language.Parse_Data_Template.all),
-                  Table                          => Language.Table,
-                  Productions                    => Language.Productions,
-                  Language_Fixes                 => Language.Fixes,
-                  Language_Matching_Begin_Tokens => 
Language.Matching_Begin_Tokens,
-                  Language_String_ID_Set         => Language.String_ID_Set,
-                  Partial_Parse_Active           => 
Language.Partial_Parse_Active,
-                  Partial_Parse_Byte_Goal        => 
Language.Partial_Parse_Byte_Goal,
-                  others                         => <>),
-               Root_Save_Edited_Name             => <>,
-               Save_Edited_Count                 => <>))
+         return Result               : constant Parse_Context_Access :=
+           new Parse_Context'
+             (File_Name             => +File_Name,
+              Text_Buffer           => null,
+              Text_Buffer_Byte_Last => 0,
+              Text_Buffer_Char_Last => 0,
+              Parser                => Factory.all,
+              Prev_Tree             => <>,
+              Save_Prev_Text_Tree   => False,
+              Root_Save_Edited_Name => <>,
+              Save_Edited_Count     => <>,
+              Frozen                => False)
          do
-            Result.Parser.Tree.Lexer := Language.Lexer;
             Map.Insert (Result);
             if Trace_Incremental_Parse > Outline then
                Trace.Put_Line
-                 ("parse_context created, language " & Ada.Tags.Expanded_Name 
(Language.Parse_Data_Template.all'Tag));
+                 ("parse_context created, language " & Ada.Tags.Expanded_Name 
(Result.Parser.User_Data'Tag));
                if Trace_Memory > Outline then
                   Report_Memory (Trace.all, Prefix => True);
                end if;
@@ -157,7 +128,6 @@ package body Wisi.Parse_Context is
 
    function Find
      (File_Name : in String;
-      Language  : in Wisi.Parse_Context.Language;
       Have_Text : in Boolean := False)
      return Parse_Context_Access
    is begin
@@ -174,9 +144,6 @@ package body Wisi.Parse_Context is
       begin
          if Has_Element (Found) then
             return Result : constant Parse_Context_Access := Element (Found) do
-               if Language.Descriptor /= Result.Parser.Tree.Lexer.Descriptor 
then
-                  raise WisiToken.User_Error with "language does not match for 
buffer '" & File_Name & "'";
-               end if;
                if Have_Text and (Result.Text_Buffer = null or else 
Result.Text_Buffer'Length = 0) then
                   if Trace_Incremental_Parse > Outline then
                      Result.Parser.Tree.Lexer.Trace.Put_Line ("parse_context 
found, but text buffer empty");
@@ -749,6 +716,13 @@ package body Wisi.Parse_Context is
       end if;
    end Edit_Source;
 
+   procedure Dump_Prev_Tree
+     (Context   : in Parse_Context;
+      File_Name : in String)
+   is begin
+      Context.Prev_Tree.Put_Tree (File_Name);
+   end Dump_Prev_Tree;
+
    procedure Save_Text
      (Context   : in Parse_Context;
       File_Name : in String)
diff --git a/wisi-parse_context.ads b/wisi-parse_context.ads
index d9ec6f9740..136a62a3e1 100644
--- a/wisi-parse_context.ads
+++ b/wisi-parse_context.ads
@@ -15,26 +15,11 @@ pragma License (Modified_GPL);
 
 with Ada.Strings.Unbounded;
 with Ada.Unchecked_Deallocation;
-with WisiToken.Lexer;
-with WisiToken.Parse.LR.Parser;
 with WisiToken.Syntax_Trees;
 package Wisi.Parse_Context is
 
    Not_Found : exception;
 
-   type Language is record
-      Descriptor              : WisiToken.Descriptor_Access_Constant;
-      Lexer                   : WisiToken.Lexer.Handle;
-      Table                   : WisiToken.Parse.LR.Parse_Table_Ptr;
-      Productions             : 
WisiToken.Syntax_Trees.Production_Info_Trees.Vector;
-      Partial_Parse_Active    : access Boolean;
-      Partial_Parse_Byte_Goal : access WisiToken.Buffer_Pos;
-      Fixes                   : 
WisiToken.Parse.LR.Parser.Language_Fixes_Access;
-      Matching_Begin_Tokens   : 
WisiToken.Parse.LR.Parser.Language_Matching_Begin_Tokens_Access;
-      String_ID_Set           : 
WisiToken.Parse.LR.Parser.Language_String_ID_Set_Access;
-      Parse_Data_Template     : Wisi.Parse_Data_Access;
-   end record;
-
    type Parse_Context is tagged limited record
       --  'tagged' for Object.Method notation
 
@@ -49,7 +34,13 @@ package Wisi.Parse_Context is
       --  For Incremental parse; after editing, there may be empty space at
       --  the end of Text_Buffer.
 
-      Parser : WisiToken.Parse.LR.Parser.Parser;
+      Parser : WisiToken.Parse.Base_Parser_Access;
+
+      Prev_Tree : WisiToken.Syntax_Trees.Tree;
+      --  Copy of Parser.Tree before edits applied; useful for debugging.
+
+      Save_Prev_Text_Tree : Boolean := False;
+      --  If true, save text and copy tree before each edit.
 
       Root_Save_Edited_Name : Ada.Strings.Unbounded.Unbounded_String;
       --  If not "", save source text after the edit in a parse_incremental 
command,
@@ -57,45 +48,44 @@ package Wisi.Parse_Context is
       --  increments.
 
       Save_Edited_Count : Integer := 0;
+
+      Frozen : Boolean := False;
+      --  Used by emacs_wisi_common_parse.Parse_Stream to prevent any
+      --  operations on Parse_Context.
    end record;
    type Parse_Context_Access is access all Parse_Context;
 
    function Create_No_File
-     (Language : in Wisi.Parse_Context.Language;
-      Trace    : in WisiToken.Trace_Access)
+     (Factory : in WisiToken.Parse.Factory;
+      Trace   : in WisiToken.Trace_Access)
      return Parse_Context_Access;
 
    procedure Create_No_Text
      (File_Name : in String;
-      Language  : in Wisi.Parse_Context.Language;
+      Factory   : in WisiToken.Parse.Factory;
       Trace     : in WisiToken.Trace_Access);
 
    procedure Set_File (File_Name : in String; Parse_Context : in 
Parse_Context_Access);
 
    function Find_Create
      (File_Name : in String;
-      Language  : in Wisi.Parse_Context.Language;
+      Factory   : in WisiToken.Parse.Factory;
       Trace     : in WisiToken.Trace_Access)
      return Parse_Context_Access;
-   --  If a context for File_Name exists, return it if Language matches.
+   --  If a context for File_Name exists, return it.
    --
-   --  If no context found for File_Name, create one, return it.
+   --  If no context found for File_Name, create one using Factory, return it.
    --
    --  Raise Protocol_Error if Source_File_Name is an empty string.
-   --
-   --  Raise WisiToken.User_Error if context found for File_Name, but Language 
does not match.
 
    function Find
      (File_Name : in String;
-      Language  : in Wisi.Parse_Context.Language;
       Have_Text : in Boolean := False)
      return Parse_Context_Access;
-   --  If a context for File_Name exists, return it if Language matches.
+   --  If a context for File_Name exists, return it.
    --
    --  Raise Protocol_Error if Source_File_Name is an empty string.
    --
-   --  Raise WisiToken.User_Error if context found for File_Name, but Language 
does not match.
-   --
    --  Raise Not_Found if no context found for File_Name.
    --  If Have_Text, raise Not_Found if Text_Buffer is empty.
 
@@ -130,6 +120,11 @@ package Wisi.Parse_Context is
       KMN_List      :    out WisiToken.Parse.KMN_Lists.List);
    --  Changes must be UTF-8.
 
+   procedure Dump_Prev_Tree
+     (Context   : in Parse_Context;
+      File_Name : in String);
+   --  Output Context.Prev_Tree text format to File_Name.
+
    procedure Save_Text
      (Context   : in Parse_Context;
       File_Name : in String);
diff --git a/wisi-prj.el b/wisi-prj.el
index 744a4ab8d3..a97389f849 100644
--- a/wisi-prj.el
+++ b/wisi-prj.el
@@ -81,6 +81,35 @@
   ;; if the file should be included in `project-files'.
   )
 
+;;;###autoload
+(cl-defun create-wisi-prj
+    (&key
+     name
+     compile-env
+     file-env
+     compiler
+     xref
+     case-exception-files
+     (case-full-exceptions '())
+     (case-partial-exceptions '())
+     source-path
+     file-pred)
+  ;; We declare and autoload this because we can't autoload
+  ;; make-wisi-prj in emacs < 27. We can't use '(defalias
+  ;; 'create-wisi-prj 'make-wisi-prj); then make-wisi-prj is not defined
+  ;; by autoload.
+  (make-wisi-prj
+   :name name
+   :compile-env compile-env
+   :file-env file-env
+   :compiler compiler
+   :xref xref
+   :case-exception-files case-exception-files
+   :case-full-exceptions case-full-exceptions
+   :case-partial-exceptions case-partial-exceptions
+   :source-path source-path
+   :file-pred file-pred))
+
 (defun wisi-prj-require-prj ()
   "Return current `wisi-prj' object.
 Throw an error if current project is not an wisi-prj."
@@ -105,9 +134,10 @@ Used when searching for project files.")
   "Alist holding currently parsed project objects.
 Indexed by absolute project file name.")
 
-(cl-defgeneric wisi-prj-default (prj)
+(cl-defgeneric wisi-prj-default (_prj)
   "Return a project with default values.
-Used to reset a project before refreshing it.")
+Used to reset a project before refreshing it."
+  (make-wisi-prj))
 
 (cl-defgeneric wisi-prj-parse-one (_project _name _value)
   "If recognized by PROJECT, set NAME, VALUE in PROJECT, return non-nil.
@@ -153,14 +183,19 @@ after the project file PRJ-FILE-NAME is parsed."
   "PROJECT has been de-selected; undo any compiler-specific select actions."
   nil)
 
-(cl-defgeneric wisi-compiler-show-prj-path (compiler)
-  "Display buffer listing project file search path.")
+(cl-defgeneric wisi-compiler-prj-path (_compiler)
+  "Return the project file search path.
+Returns a list of directories, for us with `locate-file'."
+  nil)
 
 (cl-defgeneric wisi-compiler-fix-error (compiler source-buffer)
   "Attempt to fix a compilation error, return non-nil if fixed.
 Current buffer is compilation buffer; point is at an error message.
 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.")
+
 (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."
@@ -206,7 +241,7 @@ Group 1 must be the simple symbol; the rest of the item may 
be
 annotations.")
 
 (cl-defgeneric wisi-xref-completion-at-point-table (xref project)
-  "Return a completion table of names defined in PROJECT.
+  "Return a completion table of names in PROJECT that are relevant at point.
 The table is a simple list of symbols.")
 
 (cl-defgeneric wisi-xref-definitions (xref project item)
@@ -217,15 +252,17 @@ The table is a simple list of symbols.")
 
 (cl-defgeneric wisi-xref-other (project &key identifier filename line column)
   "Return cross reference information.
-PROJECT - dispatching object, normally a `wisi-prj' object.
-IDENTIFIER - an identifier or operator_symbol
+PROJECT - a `wisi-prj' object.
+IDENTIFIER - string; an identifier or operator_symbol
 FILENAME - absolute filename containing the identifier
 LINE - line number containing the identifier (may be nil)
 COLUMN - Emacs column of the start of the identifier (may be nil)
 Point is on the start of the identifier.
-Returns a list (FILE LINE COLUMN) giving the corresponding location;
-FILE is an absolute file name.  If point is at the specification, the
-corresponding location is the
+
+Returns a list (FILE LINE COLUMN) giving the corresponding
+location; FILE is an absolute file name.  If point is on a
+reference, the corresponding location is the specification. If
+point is at the specification, the corresponding location is the
 body, and vice versa.")
 
 (defvar-local wisi-xref-full-path nil
@@ -314,12 +351,25 @@ user arg limits completion to current file."
              id))))
      (t def))))
 
+(eval-and-compile
+  (when (version< emacs-version "28.0.60")
+    ;; WORKAROUND: in emacs 28 xref-location changed from defclass to
+    ;; cl-defstruct.
+    (require 'eieio)
+    (with-suppressed-warnings ;; "unknown slot" in emacs 28
+       (progn
+         (defun xref-item-summary (item) (oref item summary))
+         (defun xref-item-location (item) (oref item location))
+         (defun xref-file-location-file (location) (oref location file))
+         (defun xref-file-location-line (location) (oref location line))
+         (defun xref-file-location-column (location) (oref location column))
+         ))))
+
 (defun wisi-goto-spec/body (identifier)
   "Goto declaration or body for IDENTIFIER (default symbol at point).
 If no symbol at point, or with prefix arg, prompt for symbol, goto spec."
   (interactive (list (wisi-get-identifier "Goto spec/body of: ")))
-  (let ((prj (project-current))
-       desired-loc)
+  (let (desired-loc)
     (cond
      ((consp identifier)
       ;; alist element from wisi-xref-completion-table; desired
@@ -334,49 +384,40 @@ If no symbol at point, or with prefix arg, prompt for 
symbol, goto spec."
 
      ((stringp identifier)
       ;; from xref-backend-identifier-at-point; desired location is 'other'
-      (let ((item (wisi-xref-item identifier prj)))
-       (condition-case err
-           ;; WORKAROUND: xref 1.3.2 xref-location changed from
-           ;; defclass to cl-defstruct. If drop emacs 26, use
-           ;; 'with-suppressed-warnings'.
-           (with-no-warnings ;; "unknown slot"
-             (let ((summary (if (functionp 'xref-item-summary) 
(xref-item-summary item) (oref item summary)))
-                   (location (if (functionp 'xref-item-location) 
(xref-item-location item) (oref item location)))
-                   (eieio-skip-typecheck t)) ;; 'location' may have line, 
column nil
-               (let ((file (if (functionp 'xref-file-location-file)
-                               (xref-file-location-file location)
-                             (oref location file)))
-                     (line (if (functionp 'xref-file-location-line)
-                               (xref-file-location-line location)
-                             (oref location line)))
-                     (column (if (functionp 'xref-file-location-column)
-                                 (xref-file-location-column location)
-                               (oref location column))))
-                 (let ((target
-                        (wisi-xref-other
-                         (wisi-prj-xref prj) prj
-                         :identifier summary
-                         :filename file
-                         :line line
-                         :column column)))
-                   (setq desired-loc
-                         (xref-make summary
-                                    (xref-make-file-location
-                                     (nth 0 target) ;; file
-                                     (nth 1 target) ;; line
-                                     (nth 2 target))) ;; column
-                         )))))
-         (user-error ;; from gpr-query; current file might be new to project, 
so try wisi-names
-          (let ((item (assoc identifier (wisi-names nil t))))
-            (if item
-                (setq desired-loc
-                      (xref-make identifier
-                                 (xref-make-file-location
-                                  (nth 1 item) ;; file
-                                  (nth 2 item) ;; line
-                                  (nth 3 item))))
-              (signal (car err) (cdr err)))))
-         )))
+      (condition-case err
+         (let* ((prj (project-current))
+                (item (wisi-xref-item identifier prj)))
+           (let ((summary (xref-item-summary item))
+                 (location (xref-item-location item))
+                 (eieio-skip-typecheck t)) ;; 'location' may have line, column 
nil
+             (let ((file (xref-file-location-file location))
+                   (line (xref-file-location-line location))
+                   (column (xref-file-location-column location)))
+               (let ((target
+                      (wisi-xref-other
+                       (wisi-prj-xref prj) prj
+                       :identifier summary
+                       :filename file
+                       :line line
+                       :column column)))
+                 (setq desired-loc
+                       (xref-make summary
+                                  (xref-make-file-location
+                                   (nth 0 target) ;; file
+                                   (nth 1 target) ;; line
+                                   (nth 2 target))) ;; column
+                       )))))
+       (user-error ;; from gpr-query; current file might be new to project, so 
try wisi-names
+        (let ((item (assoc identifier (wisi-names nil t))))
+          (if item
+              (setq desired-loc
+                    (xref-make identifier
+                               (xref-make-file-location
+                                (nth 1 item) ;; file
+                                (nth 2 item) ;; line
+                                (nth 3 item))))
+            (signal (car err) (cdr err)))))
+       ))
 
      (t ;; something else
       (error "unknown case in wisi-goto-spec/body")))
@@ -563,8 +604,13 @@ COLUMN - Emacs column of the start of the identifier")
 ;;;; wisi-prj specific methods
 
 (cl-defmethod project-root ((project wisi-prj))
-   ;; Not meaningful, but some project functions insist on a valid directory
-   (car (wisi-prj-source-path project)))
+  ;; Some project functions insist on a valid directory. eglot starts
+  ;; language server in this directory; for ada_language_server it
+  ;; must be the directory containing the gnat project file.
+  (or
+   (and (wisi-prj-compiler project)
+       (wisi-compiler-root-dir (wisi-prj-compiler project)))
+   (car (wisi-prj-source-path project))))
 
 (cl-defmethod project-files ((project wisi-prj) &optional dirs)
   (let (result)
@@ -677,15 +723,22 @@ absolute file name.")
 Parser is called with two arguments; the project file name and
 a project. Parser should update the project with values from the file.")
 
-(cl-defmethod wisi-prj-parse-one (project name value)
+(cl-defmethod wisi-prj-parse-one ((project wisi-prj) name value)
   "If NAME is a wisi-prj slot, set it to VALUE, return t.
 Else return nil."
   (cond
    ((string= name "casing")
-    (cl-pushnew (expand-file-name
-                 (substitute-in-file-name value))
-                (wisi-prj-case-exception-files project)
-               :test #'string-equal)
+    (let ((exp-value (substitute-in-file-name value)))
+      (if (and (wisi-prj-compiler project)
+              (not (file-name-absolute-p exp-value)))
+         (let ((found (locate-file exp-value (wisi-compiler-prj-path 
(wisi-prj-compiler project)))))
+           (setq exp-value (if found found (expand-file-name exp-value))))
+
+       (setq exp-value (expand-file-name exp-value)))
+
+      (cl-pushnew exp-value
+                  (wisi-prj-case-exception-files project)
+                 :test #'string-equal))
     t)
 
    ((string= name "src_dir")
@@ -701,6 +754,13 @@ Else return nil."
                (wisi-prj-file-env project)))
     t)
 
+   ((string= name "import_env_var")
+    ;; Copy an env var from parent.
+    (setf (wisi-prj-file-env project)
+         (cons (concat value "=" (getenv value))
+               (wisi-prj-file-env project)))
+    t)
+
    ))
 
 (defvar-local wisi-prj-parse-undefined-function nil
@@ -723,9 +783,11 @@ Called with three args: PROJECT NAME VALUE.")
              result)
 
          ;; Both compiler and xref need to see some settings; eg gpr_file, env 
vars.
-         (when (wisi-compiler-parse-one (wisi-prj-compiler project) project 
name value)
+         (when (and (wisi-prj-compiler project)
+                    (wisi-compiler-parse-one (wisi-prj-compiler project) 
project name value))
            (setq result t))
-         (when (wisi-xref-parse-one (wisi-prj-xref project) project name value)
+         (when (and (wisi-prj-xref project)
+                    (wisi-xref-parse-one (wisi-prj-xref project) project name 
value))
            (setq result t))
 
          (unless result
@@ -760,9 +822,13 @@ case, return the project."
       ;; If no parser, prj-file is just a placeholder; there is no file to 
parse.
       ;; For example, sal-android-prj has no project file.
        (funcall parser prj-file project)
-       (wisi-prj-parse-final project prj-file)
-       (wisi-compiler-parse-final (wisi-prj-compiler project) project prj-file)
-       (wisi-xref-parse-final (wisi-prj-xref project) project prj-file))
+       (wisi-prj-parse-final project prj-file))
+
+    ;; We do this even without a parser, so project builders can just
+    ;; set the compiler and xref; see gnat-alire.el
+    ;; create-alire-project.
+    (wisi-compiler-parse-final (wisi-prj-compiler project) project prj-file)
+    (wisi-xref-parse-final (wisi-prj-xref project) project prj-file)
 
     (when cache
       ;; Cache the project properties
@@ -775,7 +841,15 @@ case, return the project."
 (defun wisi-prj-show-prj-path ()
   "Show the compiler project file search path."
   (interactive)
-  (wisi-compiler-show-prj-path (wisi-prj-compiler (wisi-prj-require-prj))))
+  (let ((path (wisi-compiler-prj-path (wisi-prj-compiler 
(wisi-prj-require-prj)))))
+    (if path
+       (progn
+         (pop-to-buffer (get-buffer-create "*project file search path*"))
+         (erase-buffer)
+         (dolist (file path)
+           (insert (format "%s\n" file))))
+      (message "no project file search path set")
+      )))
 
 (defun wisi-prj-show-src-path ()
   "Show the project source file search path."
@@ -792,26 +866,26 @@ case, return the project."
 (defun wisi-fix-compiler-error ()
   "Attempt to fix the current compiler error.
 Point must be at the source location referenced in a compiler error.
-In `compilation-last-buffer', point must be at the compiler error.
+In `next-error-last-buffer', point must be at the compiler error.
 Leave point at fixed code."
   (interactive)
   (let ((source-buffer (current-buffer))
        (line-move-visual nil)); screws up next-line otherwise
 
     (cond
-     ((equal compilation-last-buffer wisi-error-buffer)
+     ((equal next-error-last-buffer wisi-error-buffer)
       (set-buffer source-buffer)
       (wisi-repair-error))
 
      (t
-      (with-current-buffer compilation-last-buffer
+      (with-current-buffer next-error-last-buffer
        (let ((comp-buf-pt (point))
              (success
               (wisi-compiler-fix-error
                (wisi-prj-compiler (wisi-prj-require-prj))
                source-buffer)))
          ;; restore compilation buffer point
-         (set-buffer compilation-last-buffer)
+         (set-buffer next-error-last-buffer)
          (goto-char comp-buf-pt)
 
          (unless success
@@ -1252,13 +1326,13 @@ with \\[universal-argument]."
 (defun wisi-case-activate-keys (map)
   "Modify the key bindings for all the keys that should adjust casing."
   (mapc (function
-        (lambda(key)
+        (lambda (key)
           (define-key
             map
-            (char-to-string key)
-            'wisi-case-adjust-interactive)))
+            (vector key)
+            #'wisi-case-adjust-interactive)))
        '( ?_ ?% ?& ?* ?\( ?\) ?- ?= ?+
-             ?| ?\; ?: ?' ?\" ?< ?, ?. ?> ?/ ?\n 32 ?\r ))
+             ?| ?\; ?: ?' ?\" ?< ?, ?. ?> ?/ ?\n ?\s ?\r ))
   )
 
 ;;;; xref backend
@@ -1288,7 +1362,8 @@ IDENTIFIER is from a user prompt with completion, or from
       (setq column (plist-get t-prop :column))
       )
 
-     ((string-match (wisi-xref-completion-regexp (wisi-prj-xref prj)) 
identifier)
+     ((and (wisi-prj-xref prj)
+          (string-match (wisi-xref-completion-regexp (wisi-prj-xref prj)) 
identifier))
       ;; IDENTIFIER is from prompt/completion on wisi-xref-completion-table
       (setq ident (match-string 1 identifier))
 
@@ -1300,7 +1375,8 @@ IDENTIFIER is from a user prompt with completion, or from
        (setq column (nth 2 loc))
        ))
 
-     ((string-match wisi-names-regexp identifier)
+     ((and (wisi-prj-xref prj)
+          (string-match wisi-names-regexp identifier))
       ;; IDENTIFIER is from prompt/completion on wisi-names.
       (setq ident (match-string 1 identifier))
       (setq file (buffer-file-name))
@@ -1346,11 +1422,13 @@ IDENTIFIER is from a user prompt with completion, or 
from
 
 ;;;###autoload
 (defun wisi-prj-xref-backend ()
-  "For `xref-backend-functions'; return the current wisi project."
+  "Return the current wisi project if it has an xref backend.
+For `xref-backend-functions'."
   ;; We return the project, not the xref object, because the
   ;; wisi-xref-* functions need the project.
   (let ((prj (project-current)))
-    (when (wisi-prj-p prj)
+    (when (and (wisi-prj-p prj)
+              (wisi-prj-xref prj))
       prj)))
 
 ;;;; project-find-functions alternatives
@@ -1401,15 +1479,16 @@ project is current."
   (when (or dominating-file (buffer-file-name))
     ;; buffer-file-name is nil in *compilation* buffer
     (let ((prj-file (cdr (assoc (or dominating-file (buffer-file-name)) 
wisi-prj--dominating-alist))))
-      (unless (string-equal prj-file wisi-prj--current-file)
-       (message "Switching to project file '%s'" prj-file)
-       (let ((old-prj (cdr (assoc  wisi-prj--current-file wisi-prj--cache)))
-             (new-prj (cdr (assoc prj-file wisi-prj--cache))))
-         (when (wisi-prj-p old-prj)
-           (wisi-prj-deselect old-prj))
-         (when (wisi-prj-p new-prj)
-           (wisi-prj-select new-prj))
-         (setq wisi-prj--current-file prj-file))))))
+      (when prj-file ;; don't switch if dominating-file not recognized.
+       (unless (string-equal prj-file wisi-prj--current-file)
+         (message "Switching to project file '%s'" prj-file)
+         (let ((old-prj (cdr (assoc  wisi-prj--current-file wisi-prj--cache)))
+               (new-prj (cdr (assoc prj-file wisi-prj--cache))))
+           (when (wisi-prj-p old-prj)
+             (wisi-prj-deselect old-prj))
+           (when (wisi-prj-p new-prj)
+             (wisi-prj-select new-prj))
+           (setq wisi-prj--current-file prj-file)))))))
 
 ;;;###autoload
 (defun wisi-prj-current-cached (_dir)
@@ -1506,10 +1585,11 @@ not the current project."
          (unless new-prj
            ;; User may have used `wisi-prj-set-dominating' instead of
            ;; `wisi-prj-cache-dominating'; parse the project file now.
-           (wisi-prj-parse-file
-            :prj-file prj-file
-            :init-prj (cdr (assoc-string prj-file wisi-prj--default))
-            :cache t))
+           (when (assoc-string prj-file wisi-prj--default)
+             (wisi-prj-parse-file
+              :prj-file prj-file
+              :init-prj (cdr (assoc-string prj-file wisi-prj--default))
+              :cache t)))
          (when new-prj (wisi-prj-select new-prj))))
       new-prj)))
 
@@ -1574,6 +1654,33 @@ Do The Right Thing to make PRJ-FILE active and selected; 
return the project."
       (memq #'wisi-prj-current-cached project-find-functions)
       (memq #'wisi-prj-current-parse project-find-functions)))
 
+(defun wisi-prompt-prj-file ()
+  "Prompt for a project file.
+Return nil if no file selected, the absolute file name
+otherwise. The file must have an extension from
+`wisi-prj-file-extensions'."
+  (let ((filename
+        (condition-case-unless-debug nil
+            (read-file-name
+             "Project file: " ; prompt
+             nil ; dir
+             "" ; default-filename
+             t   ; mustmatch
+             nil; initial
+             (lambda (name)
+               ;; this allows directories, which enables navigating
+               ;; to the desired file. We just assume the user won't
+               ;; return a directory.
+               (or (file-accessible-directory-p name)
+                   (member (file-name-extension name) 
wisi-prj-file-extensions))))
+          (error nil)
+          )))
+
+  (unless (or (null filename)
+             (file-name-absolute-p filename))
+    (setq filename (expand-file-name filename)))
+  filename))
+
 ;;;; project menu
 
 (defun wisi-prj--menu-compute ()
@@ -1620,7 +1727,7 @@ Menu displays cached wisi projects."
        ))
     ))
 
-(add-hook 'menu-bar-update-hook 'wisi-prj-menu-install)
+(add-hook 'menu-bar-update-hook #'wisi-prj-menu-install)
 
 (defun wisi-prj-completion-table ()
   "Return list of names of cached projects."
diff --git a/wisi-process-parse.el b/wisi-process-parse.el
index d00e6762fb..05dca65c66 100644
--- a/wisi-process-parse.el
+++ b/wisi-process-parse.el
@@ -1,4 +1,4 @@
-;;; wisi-process-parse.el --- interface to external parse program
+;;; wisi-process-parse.el --- interface to external parse program  -*- 
lexical-binding: t; -*-
 ;;
 ;; Copyright (C) 2014, 2017 - 2022 Free Software Foundation, Inc.
 ;;
@@ -83,7 +83,7 @@ Otherwise add PARSER to `wisi-process--alist', return it."
       (let ((exec-file (locate-file (wisi-process--parser-exec-file parser) 
exec-path '("" ".exe"))))
 
        (unless exec-file
-         (error "%s not found on `exec-path'; run 'build.sh' in the ELPA 
package."
+         (user-error "%s not found on `exec-path'."
                 (wisi-process--parser-exec-file parser)))
 
        (push (cons (wisi-process--parser-label parser) parser) 
wisi-process--alist)
@@ -192,7 +192,7 @@ 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 ..."))
+       (message "starting parser %s ..." (wisi-process--parser-label parser)))
       (wisi-parse-log-message parser "create process")
 
       (setf (wisi-process--parser-version-checked parser) nil)
@@ -232,6 +232,7 @@ Otherwise add PARSER to `wisi-process--alist', return it."
     (with-current-buffer (wisi-process--parser-buffer parser)
       (setq search-start (point-min))
       (while (if filter-active
+                ;; FIXME: if the filter is hung, this should reset it
                 (not (eq #'internal-default-process-filter (process-filter 
process)));; wait for filter to finish
 
              (and (process-live-p process)
@@ -389,6 +390,8 @@ complete."
                    )))
           (process (wisi-process--parser-process parser)))
 
+      (setf (wisi-process--parser-update-fringe parser) t)
+
       (with-current-buffer (wisi-process--parser-buffer parser)
        (erase-buffer))
 
@@ -515,7 +518,7 @@ PARSER will respond with one or more Query messages."
        )))
     ))
 
-(defun wisi-process-parse--Name_Property (parser sexp)
+(defun wisi-process-parse--Name_Property (_parser sexp)
   ;; sexp is [Name_Property first-pos last-pos]
   ;; see `wisi-process-parse--execute'
   ;; implements wisi-name-action
@@ -546,7 +549,7 @@ PARSER will respond with one or more Query messages."
               'fontified t)
         )))))
 
-(defun wisi-process-parse--Indent (parser sexp)
+(defun wisi-process-parse--Indent (_parser sexp)
   ;; sexp is [Indent line-number line-begin-char-pos indent]
   ;; see `wisi-process-parse--execute'
   (let ((pos (aref sexp 2)))
@@ -559,7 +562,7 @@ PARSER will respond with one or more Query messages."
         (aref sexp 3)))
       )))
 
-(defun wisi-process-parse--Lexer_Error (parser sexp)
+(defun wisi-process-parse--Lexer_Error (_parser sexp)
   ;; sexp is [Lexer_Error char-position <message> <repair-char>]
   ;; see `wisi-process-parse--execute'
   (let ((pos (min (point-max) (aref sexp 1)))
@@ -582,7 +585,7 @@ PARSER will respond with one or more Query messages."
     (push err (wisi-parser-local-lexer-errors wisi-parser-local))
     ))
 
-(defun wisi-process-parse--Parser_Error (parser sexp)
+(defun wisi-process-parse--Parser_Error (_parser sexp)
   ;; sexp is [Parser_Error char-position <string>]
   ;; see `wisi-process-parse--execute'
   (let ((pos (min (point-max) (aref sexp 1)))
@@ -611,7 +614,7 @@ PARSER will respond with one or more Query messages."
     (push err (wisi-parser-local-parse-errors wisi-parser-local))
     ))
 
-(defun wisi-process-parse--In_Parse_Action_Error (parser sexp)
+(defun wisi-process-parse--In_Parse_Action_Error (_parser sexp)
   ;; sexp is [In_Parse_Action_Error code name-1-pos name-2-pos <string>]
   ;; see `wisi-process-parse--execute'
   (let ((name-1-pos (aref sexp 2))
@@ -671,7 +674,9 @@ PARSER will respond with one or more Query messages."
              (wisi--parse-error-repair err)) ;; new
             err ;; old
             (wisi-parser-local-parse-errors wisi-parser-local) ;; tree
-            :test (lambda (old el) (= (wisi--parse-error-pos old) 
(wisi--parse-error-pos err)))))
+            :test (lambda (old _el)
+                    (= (wisi--parse-error-pos old)
+                       (wisi--parse-error-pos err)))))
           )))
     ))
 
@@ -680,7 +685,7 @@ PARSER will respond with one or more Query messages."
   ;; see `wisi-process-parse--execute'
   (setf (wisi-process--parser-end-pos parser) (1+ (aref sexp 1))))
 
-(defun wisi-process-parse--Edit (parser sexp)
+(defun wisi-process-parse--Edit (_parser sexp)
   ;; sexp is [Edit begin end text]
   (save-excursion
     (delete-region (aref sexp 1) (1+ (aref sexp 2)))
@@ -715,88 +720,91 @@ PARSER will respond with one or more Query messages."
 Source buffer is current."
   ;; sexp is [action arg ...]; an encoded instruction that we need to execute
   ;;
-  ;; Actions:
-  ;;
-  ;; [Navigate_Cache pos statement_id id length class containing_pos prev_pos 
next_pos end_pos]
-  ;;    Set a wisi-cache text-property.
-  ;;    *pos          : integer buffer position; -1 if nil (not set)
-  ;;    *id           : integer index into parser-token-table
-  ;;    length        : integer character count
-  ;;    class         : integer index into wisi-class-list
-  ;;
-  ;; [Name_Property first-pos last-pos]
-  ;;
-  ;; [Face_Property first-pos last-pos face-index]
-  ;;    Set a font-lock-face text-property
-  ;;    face-index: integer index into parser-elisp-face-table
-  ;;
-  ;; [Indent line-number indent]
-  ;;    Set an indent text property
-  ;;
-  ;; [Lexer_Error char-position <message> <repair-char>]
-  ;;    The lexer detected an error at char-position.
-  ;;
-  ;;    If <repair-char> is not ASCII NUL, it was inserted immediately
-  ;;    after char-position to fix the error.
-  ;;
-  ;; [Parser_Error char-position <message>]
-  ;;    The parser detected a syntax error; save information for later
-  ;;    reporting.
-  ;;
-  ;;    If error recovery is successful, there can be more than one
-  ;;    error reported during a parse.
-  ;;
-  ;; [In_Parse_Action_Error code name-1-pos name-2-pos <string>]
-  ;;    The parser detected an in-parse action error; save information
-  ;;    for later reporting. Either of the name-*-pos may be 0,
-  ;;    indicating a missing name.
-  ;;
-  ;;    If error recovery is successful, there can be more than one
-  ;;    error reported during a parse.
-  ;;
-  ;; [Recover [error-pos edit-pos [inserted] [deleted] deleted-region]...]
-  ;;    The parser finished a successful error recovery.
-  ;;
-  ;;    error-pos: Buffer position where error was detected
-  ;;
-  ;;    edit-pos: Buffer position of inserted/deleted tokens
-  ;;
-  ;;    inserted: Virtual tokens (terminal or non-terminal) inserted
-  ;;    before edit-pos.
-  ;;
-  ;;    deleted: Tokens deleted after edit-pos.
-  ;;
-  ;;    deleted-region: source buffer char region containing deleted tokens
-  ;;
-  ;;    Args are token ids; index into parser-token-table. Save the
-  ;;    information for later use by `wisi-repair-error'.
-  ;;
-  ;; [Edit begin end text]
-  ;;    Replace region BEGIN . END with TEXT; normally the result of a
-  ;;    refactor command.
-  ;;
-  ;; [Language ...]
-  ;;    Dispatch to a language-specific action, via
-  ;;    `wisi-process--parser-language-action-table'.
-  ;;
-  ;; [Query query-label ...]
-  ;;
-  ;; Numeric action codes are given in the case expression below
+  ;; Numeric action codes are given in the case expression below; must
+  ;; match list of *_Code in wisi.ads.
 
   (condition-case err
       (cl-ecase (aref sexp 0)
        (1  (wisi-process-parse--Navigate_Cache parser sexp))
+       ;; [Navigate_Cache pos statement_id id length class containing_pos 
prev_pos next_pos end_pos]
+       ;;    Set a wisi-cache text-property.
+       ;;    *pos          : integer buffer position; -1 if nil (not set)
+       ;;    *id           : integer index into parser-token-table
+       ;;    length        : integer character count
+       ;;    class         : integer index into wisi-class-list
+
        (2  (wisi-process-parse--Face_Property parser sexp))
+       ;; [Face_Property first-pos last-pos face-index]
+       ;;    Set a font-lock-face text-property
+       ;;    face-index: integer index into parser-elisp-face-table
+
        (3  (wisi-process-parse--Indent parser sexp))
+       ;; [Indent line-number indent]
+       ;;    Set an indent text property
+
        (4  (wisi-process-parse--Lexer_Error parser sexp))
+       ;; [Lexer_Error char-position <message> <repair-char>]
+       ;;    The lexer detected an error at char-position.
+       ;;
+       ;;    If <repair-char> is not ASCII NUL, it was inserted immediately
+       ;;    after char-position to fix the error.
+
        (5  (wisi-process-parse--Parser_Error parser sexp))
+       ;; [Parser_Error char-position <message>]
+       ;;    The parser detected a syntax error; save information for later
+       ;;    reporting.
+       ;;
+       ;;    If error recovery is successful, there can be more than one
+       ;;    error reported during a parse.
+
        (6  (wisi-process-parse--In_Parse_Action_Error parser sexp))
+       ;; [In_Parse_Action_Error code name-1-pos name-2-pos <string>]
+       ;;    The parser detected an in-parse action error; save information
+       ;;    for later reporting. Either of the name-*-pos may be 0,
+       ;;    indicating a missing name.
+       ;;
+       ;;    If error recovery is successful, there can be more than one
+       ;;    error reported during a parse.
+
        (7  (wisi-process-parse--Recover parser sexp))
+       ;; [Recover [error-pos edit-pos [inserted] [deleted] deleted-region]...]
+       ;;    The parser finished a successful error recovery.
+       ;;
+       ;;    error-pos: Buffer position where error was detected
+       ;;
+       ;;    edit-pos: Buffer position of inserted/deleted tokens
+       ;;
+       ;;    inserted: Virtual tokens (terminal or non-terminal) inserted
+       ;;    before edit-pos.
+       ;;
+       ;;    deleted: Tokens deleted after edit-pos.
+       ;;
+       ;;    deleted-region: source buffer char region containing deleted 
tokens
+       ;;
+       ;;    Args are token ids; index into parser-token-table. Save the
+       ;;    information for later use by `wisi-repair-error'.
+
        (8  (wisi-process-parse--End parser sexp))
+       ;; [End pos]
+       ;;    Record last buffer position parsed.
+
        (9  (wisi-process-parse--Name_Property parser sexp))
+       ;; [Name_Property first-pos last-pos]
+
        (10 (wisi-process-parse--Edit parser sexp))
+       ;; [Edit begin end text]
+       ;;    Replace region BEGIN . END with TEXT; normally the result of a
+       ;;    refactor command.
+
        (11 (wisi-process-parse--Language parser sexp))
+       ;; [Language ...]
+       ;;    Dispatch to a language-specific action, via
+       ;;    `wisi-process--parser-language-action-table'.
+
        (12 (wisi-process-parse--Query parser sexp))
+       ;; [Query query-label ...]
+       ;;    Query result.
+
        )
     (error
      (when (< 0 wisi-debug)
@@ -822,8 +830,7 @@ Source buffer is current."
     ;; executable is not reading command input.
 
     ;; Don't let font-lock start a parse for face while waiting for
-    ;; the process to die. FIXME: that just means font-lock will
-    ;; restart the process immediately; tell font-lock not to do that?
+    ;; the process to die.
     (setf (wisi-process--parser-busy parser) t)
     (wisi-parse-log-message parser "kill process")
     (kill-process (wisi-process--parser-process parser)))
@@ -900,6 +907,7 @@ Source buffer is current."
   (let ((response-buffer (wisi-process--parser-buffer parser))
         (source-buffer (wisi-process--parser-source-buffer parser))
        log-start)
+    (defvar w32-pipe-read-delay)
     (condition-case err
        (let* ((process (wisi-process--parser-process parser))
               (w32-pipe-read-delay 0) ;; fastest subprocess read
@@ -1004,7 +1012,7 @@ Source buffer is current."
                     (t
                      ;; Something else
                      (condition-case-unless-debug err
-                         (eval response)
+                         (eval response t)
                        (error
                         (wisi-parse-log-message parser (cadr err))
                         (with-current-buffer source-buffer
@@ -1018,7 +1026,7 @@ Source buffer is current."
                   ((arrayp response)
                    ;; encoded action
                    (set-buffer source-buffer) ;; for put-text-property in 
actions
-                   (condition-case err
+                   (condition-case nil
                        (wisi-process-parse--execute parser response)
 
                      (t ;; error from bug in action code above, or bad data 
from parser.
@@ -1108,33 +1116,19 @@ Source buffer is current."
        (signal (car err) (cdr err)))
       )))
 
-(cl-defun wisi-process-parse--handle-messages-file-not-found (parser action 
&key no-text)
+(cl-defun wisi-process-parse--handle-messages-file-not-found (parser action)
   (funcall action)
   (condition-case _err
       (wisi-process-parse--handle-messages parser)
     ('wisi-file_not_found
-     (cond
-      (no-text
-       (let ((cmd (format "create-context \"%s\"" (if (buffer-file-name) 
(buffer-file-name) (buffer-name))))
-            (process (wisi-process--parser-process parser)))
-        (with-current-buffer (wisi-process--parser-buffer parser)
-          (erase-buffer))
-        (wisi-parse-log-message parser cmd)
-        (process-send-string process (wisi-process-parse--add-cmd-length cmd)))
-       (wisi-process-parse--wait parser)
-       (wisi-process-parse--handle-messages parser)
-       (funcall action)
-       (wisi-process-parse--handle-messages parser)
-       )
-      (t
-       (message "parsing buffer ...")
-       (wisi-process-parse--send-incremental-parse parser t)
-       (wisi-process-parse--wait parser)
-       (wisi-process-parse--handle-messages parser)
-       (message "parsing buffer ... done")
-       (funcall action)
-       (wisi-process-parse--handle-messages parser)
-       )))))
+     (message "parsing buffer ...")
+     (wisi-process-parse--send-incremental-parse parser t) ;; creates parse 
context
+     (wisi-process-parse--wait parser)
+     (wisi-process-parse--handle-messages parser)
+     (message "parsing buffer ... done")
+     (funcall action)
+     (wisi-process-parse--handle-messages parser)
+     )))
 
 (cl-defmethod wisi-parse-enable-memory-report ((parser wisi-parser))
   (wisi-process-parse--prepare parser 'debug)
@@ -1186,7 +1180,7 @@ Source buffer is current."
     ;; send buffer holds, w-p-p--send-* hangs waiting for the process
     ;; to start reading, which is after it loads the parse table,
     ;; which can take noticeable time for Ada.
-    (message "starting parser ..."))
+    (message "starting parser %s ..." (wisi-process--parser-label parser)))
   (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)
@@ -1258,7 +1252,7 @@ Source buffer is current."
   (wisi-process-parse--handle-messages-file-not-found
    parser
    (lambda ()
-     (apply 'wisi-process-parse--send-query parser query args)))
+     (apply #'wisi-process-parse--send-query parser query args)))
   (wisi-process--parser-query-result parser))
 
 ;;;;; debugging
@@ -1277,12 +1271,25 @@ Source buffer is current."
     (process-send-string process (wisi-process-parse--add-cmd-length cmd))
     (wisi-process-parse--handle-messages parser)))
 
-(defun wisi-process-parse-dump-tree (save-file-root)
-  (interactive "Fsave-file-root: ")
+(cl-defmethod wisi-parse-save-text-tree-auto ((parser wisi-process--parser) 
enable)
+  (wisi-process-parse--prepare parser 'debug)
+  (let* ((cmd
+         (format "save_prev_auto \"%s\" %d"
+                 (if (buffer-file-name) (buffer-file-name) (buffer-name))
+                 (if enable 1 0)))
+        (process (wisi-process--parser-process parser)))
+    (with-current-buffer (wisi-process--parser-buffer parser)
+      (erase-buffer))
+
+    (wisi-parse-log-message parser cmd)
+    (process-send-string process (wisi-process-parse--add-cmd-length cmd))
+    (wisi-process-parse--handle-messages parser)))
+
+(defun wisi-process-parse-dump-tree (save-file-root prev)
+  (interactive "Fsave-file-root: \nP")
   (let ((parser wisi-parser-shared))
     (wisi-process-parse--prepare parser 'debug)
-    ;; Also save the source text, so we have a complete test case
-    ;; starting point.
+    ;; Also save the source text, so we have a complete test case.
     (let* ((cmd
            (format (concat "save_text" " \"%s\" \"%s\"")
                    (if (buffer-file-name) (buffer-file-name) (buffer-name))
@@ -1295,7 +1302,20 @@ Source buffer is current."
       (process-send-string process (wisi-process-parse--add-cmd-length cmd))
       (wisi-process-parse--handle-messages parser))
 
-    (wisi-parse-tree-query parser 'dump (concat save-file-root ".tree_text"))))
+    (if prev
+       (let ((cmd
+              (format (concat "dump_prev_tree" " \"%s\" \"%s\"")
+                      (if (buffer-file-name) (buffer-file-name) (buffer-name))
+                     (concat save-file-root ".tree_text")))
+            (process (wisi-process--parser-process parser)))
+         (with-current-buffer (wisi-process--parser-buffer parser)
+           (erase-buffer))
+
+         (wisi-parse-log-message parser cmd)
+         (process-send-string process (wisi-process-parse--add-cmd-length cmd))
+         (wisi-process-parse--handle-messages parser))
+
+       (wisi-parse-tree-query parser 'dump (concat save-file-root 
".tree_text")))))
 
 (defun wisi-process-all-changes-to-cmd (&optional cmd-buffer-name)
   "Convert wisi-parser-local-all-changes in current buffer to command file
@@ -1312,7 +1332,7 @@ in CMD-BUFFER-NAME."
        (mckenzie_zombie_limit wisi-mckenzie-zombie-limit)
        (mckenzie_enqueue_limit wisi-mckenzie-enqueue-limit)
        (language_options (wisi-parse-format-language-options 
wisi-parser-shared))
-       edit begin end)
+       begin end)
     (set-buffer cmd-buffer)
     (erase-buffer)
 
@@ -1399,7 +1419,6 @@ prompt for it."
        (let ((verbosity (match-string 2))
             (mckenzie_zombie_limit (match-string 3))
             (mckenzie_enqueue_limit (match-string 4))
-            (parse_max_parallel (match-string 5))
             (language_param (match-string 6)))
 
         (set-buffer cmd-buffer)
@@ -1575,9 +1594,6 @@ command_file command in the kill ring."
    ((looking-at "parse 2 \"\\([^\"]*\\)\" \"\\([^\"]*\\)\" \\([-0-9]+\\) 
\\([-0-9]+\\) \\([-0-9]+\\) [-0-9]+ [-0-9]+ \"\\([^\"]*\\)\"")
     (let ((source-file (match-string 1))
          (verbosity (match-string 2))
-         (mckenzie_zombie_limit (match-string 3))
-         (mckenzie_enqueue_limit (match-string 4))
-         (parse_max_parallel (match-string 5))
          (language_param (match-string 6))
          cmd)
 
@@ -1589,16 +1605,23 @@ command_file command in the kill ring."
                    ))
       (kill-new cmd)))
 
-   ((looking-at "post-parse \"\\([^\"]*\\)\" \"\\([^\"]*\\)\" \\([-0-9]+\\) 
\\([-0-9]+\\) \\([-0-9]+\\) \\([-0-9]+\\) \\([-0-9]+\\) \"\\([^\"]*\\)\"")
+    ((looking-at "parse 1 \"\\([^\"]+\\)\"")
+     (let (begin cmd)
+       (search-forward-regexp "((")
+       (setq begin (match-beginning 0))
+       (search-forward-regexp "\")) ") ;; avoid matching 'is (Float (A));'
+       (setq cmd (concat "parse_incremental "
+                        (replace-regexp-in-string "\n" "\\n"
+                                        (buffer-substring begin (match-end 
0)))))
+       (kill-new cmd)))
+
+    ((looking-at "post-parse \"\\([^\"]*\\)\" \"\\([^\"]*\\)\" \\([-0-9]+\\) 
\\([-0-9]+\\) \\([-0-9]+\\) \\([-0-9]+\\) \\([-0-9]+\\) \"\\([^\"]*\\)\"")
     ;; see wisi-process-parse--send-action above
-    (let* ((source-file (match-string 1))
-          (verbosity (match-string 2))
-          (action (string-to-number (match-string 3)))
+    (let* ((action (string-to-number (match-string 3)))
           (begin-bytes (match-string 4))
           (begin-chars (match-string 5))
           (end-bytes (match-string 6))
           (end-chars (match-string 7))
-          (language-opts (match-string 8))
           (cmd
            (concat "post_parse "
                    (cl-ecase action (0 "Navigate") (1 "Face") (2 "Indent") (3 
"None")) " "
diff --git a/wisi-run-indent-test.el b/wisi-run-indent-test.el
index 3aea39bbde..792568a2a5 100644
--- a/wisi-run-indent-test.el
+++ b/wisi-run-indent-test.el
@@ -1,4 +1,4 @@
-;;; wisi-run-indent-test.el --- utils for automating indentation and casing 
tests
+;;; wisi-run-indent-test.el --- utils for automating indentation and casing 
tests  -*- lexical-binding: t; -*-
 ;;
 ;; Copyright (C) 2018 - 2022  Free Software Foundation, Inc.
 ;;
@@ -36,6 +36,9 @@ text, after each edit in an incremental parse, and before 
each partial parse.")
 (defun test-in-comment-p ()
   (nth 4 (syntax-ppss)))
 
+(defvar test-face-wait-fn nil
+  "Function to call after `font-lock-ensure' to wait for face to actually be 
set.")
+
 (defun test-face (token face)
   "Test if all of TOKEN in next code line has FACE.
 FACE may be a list."
@@ -43,52 +46,58 @@ FACE may be a list."
     (when (test-in-comment-p)
       (beginning-of-line); forward-comment doesn't move if inside a comment!
       (forward-comment (point-max)))
-    (condition-case err
+    (condition-case nil
        (search-forward token (line-end-position 5))
       (error
        (error "can't find '%s'" token)))
 
-    (save-match-data
-      (wisi-validate-cache (line-beginning-position) (line-end-position) nil 
'face)
-      (font-lock-ensure (line-beginning-position) (line-end-position)))
+    (when (not skip-recase-test) ;; should be t when wisi-disable-face is t
+      (let ((token (match-string 0))
+           (test-pos (match-beginning 0)))
 
-    ;; We don't use face-at-point, because it doesn't respect
-    ;; font-lock-face set by the parser! And we want to check for
-    ;; conflicts between font-lock-keywords and the parser.
+       (when wisi-parser-shared
+         (wisi-validate-cache (line-beginning-position) (line-end-position) 
nil 'face))
 
-    ;; font-lock-keywords sets 'face property, parser sets 'font-lock-face.
+       (font-lock-ensure (line-beginning-position) (line-end-position))
 
-    ;; In emacs < 27, if we use (get-text-property (point) 'face), we
-    ;; also get 'font-lock-face, but not vice-versa. So we have to use
-    ;; text-properties-at to check for both.
-    (let* ((token (match-string 0))
-          (props (text-properties-at (match-beginning 0)))
-          key
-          token-face)
+       (when test-face-wait-fn
+         (funcall test-face-wait-fn))
 
-      (cond
-       ((plist-get props 'font-lock-face)
-       (setq key 'font-lock-face)
-       (setq token-face (plist-get props 'font-lock-face)))
-
-       ((plist-get props 'face)
-       (setq key 'face)
-       (setq token-face (plist-get props 'face)))
-       )
-
-      (when (and (memq 'font-lock-face props)
-                (memq 'face props))
-       (describe-text-properties (match-beginning 0))
-       (error "mixed font-lock-keyword and parser faces for '%s'" token))
-
-      (unless (not (text-property-not-all 0 (length token) key token-face 
token))
-       (error "mixed faces, expecting %s for '%s'" face token))
-
-      (unless (or (and (listp face)
-                      (memq token-face face))
-                 (eq token-face face))
-       (error "found face %s, expecting %s for '%s'" token-face face token))
-    )))
+       ;; We don't use face-at-point, because it doesn't respect
+       ;; font-lock-face set by the parser! And we want to check for
+       ;; conflicts between font-lock-keywords and the parser.
+
+       ;; font-lock-keywords sets 'face property, parser sets 'font-lock-face.
+
+       ;; In emacs < 27, if we use (get-text-property (point) 'face), we
+       ;; also get 'font-lock-face, but not vice-versa. So we have to use
+       ;; text-properties-at to check for both.
+       (let ((props (text-properties-at test-pos))
+             key
+             token-face)
+         (cond
+          ((plist-get props 'font-lock-face)
+           (setq key 'font-lock-face)
+           (setq token-face (plist-get props 'font-lock-face)))
+
+          ((plist-get props 'face)
+           (setq key 'face)
+           (setq token-face (plist-get props 'face)))
+          )
+
+         (when (and (memq 'font-lock-face props)
+                    (memq 'face props))
+           (describe-text-properties test-pos)
+           (error "mixed font-lock-keyword and parser faces for '%s'" token))
+
+         (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))
+           (error "found face %s, expecting %s for '%s'" token-face face 
token))
+         )))))
 
 (defun test-face-1 (search token face)
   "Move to end of comment, search for SEARCH, call `test-face'."
@@ -126,7 +135,7 @@ is not present."
     (wisi-validate-cache (line-beginning-position 0) (line-end-position 3) nil 
'navigate)
     (beginning-of-line); forward-comment doesn't move if inside a comment!
     (forward-comment (point-max))
-    (condition-case err
+    (condition-case nil
        (search-forward token (line-end-position 5))
       (error
        (error "can't find '%s'" token)))
@@ -213,7 +222,9 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END 
EDIT-BEGIN)")
 
        ;; Test files use wisi-prj-select-cached to parse and select a project 
file.
        (setq project-find-functions (list #'wisi-prj-current-cached))
-       (setq xref-backend-functions (list #'wisi-prj-xref-backend))
+
+       (unless (memq 'eglot-xref-backend xref-backend-functions)
+         (setq xref-backend-functions (list #'wisi-prj-xref-backend)))
 
        (when (stringp save-edited-text)
          (wisi-process-parse-save-text wisi-parser-shared save-edited-text t))
@@ -254,25 +265,25 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END 
EDIT-BEGIN)")
              (setq cmd-line (line-number-at-pos)
                    last-cmd (match-string 0))
              (let ((msg (format "%s:%d: test %s" (buffer-file-name) cmd-line 
last-cmd)))
-               (wisi-parse-log-message wisi-parser-shared msg)
+               (when wisi-parser-shared (wisi-parse-log-message 
wisi-parser-shared msg))
                (message "%s" msg)
                (save-excursion
                  (setq last-result
                        (condition-case-unless-debug err
                            (prog1
-                             (eval (car (read-from-string last-cmd)))
+                             (eval (car (read-from-string last-cmd)) t)
                              (when (> wisi-debug 1)
                                (setq msg (concat msg " ... done"))
-                                (wisi-parse-log-message wisi-parser-shared msg)
+                                (when wisi-parser-shared 
(wisi-parse-log-message wisi-parser-shared msg))
                                 (message msg)))
                          ((error wisi-parse-error)
                           (setq error-count (1+ error-count))
                           (setq msg (concat msg " ... signaled"))
                           (setq force-fail t)
-                          (wisi-parse-log-message wisi-parser-shared msg)
+                          (when wisi-parser-shared (wisi-parse-log-message 
wisi-parser-shared msg))
                           (message msg)
                           (setq msg (format "... %s: %s" (car err) (cdr err)))
-                          (wisi-parse-log-message wisi-parser-shared msg)
+                          (when wisi-parser-shared (wisi-parse-log-message 
wisi-parser-shared msg))
                           (message msg)
                           nil)))
                  ))
@@ -284,12 +295,15 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END 
EDIT-BEGIN)")
 
             ((string= (match-string 1) "RESULT")
              (looking-at ".*$")
-             (setq expected-result (save-excursion (end-of-line 1) (eval (car 
(read-from-string (match-string 0))))))
+             (setq expected-result
+                   (save-excursion
+                     (end-of-line 1)
+                     (eval (car (read-from-string (match-string 0))) t)))
              (if (and (not force-fail)
                       (equal expected-result last-result))
                  (let ((msg (format "test passes %s:%d:\n" (buffer-file-name) 
(line-number-at-pos))))
                    (setq pass-count (1+ pass-count))
-                   (wisi-parse-log-message wisi-parser-shared msg)
+                   (when wisi-parser-shared (wisi-parse-log-message 
wisi-parser-shared msg))
                    (message msg))
 
                (setq error-count (1+ error-count))
@@ -302,19 +316,23 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END 
EDIT-BEGIN)")
                                      last-cmd
                                      last-result
                                      expected-result)))))
-                 (wisi-parse-log-message wisi-parser-shared msg)
+                 (when wisi-parser-shared (wisi-parse-log-message 
wisi-parser-shared msg))
                  (message "%s" msg))
                (setq force-fail nil)))
 
             ((string= (match-string 1) "RESULT_START")
              (looking-at ".*$")
-             (setq expected-result
-                   (list (save-excursion (end-of-line 1) (eval (car 
(read-from-string (match-string 0))))))))
+             (let ((val (save-excursion
+                         (end-of-line 1)
+                         (eval (car (read-from-string (match-string 0))) t))))
+               (when val
+                 (setq expected-result (list val)))))
 
             ((string= (match-string 1) "RESULT_ADD")
              (looking-at ".*$")
-             (let ((val (save-excursion (end-of-line 1)
-                                        (eval (car (read-from-string 
(match-string 0)))))))
+             (let ((val (save-excursion
+                          (end-of-line 1)
+                          (eval (car (read-from-string (match-string 0))) t))))
                (when val
                  (setq expected-result (append expected-result (list val))))))
 
@@ -348,7 +366,7 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END 
EDIT-BEGIN)")
 
             ((string= (match-string 1) "_SKIP_UNLESS")
              (looking-at ".*$")
-             (unless (eval (car (read-from-string (match-string 0))))
+             (unless (eval (car (read-from-string (match-string 0))) t)
                (setq skip-cmds t)
                (setq skip-reindent-test t)
                (setq skip-recase-test t)
@@ -361,7 +379,7 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END 
EDIT-BEGIN)")
                       (current-buffer)
                       (line-number-at-pos)
                       (save-excursion
-                        (eval (car (read-from-string (match-string 0)))))))
+                        (eval (car (read-from-string (match-string 0))) t))))
 
             (t
              (setq error-count (1+ error-count))
@@ -369,7 +387,7 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END 
EDIT-BEGIN)")
 
          (let ((msg (format "%s:%d tests passed %d"
                             (buffer-file-name) (line-number-at-pos (point)) 
pass-count)))
-           (wisi-parse-log-message wisi-parser-shared msg)
+           (when wisi-parser-shared (wisi-parse-log-message wisi-parser-shared 
msg))
            (message msg))
 
          (when (> error-count 0)
@@ -406,18 +424,44 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END 
EDIT-BEGIN)")
      (signal (car err) (cdr err)))
     ))
 
-(defvar cl-print-readably); cl-print.el, used by edebug
+;; Let edebug display strings full-length, and show internals of records
+(defvar cl-print-readably t); cl-print.el, used by edebug
+(setq read-buffer-completion-ignore-case t) ;; for "*Messages*"
 
-(defun large-frame ()
+(defun wisi-half-screen ()
   (interactive)
   (modify-frame-parameters
-      nil
+   nil
+   (cl-case system-type
+     (gnu/linux
+      (list
+       (cons 'font "DejaVu Sans Mono-8")
+       (cons 'width 120) ;; characters; fringe extra
+       (cons 'height 94) ;; characters
+       (cons 'left 0)
+       (cons 'top 0)))
+     (windows-nt
       (list
+       (cons 'font "DejaVu Sans Mono-8")
        (cons 'width 120) ;; characters; fringe extra
-       (cons 'height 71) ;; characters
-       (cons 'left 0) ;; pixels
-       (cons 'top 0))))
-(define-key global-map "\C-cp" 'large-frame)
+       (cons 'height 103) ;; characters
+       (cons 'left 0)
+       (cons 'top 0))))))
+(define-key global-map "\C-cp" 'wisi-half-screen)
+
+(defun wisi-first-error ()
+  (interactive)
+  (pop-to-buffer "*Messages*")
+  (goto-char (point-min))
+  (search-forward "error:"))
+(define-key global-map [f6] 'wisi-first-error)
+
+(defun wisi-prev-window ()
+  "move to previous window"
+  (interactive)
+  (other-window -1))
+(define-key global-map [M-C-up] 'wisi-prev-window)
+(define-key global-map [M-C-down] 'other-window)
 
 (defun run-test (file-name)
   "Run an indentation and casing test on FILE-NAME."
@@ -425,9 +469,6 @@ Each item is a list (ACTION PARSE-BEGIN PARSE-END 
EDIT-BEGIN)")
 
   (setq-default indent-tabs-mode nil) ;; no tab chars in files
 
-  ;; Let edebug display strings full-length, and show internals of records
-  (setq cl-print-readably t)
-
   ;; we'd like to run emacs from a makefile as:
   ;;
   ;; emacs -Q --batch -l runtest.el -f run-test-here <filename>
diff --git a/wisi-skel.el b/wisi-skel.el
index 4bfdb88715..4c7bcee912 100644
--- a/wisi-skel.el
+++ b/wisi-skel.el
@@ -1,6 +1,6 @@
 ;;; wisi-skel.el --- Extensions skeleton  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1987, 1993, 1994, 1996-2021  Free Software Foundation, Inc.
+;; Copyright (C) 1987, 1993, 1994, 1996-2022  Free Software Foundation, Inc.
 
 ;; Authors: Stephen Leake <stephen_leake@stephe-leake.org>
 
@@ -26,6 +26,8 @@
 ;; name).
 
 (require 'skeleton)
+(require 'wisi)     ;For `wisi-inhibit-parse'.
+(require 'wisi-prj) ;For `wisi-auto-case' and `wisi-case-adjust-region'.
 
 (defvar-local wisi-skel-token-alist nil
   "Alist of (STRING . ELEMENT), used by `wisi-skel-expand'.
@@ -65,9 +67,9 @@ after AFTER-1. If AFTER-1 is a nested alist, add the new 
entry after AFTER-2."
 The prompt consists of the first COUNT keys from the alist,
 separated by `|', with trailing `...' if there are more keys."
   (if (>= count (length alist))
-      (concat (mapconcat 'car alist " | ") " : ")
+      (concat (mapconcat #'car alist " | ") " : ")
     (let ((alist-1 (butlast alist (- (length alist) count))))
-      (concat (mapconcat 'car alist-1 " | ") " | ... : "))
+      (concat (mapconcat #'car alist-1 " | ") " | ... : "))
   ))
 
 (defvar wisi-skel-test-input nil
diff --git a/wisi.adb b/wisi.adb
index 2b16301271..e75d4dcba7 100644
--- a/wisi.adb
+++ b/wisi.adb
@@ -523,10 +523,11 @@ package body Wisi is
                --  We get here in partial_parse when there is no action to set 
indent
                --  for the first few lines; they are comments or low-level 
statements
                --  or declarations. ada_mode-recover_partial_28.adb
-               Data.Indents.Replace_Element (Line, (Int, Invalid_Line_Number, 
Data.Begin_Indent));
+               Data.Indents.Replace_Element (Line, (Int, 
Data.Action_Region_Lines.First, Data.Begin_Indent));
 
             when Int =>
-               Data.Indents.Replace_Element (Line, (Int, Invalid_Line_Number, 
Indent.Int_Indent + Begin_Indent));
+               Data.Indents.Replace_Element
+                 (Line, (Int, Data.Action_Region_Lines.First, 
Indent.Int_Indent + Begin_Indent));
 
             when Anchored =>
                declare
@@ -541,7 +542,8 @@ package body Wisi is
 
                   when Int =>
                      Data.Indents.Replace_Element
-                       (Line, (Int, Invalid_Line_Number, 
Anchor_Line_Indent.Int_Indent + Indent.Anchor_Delta));
+                       (Line,
+                        (Int, Data.Action_Region_Lines.First, 
Anchor_Line_Indent.Int_Indent + Indent.Anchor_Delta));
                   end case;
                end;
 
@@ -603,8 +605,8 @@ package body Wisi is
          Simple_Delta           =>
            (case Indent.Label is
             when Not_Set  => (None, Invalid_Line_Number),
-            when Int      => (Int, Invalid_Line_Number, Indent.Int_Indent),
-            when Anchored => (Anchored, Invalid_Line_Number, 
Indent.Anchor_Line, Indent.Anchor_Delta)));
+            when Int      => (Int, Indent.Controlling_Token_Line, 
Indent.Int_Indent),
+            when Anchored => (Anchored, Indent.Controlling_Token_Line, 
Indent.Anchor_Line, Indent.Anchor_Delta)));
    end To_Delta;
 
    ----------
@@ -797,7 +799,7 @@ package body Wisi is
       Action_Region_Chars : in     WisiToken.Buffer_Region;
       Begin_Indent        : in     Integer)
    is begin
-      if not Tree.Editable then
+      if Tree.Root = Syntax_Trees.Invalid_Node_Access then
          raise Parse_Error with "previous parse failed; can't execute 
post_parse action.";
       end if;
 
@@ -1811,16 +1813,13 @@ package body Wisi is
                           (Data, Tree,
                            Line_Region       => Indenting.Comment,
                            Delta_Indent      => Comment_Delta,
-                           Controlling_Delta => To_Delta
-                             (Data.Indents
-                                (Line_Number_Type'
-                                   (if Params (I).Comment_Present
-                                    then -- 
ada_mode-conditional_expressions.adb case expression for K, if
-                                          --  expression blank line.
-                                       Tree.Line_Region (Controlling_Token, 
Trailing_Non_Grammar => True).Last
-
-                                    else --  
ada_mode-conditional_expressions.adb case expression for K.
-                                       Tree.Line_Region (Controlling_Token, 
Trailing_Non_Grammar => True).First))),
+                           Controlling_Delta =>
+                             (if Params (I).Comment_Present
+                              then Null_Delta --  test_select.adb accept E2
+
+                              else To_Delta --  
ada_mode-conditional_expressions.adb case expression for K.
+                                (Data.Indents
+                                   (Tree.Line_Region (Controlling_Token, 
Trailing_Non_Grammar => True).First))),
                            Indenting_Comment => (if Params (I).Comment_Present 
then Trailing else Leading));
                      end if;
                   end if;
@@ -2012,8 +2011,15 @@ package body Wisi is
               (if Query.Label = Parent
                then Tree.Parent (Query.Node, Query.N)
                else Tree.Child (Query.Node, Positive_Index_Type (Query.N)));
-            Char_Region : constant Buffer_Region := Tree.Char_Region (Result, 
Trailing_Non_Grammar => False);
+            Char_Region : constant Buffer_Region :=
+              (if Result = Invalid_Node_Access
+               then Null_Buffer_Region
+               else Tree.Char_Region (Result, Trailing_Non_Grammar => False));
          begin
+            if Result = Invalid_Node_Access then
+               raise Parse_Error with "previous parse failed; can't execute 
post_parse action.";
+            end if;
+
             Ada.Text_IO.Put_Line
               ("[" & Query_Tree_Code &
                  Query_Label'Pos (Query.Label)'Image & " " &
@@ -2040,21 +2046,23 @@ package body Wisi is
          end if;
 
       when Dump =>
-         declare
-            use Ada.Directories;
-            File_Name : constant String := -Query.File_Name;
-            Normalized_Tree : WisiToken.Syntax_Trees.Tree;
-         begin
-            if Exists (File_Name) then
-               Delete_File (File_Name);
-            end if;
+         if Tree.Parents_Set then
+            declare
+               use Ada.Directories;
+               File_Name : constant String := -Query.File_Name;
+               Normalized_Tree : WisiToken.Syntax_Trees.Tree;
+            begin
+               if Exists (File_Name) then
+                  Delete_File (File_Name);
+               end if;
 
-            WisiToken.Syntax_Trees.Copy_Tree
-              (Source      => Tree,
-               Destination => Normalized_Tree,
-               User_Data   => Syntax_Trees.User_Data_Access_Constant (Data));
-            Normalized_Tree.Put_Tree (-Query.File_Name);
-         end;
+               WisiToken.Syntax_Trees.Copy_Tree
+                 (Source      => Tree,
+                  Destination => Normalized_Tree,
+                  User_Data   => Syntax_Trees.User_Data_Access_Constant 
(Data));
+               Normalized_Tree.Put_Tree (-Query.File_Name);
+            end;
+         end if;
       end case;
    end Query_Tree;
 
@@ -2127,6 +2135,7 @@ package body Wisi is
 
    procedure Put_Errors (Tree : in Syntax_Trees.Tree)
    is
+      use all type SAL.Base_Peek_Type;
       use Ada.Text_IO;
       Descriptor  : WisiToken.Descriptor renames Tree.Lexer.Descriptor.all;
 
@@ -2537,7 +2546,7 @@ package body Wisi is
             return
               (Simple,
                (Int,
-                Tree.Line_Region (Indenting_Token, Trailing_Non_Grammar => 
True).First,
+                Tree.Line_At_Node (Indenting_Token),
                 Param.Param.Int_Delta));
 
          when Simple_Param_Anchored =>
diff --git a/wisi.ads b/wisi.ads
index 28827cfd5d..cd0c689695 100644
--- a/wisi.ads
+++ b/wisi.ads
@@ -554,6 +554,8 @@ private
 
       Controlling_Token_Line : WisiToken.Base_Line_Number_Type := 
WisiToken.Invalid_Line_Number;
       --  See [2] Indent actions for description of controlling token.
+      --  Invalid when Label is Not_Set; see Delta_Indent for description of
+      --  other cases when it is invalid.
 
       case Label is
       when Not_Set =>
@@ -610,7 +612,9 @@ private
    type Simple_Delta_Type (Label : Simple_Delta_Labels := None) is
    record
       Controlling_Token_Line : WisiToken.Base_Line_Number_Type;
-      --  If Invalid_Line_Number, delta should not be ignored.
+      --  If Invalid_Line_Number, delta should not be ignored. Invalid when
+      --  Label is None, and when Delta is from wisi-block,
+      --  ada-indent-aggregate or similar indent function.
 
       case Label is
       when None =>
@@ -664,8 +668,7 @@ private
       Tree : in WisiToken.Syntax_Trees.Tree;
       Node : in WisiToken.Syntax_Trees.Valid_Node_Access)
      return Wisi.Indenting
-   with Pre => Tree.Line_Region (Node, Trailing_Non_Grammar => False) /= 
WisiToken.Null_Line_Region and
-               Tree.SOI /= Node and Tree.EOI /= Node;
+   with Pre => Tree.SOI /= Node and Tree.EOI /= Node;
    --  Return Node.Augmented.Indenting, computing it first if needed.
 
    function Current_Indent_Offset
@@ -703,7 +706,7 @@ private
       Indenting_Token   : in     WisiToken.Syntax_Trees.Valid_Node_Access;
       Indenting_Comment : in     Boolean)
      return Delta_Type;
-   --  Return indent defined by Param for Tree_Indenting in Nonterm.
+   --  Return indent defined by Param for Indenting_Token (a child of Nonterm).
 
    procedure Indent_Token_1
      (Data              : in out Parse_Data_Type;
@@ -717,7 +720,7 @@ private
    --  Controlling_Delta should be Null_Delta if Indenting_Comment is
    --  None; it should be any existing indent for
    --  Controlling_Token.Line_Region.[First | Last] if Indenting_Comment
-   --  is Leading | Trailing. This allows adding previously computed
+   --  is Trailing | Leading. This allows adding previously computed
    --  indents for the token controlling a comment line to the comment
    --  line indent.
    --
diff --git a/wisi.el b/wisi.el
index ca3469e622..bb2506fefa 100644
--- a/wisi.el
+++ b/wisi.el
@@ -7,7 +7,7 @@
 ;; Keywords: parser
 ;;  indentation
 ;;  navigation
-;; Version: 4.0.beta1
+;; Version: 4.1.1
 ;; package-requires: ((emacs "25.3") (seq "2.20"))
 ;; URL: http://stephe-leake.org/ada/wisitoken.html
 ;;
@@ -127,14 +127,13 @@
   is no response from the parser after waiting this amount (in
   seconds)."
   :type 'float
-  :safe 'numberp)
+  :safe #'numberp)
 (make-variable-buffer-local 'wisi-process-time-out)
 
 (defcustom wisi-size-threshold most-positive-fixnum
   "Max size (in characters) for using wisi parser results for anything."
   :type 'integer
-  :group 'wisi
-  :safe 'integerp)
+  :safe #'integerp)
 (make-variable-buffer-local 'wisi-size-threshold)
 
 (defcustom wisi-indent-context-lines 0
@@ -142,27 +141,36 @@
 Increasing this will give better results when in the middle of a
 deeply nested statement, but worse in some situations."
   :type 'integer
-  :group 'wisi
-  :safe 'integerp)
+  :safe #'integerp)
 
 (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."
   :type 'boolean
-  :group 'wisi
-  :safe 'booleanp)
+  :safe #'booleanp)
 
-(defcustom wisi-incremental-parse-enable nil
-  "If non-nil, use incremental parse when possible."
+(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
-  :group 'wisi
-  :safe 'booleanp)
+  :safe #'booleanp)
+
+(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."
+  :type 'boolean
+  :safe #'booleanp)
+
+(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."
+  :type 'boolean
+  :safe #'booleanp)
 
 (defcustom wisi-parse-full-background t
   "If non-nil, do initial full parse in background."
   :type 'boolean
-  :group 'wisi
-  :safe 'booleanp)
+  :safe #'booleanp)
 
 (defconst wisi-error-buffer-name "*wisi syntax errors*"
   "Name of buffer for displaying syntax errors.")
@@ -175,6 +183,29 @@ Useful when debugging parser or parser actions."
 Language code can set this non-nil when syntax is known to be
 invalid temporarily, or when making lots of changes.")
 
+;; wisi--change-* keep track of buffer modifications.
+;; If wisi--change-end comes before wisi--change-beg, it means there were
+;; no modifications.
+(defvar-local wisi--change-beg most-positive-fixnum
+  "First position where a change may have taken place.")
+
+(defvar-local wisi--change-end nil
+  "Marker pointing to the last position where a change may have taken place.")
+
+(defvar-local wisi--deleted-syntax nil
+  "Worst syntax class of characters deleted in changes.
+One of:
+nil - no deletions since reset
+0   - only whitespace or comment deleted
+2   - some other syntax deleted
+
+Set by `wisi-before-change', used and reset by `wisi--post-change'.")
+
+(defvar-local wisi--affected-text 0
+  "Cached text of range passed to `wisi-before-change',
+used by `wisi-after-change' to get byte count of actual
+deleted range.")
+
 (defun wisi-safe-marker-pos (pos)
   "Return an integer buffer position from POS, an integer or marker"
   (cond
@@ -462,7 +493,6 @@ For debugging."
   (setq wisi--change-beg most-positive-fixnum)
   (setq wisi--change-end nil)
   (setq wisi--deleted-syntax nil)
-  (setq wisi-indenting-p nil)
 
   (setq wisi--cached-regions ;; necessary instead of wisi-invalidate after 
ediff-regions
        (list
@@ -488,41 +518,9 @@ For debugging."
   (interactive)
   (wisi-force-parse)
   (when wisi-parser-shared
-    (wisi-parse-reset wisi-parser-shared)))
-
-;; wisi--change-* keep track of buffer modifications.
-;; If wisi--change-end comes before wisi--change-beg, it means there were
-;; no modifications.
-(defvar-local wisi--change-beg most-positive-fixnum
-  "First position where a change may have taken place.")
-
-(defvar-local wisi--change-end nil
-  "Marker pointing to the last position where a change may have taken place.")
-
-(defvar-local wisi--deleted-syntax nil
-  "Worst syntax class of characters deleted in changes.
-One of:
-nil - no deletions since reset
-0   - only whitespace or comment deleted
-2   - some other syntax deleted
-
-Set by `wisi-before-change', used and reset by `wisi--post-change'.")
-
-(defvar-local wisi-indenting-p nil
-  "Non-nil when `wisi-indent-region' is actively indenting.
-Used to ignore whitespace changes in before/after change hooks.")
-
-(defvar-local wisi--changes nil
-  "Cached list of args to wisi-after-change, for incremental parse.
-Each element is
-(INSERT-BEGIN-BYTE-POS INSERT-BEGIN-CHAR-POS
- INSERT-END-BYTE-POS INSERT-END-CHAR-POS
- DELETED-BYTE-COUNT DELETED-CHAR-COUNT INSERTED-TEXT)")
-
-(defvar-local wisi--affected-text 0
-  "Cached text of range passed to `wisi-before-change',
-used by `wisi-after-change' to get byte count of actual
-deleted range.")
+    (wisi-parse-reset wisi-parser-shared)
+    (when wisi-save-text-tree
+      (wisi-parse-save-text-tree-auto wisi-parser-shared t))))
 
 (defun wisi-before-change (begin end)
   "For `before-change-functions'."
@@ -531,37 +529,34 @@ deleted range.")
     (when wisi-incremental-parse-enable
       (setq wisi--affected-text (buffer-substring-no-properties begin end)))
 
-    (unless wisi-indenting-p
-      ;; We set wisi--change-beg, -end even if only inserting, so we
-      ;; don't have to do it again in wisi-after-change.
-      (setq wisi--change-beg (min wisi--change-beg begin))
+    (setq wisi--change-beg (min wisi--change-beg begin))
 
-      ;; `buffer-base-buffer' deals with edits in indirect buffers
-      ;; created by ediff-regions-*
+    ;; `buffer-base-buffer' deals with edits in indirect buffers
+    ;; created by ediff-regions-*
 
-      (cond
-       ((null wisi--change-end)
-       (setq wisi--change-end (make-marker))
-       (set-marker wisi--change-end end (or (buffer-base-buffer) 
(current-buffer))))
+    (cond
+     ((null wisi--change-end)
+      (setq wisi--change-end (make-marker))
+      (set-marker wisi--change-end end (or (buffer-base-buffer) 
(current-buffer))))
 
-       ((> end wisi--change-end)
-       (set-marker wisi--change-end end (or (buffer-base-buffer) 
(current-buffer))))
-       )
+     ((> end wisi--change-end)
+      (set-marker wisi--change-end end (or (buffer-base-buffer) 
(current-buffer))))
+     )
 
-      (unless (= begin end)
-       (cond
-        ((or (null wisi--deleted-syntax)
-             (= 0 wisi--deleted-syntax))
-         (save-excursion
-           (if (or (nth 4 (syntax-ppss begin)) ; in comment, moves point to 
begin
-                   (= end (skip-syntax-forward " " end)));; whitespace
-               (setq wisi--deleted-syntax 0)
-             (setq wisi--deleted-syntax 2))))
+    (unless (= begin end)
+      (cond
+       ((or (null wisi--deleted-syntax)
+           (= 0 wisi--deleted-syntax))
+       (save-excursion
+         (if (or (nth 4 (syntax-ppss begin)) ; in comment, moves point to begin
+                 (= end (skip-syntax-forward " " end)));; whitespace
+             (setq wisi--deleted-syntax 0)
+           (setq wisi--deleted-syntax 2))))
 
-        (t
-         ;; wisi--deleted-syntax is 2; no change.
-         )
-        )))
+       (t
+       ;; wisi--deleted-syntax is 2; no change.
+       )
+       ))
     ))
 
 (defun wisi-after-change (begin end length)
@@ -1051,8 +1046,7 @@ fails."
 
 (defun wisi-fontify-region (begin end)
   "For `jit-lock-functions'."
-  (with-silent-modifications
-    (remove-text-properties begin end '(font-lock-face nil)))
+  (remove-text-properties begin end '(font-lock-face nil))
 
   (if wisi-parse-full-active
       ;; Record region to fontify when full parse is done.
@@ -1509,30 +1503,28 @@ If INDENT-BLANK-LINES is non-nil, also indent blank 
lines (for use as
          ;; wisi--get-cached-indent.
          (goto-char (1- end)) ;; end is exclusive
          (goto-char (line-beginning-position))
-         (let ((wisi-indenting-p t))
-           (while (and (not (bobp))
-                       (or (and (= begin end) (= (point) end))
-                           (>= (point) begin)))
-             (when (or indent-blank-lines (not (eolp)))
-               ;; ’indent-region’ doesn’t indent an empty line; ’indent-line’ 
does
-               (let ((indent (if (bobp) 0 (wisi--get-cached-indent begin 
end))))
-                 (indent-line-to indent))
-               )
-             (forward-line -1))
-
-           ;; Run wisi-indent-calculate-functions
-           (when wisi-indent-calculate-functions
-             (goto-char begin)
-             (while (and (not (eobp))
-                         (< (point) end-mark))
-               (back-to-indentation)
-               (let ((indent
-                      (run-hook-with-args-until-success 
'wisi-indent-calculate-functions)))
-                 (when indent
-                   (indent-line-to indent)))
-
-               (forward-line 1)))
-           )
+         (while (and (not (bobp))
+                     (or (and (= begin end) (= (point) end))
+                         (>= (point) begin)))
+           (when (or indent-blank-lines (not (eolp)))
+             ;; ’indent-region’ doesn’t indent an empty line; ’indent-line’ 
does
+             (let ((indent (if (bobp) 0 (wisi--get-cached-indent begin end))))
+               (indent-line-to indent))
+             )
+           (forward-line -1))
+
+         ;; Run wisi-indent-calculate-functions
+         (when wisi-indent-calculate-functions
+           (goto-char begin)
+           (while (and (not (eobp))
+                       (< (point) end-mark))
+             (back-to-indentation)
+             (let ((indent
+                    (run-hook-with-args-until-success 
'wisi-indent-calculate-functions)))
+               (when indent
+                 (indent-line-to indent)))
+
+             (forward-line 1)))
 
          (when
              (and prev-indent-failed
@@ -1557,8 +1549,6 @@ If INDENT-BLANK-LINES is non-nil, also indent blank lines 
(for use as
     ;; (1+ line-end-pos) is needed to compute indent for a line. It
     ;; can exceed (point-max); the parser must be able to handle that.
     ;;
-    ;; IMPROVEME: change parser 'indent' action to take lines, not
-    ;; buffer positions.
     (wisi-indent-region (line-beginning-position (1+ (- 
wisi-indent-context-lines))) (1+ (line-end-position)) t)
 
     (goto-char savep)
@@ -1740,9 +1730,9 @@ where the car is a list (FILE LINE COL)."
 (defun wisi-debug-keys ()
   "Add debug key definitions to `global-map'."
   (interactive)
-  (define-key global-map "\M-h" 'wisi-show-containing-or-previous-cache)
-  (define-key global-map "\M-i" 'wisi-show-indent)
-  (define-key global-map "\M-j" 'wisi-show-cache)
+  (define-key global-map "\M-h" #'wisi-show-containing-or-previous-cache)
+  (define-key global-map "\M-i" #'wisi-show-indent)
+  (define-key global-map "\M-j" #'wisi-show-cache)
   )
 
 (defun wisi-parse-buffer (&optional parse-action begin end)
@@ -1802,67 +1792,90 @@ where the car is a list (FILE LINE COL)."
       (message "previous %s" (wisi-backward-cache)))
     ))
 
+(defun wisi-replay-kbd-macro (macro)
+  "Replay keyboard macro MACRO into current buffer,
+with incremental parse after each key event."
+  (unless wisi-incremental-parse-enable
+    (user-error "wisi-incremental-parse-enable nil; use EMACS_SKIP_UNLESS"))
+  (let ((i 0))
+    (while (< i  (length macro))
+      (execute-kbd-macro (make-vector 1 (aref macro i)))
+      (save-excursion
+       (condition-case err
+           (progn
+             (wisi--check-change)
+             (when wisi--changes
+               (wisi-parse-incremental wisi-parser-shared 'none)))
+         (wisi-parse-error
+          (when (< 0 wisi-debug)
+            ;; allow continuing when parser throws parse-error
+            (signal (car err) (cdr err))))))
+      (setq i (1+ i)))))
+
 ;;;;; setup
 
 (cl-defun wisi-setup (&key indent-calculate post-indent-fail parser)
   "Set up a buffer for parsing files with wisi."
-  (setq wisi-parser-shared parser)
-  (setq wisi-parser-local (make-wisi-parser-local))
-  (setq wisi--cached-regions
-       (list
-        (cons 'face nil)
-        (cons 'navigate nil)
-        (cons 'indent nil)))
+  ;; 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)
+    (setq wisi-parser-shared parser)
+    (setq wisi-parser-local (make-wisi-parser-local))
 
-  (setq wisi--parse-try
-       (list
-        (cons 'face t)
-        (cons 'navigate t)
-        (cons 'indent t)))
+    (setq wisi--cached-regions
+         (list
+          (cons 'face nil)
+          (cons 'navigate nil)
+          (cons 'indent nil)))
 
-  (setq wisi--last-parse-region
-       (list
-        (cons 'face nil)
-        (cons 'navigate nil)
-        (cons 'indent nil)))
+    (setq wisi--parse-try
+         (list
+          (cons 'face t)
+          (cons 'navigate t)
+          (cons 'indent t)))
 
-  (setq wisi-indent-calculate-functions (append 
wisi-indent-calculate-functions indent-calculate))
-  (set (make-local-variable 'indent-line-function) #'wisi-indent-line)
-  (set (make-local-variable 'indent-region-function) #'wisi-indent-region)
-  (set (make-local-variable 'forward-sexp-function) #'wisi-forward-sexp)
+    (setq wisi--last-parse-region
+         (list
+          (cons 'face nil)
+          (cons 'navigate nil)
+          (cons 'indent nil)))
 
-  (setq wisi-post-indent-fail-hook post-indent-fail)
-  (setq wisi-indent-failed nil)
+    (setq wisi-post-indent-fail-hook post-indent-fail)
+    (setq wisi-indent-failed nil)
+    (setq wisi-indent-calculate-functions (append 
wisi-indent-calculate-functions indent-calculate))
 
-  (add-hook 'before-change-functions #'wisi-before-change 'append t)
-  (add-hook 'after-change-functions #'wisi-after-change nil t)
-  (setq wisi--change-end (copy-marker (point-min) t))
+    (add-hook 'before-change-functions #'wisi-before-change 'append t)
+    (add-hook 'after-change-functions #'wisi-after-change nil t)
+    (setq wisi--change-end (copy-marker (point-min) t))
 
-  (add-hook 'kill-buffer-hook 'wisi-parse-kill-buf 90 t)
+    (add-hook 'kill-buffer-hook #'wisi-parse-kill-buf 90 t)
 
-  (set (make-local-variable 'comment-indent-function) 'wisi-comment-indent)
+    (when (not wisi-disable-face)
+      (jit-lock-register #'wisi-fontify-region))
 
-  (add-hook 'completion-at-point-functions #'wisi-completion-at-point -90 t)
+    (when (not wisi-disable-indent)
+      (setq-local indent-line-function #'wisi-indent-line)
+      (setq-local indent-region-function #'wisi-indent-region)
+      (setq-local comment-indent-function #'wisi-comment-indent))
 
-  (add-hook 'hack-local-variables-hook 'wisi-post-local-vars nil t)
-  )
+    (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))
 
-(defun wisi-post-local-vars ()
-  "See wisi-setup."
-  (remove-hook 'hack-local-variables-hook #'wisi-post-local-vars)
+    (setq-local forward-sexp-function #'wisi-forward-sexp)
 
-  (unless wisi-disable-face
-    (jit-lock-register #'wisi-fontify-region))
+    (when wisi-incremental-parse-enable
+      (when wisi-save-all-changes
+       (setf (wisi-parser-local-all-changes wisi-parser-local) nil))
 
-  (when wisi-incremental-parse-enable
-    (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)
 
-    ;; 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)))
+      (when wisi-save-text-tree
+       (wisi-parse-save-text-tree-auto wisi-parser-shared t))
+      )))
 
 (provide 'wisi)
 ;;; wisi.el ends here
diff --git a/wisi.texi b/wisi.texi
index 9e88cf5642..8f6987d43c 100644
--- a/wisi.texi
+++ b/wisi.texi
@@ -25,7 +25,7 @@ developing GNU and promoting software freedom.''
 
 @titlepage
 @sp 10
-@title Wisi Version 4.0.beta
+@title Wisi Version 4.1.1
 @page
 @vskip 0pt plus 1filll
 @insertcopying
@@ -37,7 +37,7 @@ developing GNU and promoting software freedom.''
 @node Top
 @top Top
 
-Wisi Version 4.0.beta
+Wisi Version 4.1.1
 @end ifnottex
 
 @menu
@@ -828,10 +828,10 @@ indenting the comment with the last line of the 
expression.
 
 @item statements: [(wisi-block ada-indent) ada-indent]
 Applies a delta indent of 3 to the code and comment on lines 5 thru
-10, and 3 to the trailing comment on lines 11 and
-12. @code{wisi-block} says to ignore the controlling token line; that
-is 5, so this would be ignored for line 6; this is why we need
-@code{wisi-block}. The delta is ignored for the Anchored line 7.
+10, and 3 to the trailing comment on lines 11 and 12. The controlling
+token line is 5, so this delta would be ignored for line 6; this is
+why we need @code{wisi-block}, which sets controlling token line to
+invalid. The delta is ignored for the Anchored line 7.
 
 Note that the indent for comments after statements is given here, not
 at a lower level; it would be tedious to add it to each statement.
@@ -957,11 +957,21 @@ add more.
 
 @table @asis
 @item @code{casing}         [slot: @code{case-exception-files}]
-List of files containing casing exceptions. @xref{Casing exception files}.
+List of files containing casing exceptions, either absolute, relative
+to the project file directory, or found on the project file
+path. @xref{Casing exception files}.
+
+@item @code{import_env_var} [slot: @code{file-env}]
+Copies an environment variable from @code{process-environment}.
 
 @item @code{src_dir}        [slot: @code{source-path}]
 A list of directories to search for source files.
 
+@item @code{$<name>}        [slot: @code{file-env}]
+Set an environment variable @code{name} in the local @code{file-env};
+it may be referenced in subsequent project file statements, and in
+processes spawned by the project.
+
 @end table
 
 @node Selecting projects
diff --git a/wisitoken-bnf-generate.adb b/wisitoken-bnf-generate.adb
index 19b6ab37c4..b401e8e523 100644
--- a/wisitoken-bnf-generate.adb
+++ b/wisitoken-bnf-generate.adb
@@ -37,7 +37,6 @@ with WisiToken.BNF.Output_Ada_Emacs;
 with WisiToken.BNF.Output_Elisp_Common;
 with WisiToken.Generate.LR.LALR_Generate;
 with WisiToken.Generate.LR.LR1_Generate;
-with WisiToken.Generate.LR1_Items;
 with WisiToken.Generate.Packrat;
 with WisiToken.Parse.LR.Parser_No_Recover; -- for reading BNF file
 with WisiToken.Productions;
@@ -49,12 +48,14 @@ with WisiToken_Grammar_Runtime;
 with Wisitoken_Grammar_Main;
 procedure WisiToken.BNF.Generate
 is
+   use all type SAL.Base_Peek_Type;
+
    procedure Put_Usage
    is
       use Ada.Text_IO;
       First : Boolean := True;
    begin
-      Put_Line (Standard_Error, "version 3.0"); -- matches release version in 
Docs/wisitoken.html
+      Put_Line (Standard_Error, "version 4.0"); -- 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);
@@ -122,8 +123,7 @@ is
                 "  --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 unless %lr1_hash_table_size specified; then 0.");
-      Put_Line (Standard_Error, "  --lr1_hash_table_size n; default 113; 
bigger should be faster");
+                  " Default 1.");
       Put_Line (Standard_Error, "verbosity keys:");
       Enable_Trace_Help;
    end Put_Usage;
@@ -141,7 +141,8 @@ is
 
    Trace          : aliased WisiToken.Text_IO_Trace.Trace;
    Input_Data     : aliased WisiToken_Grammar_Runtime.User_Data_Type;
-   Grammar_Parser : WisiToken.Parse.LR.Parser_No_Recover.Parser;
+   Grammar_Parser : WisiToken.Parse.LR.Parser_No_Recover.Parser := 
Wisitoken_Grammar_Main.Create_Parser
+     (Trace'Unchecked_Access, Input_Data'Unchecked_Access);
    Log_File       : Ada.Text_IO.File_Type; -- not used
 
    procedure Use_Input_File (File_Name : in String)
@@ -151,11 +152,6 @@ is
    begin
       Output_File_Name_Root := +Ada.Directories.Base_Name (File_Name) & Suffix;
 
-      WisiToken.Parse.LR.Parser_No_Recover.New_Parser
-        (Grammar_Parser, Wisitoken_Grammar_Main.Create_Lexer 
(Trace'Unchecked_Access),
-         Wisitoken_Grammar_Main.Create_Parse_Table, 
Wisitoken_Grammar_Main.Create_Productions,
-         Input_Data'Unchecked_Access);
-
       Grammar_Parser.Tree.Lexer.Reset_With_File (File_Name);
 
       declare
@@ -245,16 +241,6 @@ begin
                Add (Command_Generate_Set, Tuple);
             end;
 
-         elsif Argument (Arg_Next) = "--lr1_hash_table_size" then
-            Arg_Next := Arg_Next + 1;
-
-            Input_Data.Language_Params.LR1_Hash_Table_Size := Positive'Value 
(Argument (Arg_Next));
-            if not Generate_Task_Count_Set then
-               Generate_Task_Count := 0;
-            end if;
-
-            Arg_Next := Arg_Next + 1;
-
          elsif Argument (Arg_Next) = "--output_bnf" then
             Output_BNF := True;
             Arg_Next   := Arg_Next + 1;
@@ -299,7 +285,7 @@ begin
    end if;
 
    begin
-      Grammar_Parser.Parse (Log_File); -- Execute_Actions only does meta phase
+      Grammar_Parser.Parse (Log_File);
    exception
    when WisiToken.Syntax_Error =>
       if Grammar_Parser.Tree.Parents_Set then
@@ -434,7 +420,7 @@ begin
                      Trace.Put_Line ("post-parse grammar file OTHER, bnf 
tree");
                   end if;
 
-                  WisiToken.Parse.LR.Parser_No_Recover.Execute_Actions
+                  WisiToken.Parse.Execute_Actions
                     (BNF_Tree, Grammar_Parser.Productions, 
Input_Data'Unchecked_Access);
                end if;
 
@@ -536,14 +522,12 @@ begin
                Parser => Tuple.Gen_Alg,
                Phase  => WisiToken_Grammar_Runtime.Other);
 
-            if Input_Data.Language_Params.LR1_Hash_Table_Size /=
-              WisiToken.Generate.LR1_Items.Item_Set_Trees.Default_Rows and
-              not Generate_Task_Count_Set
-            then
+            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;
 
                Time_Start : Time;
@@ -617,13 +601,14 @@ begin
                        (Generate_Data.Grammar,
                         Generate_Data.Descriptor.all,
                         Grammar_Parser.Tree.Lexer.File_Name,
+                        Input_Data.Language_Params.Error_Recover,
                         Generate_Data.Conflicts,
                         Generate_Utils.To_McKenzie_Param (Generate_Data, 
Input_Data.McKenzie_Recover),
                         Input_Data.Max_Parallel,
                         Parse_Table_File_Name,
                         Include_Extra         => Test_Main,
                         Ignore_Conflicts      => Ignore_Conflicts,
-                        Partial_Recursion     => 
Input_Data.Language_Params.Partial_Recursion,
+                        Recursion_Strategy    => 
Input_Data.Language_Params.Recursion_Strategy,
                         Use_Cached_Recursions => not 
(Input_Data.If_Lexer_Present or Input_Data.If_Parser_Present),
                         Recursions            => Cached_Recursions);
 
@@ -658,15 +643,15 @@ begin
                        (Generate_Data.Grammar,
                         Generate_Data.Descriptor.all,
                         Grammar_Parser.Tree.Lexer.File_Name,
+                        Input_Data.Language_Params.Error_Recover,
                         Generate_Data.Conflicts,
                         Generate_Utils.To_McKenzie_Param (Generate_Data, 
Input_Data.McKenzie_Recover),
                         Input_Data.Max_Parallel,
                         Parse_Table_File_Name,
                         Include_Extra         => Test_Main,
                         Ignore_Conflicts      => Ignore_Conflicts,
-                        Partial_Recursion     => 
Input_Data.Language_Params.Partial_Recursion,
+                        Recursion_Strategy    => 
Input_Data.Language_Params.Recursion_Strategy,
                         Task_Count            => Generate_Task_Count,
-                        Hash_Table_Size       => 
Input_Data.Language_Params.LR1_Hash_Table_Size,
                         Use_Cached_Recursions => not 
(Input_Data.If_Lexer_Present or Input_Data.If_Parser_Present),
                         Recursions            => Cached_Recursions);
 
@@ -721,6 +706,10 @@ begin
 
                case Tuple.Gen_Alg is
                when LR_Generate_Algorithm =>
+                  pragma Assert
+                    (Generate_Data.LR_Parse_Table /= null and then
+                     Generate_Data.LR_Parse_Table.Error_Recover_Enabled = 
Input_Data.Language_Params.Error_Recover);
+
                   if Tuple.Text_Rep then
                      WisiToken.Generate.LR.Put_Text_Rep
                        (Generate_Data.LR_Parse_Table.all,
diff --git a/wisitoken-bnf-generate_packrat.adb 
b/wisitoken-bnf-generate_packrat.adb
index ec0216487a..2bc59eb3d3 100644
--- a/wisitoken-bnf-generate_packrat.adb
+++ b/wisitoken-bnf-generate_packrat.adb
@@ -56,6 +56,7 @@ is
    end Var_Suffix;
 
    procedure Generate_Parser_Body (Prod : in Productions.Instance)
+   --  Generate the parser function for one production.
    is
       use all type Ada.Containers.Count_Type;
 
@@ -72,10 +73,11 @@ is
       Indent_Line ("Descriptor : WisiToken.Descriptor renames 
Tree.Lexer.Descriptor.all;");
       Indent_Line
         ("Start_Pos  : constant Syntax_Trees.Stream_Index := Tree.Stream_Next 
(Tree.Shared_Stream, Last_Pos);");
-      Indent_Line ("Start_Pos_Index : constant Syntax_Trees.Node_Index :=");
+      Indent_Line ("Start_Pos_Index  : constant Syntax_Trees.Node_Index :=");
       Indent_Line ("  Tree.Get_Node_Index (Tree.Shared_Stream, Start_Pos);");
-      Indent_Line ("Pos        : Syntax_Trees.Stream_Index := Last_Pos; --  
last token parsed.");
-      Indent_Line ("Next_Pos   : Syntax_Trees.Stream_Index := Start_Pos;");
+      Indent_Line ("Pos              : Syntax_Trees.Stream_Index := Last_Pos; 
--  last token parsed.");
+      Indent_Line ("Next_Pos         : Syntax_Trees.Stream_Index := 
Start_Pos;");
+      Indent_Line ("Max_Examined_Pos : Syntax_Trees.Stream_Index := 
Last_Pos;");
 
       for RHS_Index in Prod.RHSs.First_Index .. Prod.RHSs.Last_Index loop
          declare
@@ -101,11 +103,11 @@ is
       Indent := Indent + 3;
 
       Indent_Line ("if Next_Pos = Syntax_Trees.Invalid_Stream_Index then");
-      Indent_Line ("   return (State => Failure);");
+      Indent_Line ("   return (State => Failure, Max_Examined_Pos => 
Next_Pos);");
       Indent_Line ("end if;");
       Indent_Line ("declare");
       Indent_Line
-        ("   Memo : Memo_Entry renames Parser.Derivs (" & Result_ID & 
")(Start_Pos_Index);");
+        ("   Memo : Memo_Entry := Get_Deriv (Parser.Derivs, " & Result_ID & ", 
Start_Pos_Index);");
       Indent_Line ("begin");
       Indent := Indent + 3;
       Indent_Line ("case Memo.State is");
@@ -128,7 +130,9 @@ is
 
       if Data.Direct_Left_Recursive (Prod.LHS) then
          --  This is the top of the 'while' loop in [warth 2008] figure 3 
Grow-LR.
-         Indent_Line ("Parser.Derivs (" & Result_ID & ").Replace_Element 
(Start_Pos_Index, (State => Failure));");
+         Indent_Line
+           ("Set_Deriv (Parser.Derivs, " & Result_ID &
+              ", Start_Pos_Index, (State => Failure, Max_Examined_Pos => 
Next_Pos));");
          Indent_Line ("<<Recurse_Start>>");
       end if;
 
@@ -142,11 +146,12 @@ is
                   Indent_Line ("Result_Recurse :=");
                   Indent := Indent + 2;
                else
-                  Indent_Line ("Parser.Derivs (" & Result_ID & 
").Replace_Element");
-                  Indent_Line ("  (Start_Pos_Index,");
+                  Indent_Line ("Set_Deriv");
+                  Indent_Line ("  (Parser.Derivs, " & Result_ID & ", 
Start_Pos_Index,");
                   Indent := Indent + 3;
                end if;
                Indent_Line ("(State            => Success,");
+               Indent_Line (" Max_Examined_Pos => Max_Examined_Pos,");
                Indent_Line (" Result           => Parser.Tree.Add_Nonterm");
 
                Indent := Indent + 3;
@@ -218,10 +223,12 @@ is
                for Token_Index in RHS.Tokens.First_Index .. 
RHS.Tokens.Last_Index loop
                   declare
                      ID      : constant String := Trimmed_Image (RHS.Tokens 
(Token_Index));
+                     ID_Name : constant String := Image (RHS.Tokens 
(Token_Index), Descriptor);
                      Var_Suf : constant String := Var_Suffix (RHS_Index, 
Token_Index);
                   begin
                      if RHS.Tokens (Token_Index) in Terminal then
-                        Indent_Line ("if Tree.ID (Tree.Shared_Stream, 
Next_Pos) = " & ID & " then");
+                        Indent_Line ("Update (Parser, """ & ID_Name & """, 
Next_Pos, Max_Examined_Pos);");
+                        Indent_Line ("if Tree.ID (Next_Pos) = " & ID & " 
then");
                         Indent := Indent + 3;
                         Indent_Line ("Pos := Next_Pos;");
                         Indent_Line ("Next_Pos := Tree.Stream_Next 
(Tree.Shared_Stream, Pos);");
@@ -238,6 +245,9 @@ is
                         Indent_Line
                           ("Memo_" & Var_Suf & " := Parse_" & Image 
(RHS.Tokens (Token_Index), Descriptor) &
                              " (Parser, Pos);");
+                        Indent_Line
+                          ("Update (Parser, """ & ID_Name & """, Memo_" & 
Var_Suf &
+                             ".Max_Examined_Pos, Max_Examined_Pos);");
                         Indent_Line ("case Result_States'(Memo_" & Var_Suf & 
".State) is");
                         Indent_Line ("when Success =>");
                         Indent := Indent + 3;
@@ -255,16 +265,18 @@ is
                end loop;
             end if;
 
-            Indent_Line ("<<RHS_" & Trimmed_Image (RHS_Index) & "_Fail>>");
             New_Line;
+            Indent_Line ("<<RHS_" & Trimmed_Image (RHS_Index) & "_Fail>>");
          end;
       end loop;
 
       --  We get here if the last alternative fails.
       if Data.Direct_Left_Recursive (Prod.LHS) then
-         Indent_Line ("Result_Recurse := (State => Failure);");
+         Indent_Line ("Result_Recurse := (State => Failure, Max_Examined_Pos 
=> Max_Examined_Pos);");
       else
-         Indent_Line ("Parser.Derivs (" & Result_ID & ").Replace_Element 
(Start_Pos_Index, (State => Failure));");
+         Indent_Line ("Set_Deriv");
+         Indent_Line ("   (Parser.Derivs, " & Result_ID & ", 
Start_Pos_Index,");
+         Indent_Line ("    (State => Failure, Max_Examined_Pos => 
Max_Examined_Pos));");
          Indent_Line ("return Parser.Derivs (" & Result_ID & 
")(Start_Pos_Index);");
       end if;
 
@@ -277,12 +289,12 @@ is
          Indent_Line ("then");
          --  made progress, try again
          Indent := Indent + 3;
-         Indent_Line ("Parser.Derivs (" & Result_ID & ").Replace_Element 
(Start_Pos_Index, Result_Recurse);");
+         Indent_Line ("Set_Deriv (Parser.Derivs, " & Result_ID & ", 
Start_Pos_Index, Result_Recurse);");
          Indent_Line ("Pos_Recurse_Last := Pos;");
          Indent_Line ("if WisiToken.Trace_Parse > Detail then");
          Indent_Line ("   Tree.Lexer.Trace.Put_Line");
          Indent_Line ("     (Parser.Tree.Image (Result_Recurse.Result,");
-         Indent_Line ("      Children => True, Terminal_Node_Numbers => 
True));");
+         Indent_Line ("      Children => True, Terminal_Node_Numbers => True, 
RHS_Index => True));");
          Indent_Line ("end if;");
          Indent_Line ("goto Recurse_Start;");
          Indent := Indent - 3;
@@ -291,7 +303,7 @@ is
               "Parser.Tree.Is_Empty_Nonterm (Result_Recurse.Result) then");
          --  Parse succeeded producing an empty nonterm; don't try again. This
          --  special case is not in [warth 2008].
-         Indent_Line ("   Parser.Derivs (" & Result_ID & ").Replace_Element 
(Start_Pos_Index, Result_Recurse);");
+         Indent_Line ("   Set_Deriv (Parser.Derivs, " & Result_ID & ", 
Start_Pos_Index, Result_Recurse);");
          Indent_Line ("end if;");
          Indent := Indent - 3;
          Indent_Line ("end if;");
@@ -305,7 +317,7 @@ is
          Indent_Line ("Tree.Lexer.Trace.Put_Line");
          Indent_Line ("  (Parser.Tree.Image");
          Indent_Line ("    (Parser.Derivs (" & Result_ID & 
")(Start_Pos_Index).Result,");
-         Indent_Line ("     Children => True, Terminal_Node_Numbers => 
True));");
+         Indent_Line ("     Children => True, Terminal_Node_Numbers => True, 
RHS_Index => True));");
          Indent := Indent - 3;
          Indent_Line ("end if;");
       end if;
@@ -328,17 +340,30 @@ begin
    end loop;
    New_Line;
 
+   Indent_Line ("procedure Update");
+   Indent_Line ("  (Parser           : in out Generated.Parser;");
+   Indent_Line ("   Nonterm          : in     String;");
+   Indent_Line ("   New_Pos          : in     Syntax_Trees.Stream_Index;");
+   Indent_Line ("   Max_Examined_Pos : in out Syntax_Trees.Stream_Index)");
+   Indent_Line ("is");
+   Indent_Line ("   Tree : Syntax_Trees.Tree renames Parser.Tree;");
+   Indent_Line ("begin");
+   Indent_Line ("   if Tree.Byte_Region");
+   Indent_Line ("     (Tree.Get_Node (Tree.Shared_Stream, New_Pos), 
Trailing_Non_Grammar => False).First >");
+   Indent_Line ("     Tree.Byte_Region");
+   Indent_Line ("       (Tree.Get_Node (Tree.Shared_Stream, Max_Examined_Pos), 
Trailing_Non_Grammar => False).First");
+   Indent_Line ("   then");
+   Indent_Line ("      Max_Examined_Pos := New_Pos;");
+   Indent_Line ("   end if;");
+   Indent_Line ("   if Trace_Parse > Extra then");
+   Indent_Line ("      Tree.Lexer.Trace.Put_Line");
+   Indent_Line ("        (Nonterm & "": max_examined_pos "" & Tree.Image");
+   Indent_Line ("          (Tree.Get_Node (Tree.Shared_Stream, 
Max_Examined_Pos), Node_Numbers => True));");
+   Indent_Line ("   end if;");
+   Indent_Line ("end Update;");
+
    for Prod of Data.Grammar loop
       Generate_Parser_Body (Prod);
    end loop;
 
-   Indent_Line ("function Parse_wisitoken_accept_1");
-   --  WORKAROUND: using Parse.Packrat.Parser'Class here generates GNAT bug 
box with GPL 2018
-   Indent_Line ("  (Parser   : in out WisiToken.Parse.Base_Parser'Class;");
-   Indent_Line ("   Last_Pos : in Syntax_Trees.Stream_Index) return 
Result_Type");
-   Indent_Line ("is begin");
-   Indent_Line ("   return Parse_wisitoken_accept (Generated.Parser (Parser), 
Last_Pos);");
-   Indent_Line ("end Parse_wisitoken_accept_1;");
-   New_Line;
-
 end WisiToken.BNF.Generate_Packrat;
diff --git a/wisitoken-bnf-generate_utils.adb b/wisitoken-bnf-generate_utils.adb
index a9eccb2132..3b089c1b98 100644
--- a/wisitoken-bnf-generate_utils.adb
+++ b/wisitoken-bnf-generate_utils.adb
@@ -22,7 +22,6 @@ with Ada.Exceptions;
 with Ada.Text_IO;
 with WisiToken.Generate; use WisiToken.Generate;
 with WisiToken.Syntax_Trees;
-with WisiToken.Text_IO_Trace;
 with WisiToken.Wisi_Ada;
 with WisiToken_Grammar_Editing;
 with Wisitoken_Grammar_Main;
@@ -308,15 +307,8 @@ package body WisiToken.BNF.Generate_Utils is
      (Grammar_Parser    : in out WisiToken.Parse.LR.Parser_No_Recover.Parser;
       Grammar_File_Name : in     String)
    is
-      Trace      : aliased WisiToken.Text_IO_Trace.Trace;
-      Input_Data : aliased WisiToken_Grammar_Runtime.User_Data_Type;
-      Log_File   : Ada.Text_IO.File_Type;
+      Log_File : Ada.Text_IO.File_Type;
    begin
-      WisiToken.Parse.LR.Parser_No_Recover.New_Parser
-        (Grammar_Parser, Wisitoken_Grammar_Main.Create_Lexer 
(Trace'Unchecked_Access),
-         Wisitoken_Grammar_Main.Create_Parse_Table, 
Wisitoken_Grammar_Main.Create_Productions,
-         Input_Data'Unchecked_Access);
-
       Grammar_Parser.Tree.Lexer.Reset_With_File (Grammar_File_Name);
 
       Grammar_Parser.Parse (Log_File);
@@ -340,14 +332,10 @@ package body WisiToken.BNF.Generate_Utils is
      return Generate_Data
    is
       use all type WisiToken_Grammar_Runtime.Meta_Syntax;
-      Grammar_Parser : WisiToken.Parse.LR.Parser_No_Recover.Parser;
+      Grammar_Parser : WisiToken.Parse.LR.Parser_No_Recover.Parser := 
Wisitoken_Grammar_Main.Create_Parser
+        (Trace'Unchecked_Access, Syntax_Trees.User_Data_Access (Input_Data));
       Log_File       : Ada.Text_IO.File_Type;
    begin
-      WisiToken.Parse.LR.Parser_No_Recover.New_Parser
-        (Grammar_Parser, Wisitoken_Grammar_Main.Create_Lexer 
(Trace'Unchecked_Access),
-         Wisitoken_Grammar_Main.Create_Parse_Table, 
Wisitoken_Grammar_Main.Create_Productions,
-         Syntax_Trees.User_Data_Access (Input_Data));
-
       Grammar_Parser.Tree.Lexer.Reset_With_File (Grammar_File_Name);
 
       Grammar_Parser.Parse (Log_File);
diff --git a/wisitoken-bnf-output_ada.adb b/wisitoken-bnf-output_ada.adb
index 0b727b1504..bf30759c27 100644
--- a/wisitoken-bnf-output_ada.adb
+++ b/wisitoken-bnf-output_ada.adb
@@ -287,7 +287,8 @@ is
 
    procedure Create_Ada_Main_Body
      (Actions_Package_Name : in String;
-      Main_Package_Name    : in String)
+      Main_Package_Name    : in String;
+      Input_Data           : in WisiToken_Grammar_Runtime.User_Data_Type)
    is
       use WisiToken.Generate;
 
@@ -314,23 +315,25 @@ is
          Put_Line ("with " & re2c_Package_Name & ";");
       end case;
 
-      Put_Line ("with " & Actions_Package_Name & "; use " & 
Actions_Package_Name & ";");
-
       case Common_Data.Generate_Algorithm is
-      when LR_Generate_Algorithm | Tree_Sitter =>
-         null;
-
-      when Packrat_Gen =>
-         Put_Line ("with WisiToken.Parse.Packrat.Generated;");
+      when LR_Generate_Algorithm =>
+         if not Input_Data.Language_Params.Error_Recover then
+            Put_Line ("with WisiToken.Parse.LR;");
+         end if;
 
       when Packrat_Proc =>
-         Put_Line ("with WisiToken.Parse.Packrat.Procedural;");
          Put_Line ("with WisiToken.Productions;");
 
-      when External =>
+      when Packrat_Gen =>
+         null;
+
+      when External | Tree_Sitter =>
          null;
+
       end case;
 
+      Put_Line ("with " & Actions_Package_Name & "; use " & 
Actions_Package_Name & ";");
+
       Put_Line ("package body " & Main_Package_Name & " is");
       Indent := Indent + 3;
       New_Line;
@@ -345,8 +348,9 @@ is
 
       case Common_Data.Generate_Algorithm is
       when LR_Generate_Algorithm =>
-         LR_Create_Create_Parse_Table (Input_Data, Common_Data, Generate_Data, 
Actions_Package_Name);
+         LR_Create_Create_Parse_Table (Input_Data, Common_Data, Generate_Data);
          Create_Create_Productions (Generate_Data);
+         LR_Create_Create_Parser (Actions_Package_Name, Common_Data, 
Generate_Data);
 
       when Packrat_Gen =>
          WisiToken.BNF.Generate_Packrat (Packrat_Data, Generate_Data);
@@ -385,9 +389,10 @@ is
                then "Gen_LR_Text_Rep_Parser_No_Recover_Run"
                else "Gen_LR_Parser_No_Recover_Run")),
 
-         when Packrat_Generate_Algorithm => "Gen_Packrat_Parser_Run",
-         when External => raise SAL.Programmer_Error,
-         when Tree_Sitter => "Gen_Tree_Sitter_Parser_Run");
+         when Packrat_Proc          => "Gen_Packrat_Proc_Parser_Run",
+         when Packrat_Gen           => "Gen_Packrat_Gen_Parser_Run",
+         when External              => raise SAL.Programmer_Error,
+         when Tree_Sitter           => "Gen_Tree_Sitter_Parser_Run");
 
       Unit_Name : constant String := File_Name_To_Ada (Output_File_Name_Root) 
& Gen_Alg_Name & "_Run";
 
@@ -441,9 +446,7 @@ is
                Put_Line ("   null, null, null,");
             end if;
          end if;
-         Put_Line ("   " & Main_Package_Name & ".Create_Parse_Table,");
-         Put_Line ("   " & Main_Package_Name & ".Create_Productions,");
-         Put_Line ("   " & Main_Package_Name & ".Create_Lexer);");
+         Put_Line ("   " & Main_Package_Name & ".Create_Parser);");
 
       when Packrat_Generate_Algorithm | Tree_Sitter =>
          Put_Line ("   " & Main_Package_Name & ".Create_Parser);");
@@ -480,9 +483,9 @@ begin
 
       if Tuple.Gen_Alg = External then
          Create_External_Main_Spec (Main_Package_Name, Tuple, Input_Data);
-         Create_Ada_Main_Body (Actions_Package_Name, Main_Package_Name);
+         Create_Ada_Main_Body (Actions_Package_Name, Main_Package_Name, 
Input_Data);
       else
-         Create_Ada_Main_Body (Actions_Package_Name, Main_Package_Name);
+         Create_Ada_Main_Body (Actions_Package_Name, Main_Package_Name, 
Input_Data);
 
          Create_Ada_Main_Spec (To_Lower (Main_Package_Name) & ".ads", 
Main_Package_Name, Input_Data, Common_Data);
 
diff --git a/wisitoken-bnf-output_ada_common.adb 
b/wisitoken-bnf-output_ada_common.adb
index ffd61d4698..853b690022 100644
--- a/wisitoken-bnf-output_ada_common.adb
+++ b/wisitoken-bnf-output_ada_common.adb
@@ -228,6 +228,9 @@ package body WisiToken.BNF.Output_Ada_Common is
          end if;
       end loop;
 
+      Indent_Line ("Partial_Parse_Active    : aliased Boolean := False;");
+      Indent_Line ("Partial_Parse_Byte_Goal : aliased WisiToken.Buffer_Pos := 
WisiToken.Buffer_Pos'Last;");
+
       Put_Raw_Code (Ada_Comment, Input_Data.Raw_Code (Actions_Spec_Post));
 
       Put_Line ("end " & Package_Name & ";");
@@ -248,25 +251,49 @@ package body WisiToken.BNF.Output_Ada_Common is
 
       procedure LR_Process
       is begin
-         Indent_Line ("function Create_Parse_Table");
+         Indent_Line ("function Create_Parser");
+         Indent_Line ("  (Trace      : in WisiToken.Trace_Access;");
+         Indent_Start   ("   User_Data  : in 
WisiToken.Syntax_Trees.User_Data_Access");
+         if Input_Data.Language_Params.Error_Recover then
+            Put_Line (";");
+            Indent_Line ("   Language_Fixes                 : in 
WisiToken.Parse.LR.Parser.Language_Fixes_Access;");
+            Indent_Line
+              ("   Language_Matching_Begin_Tokens : in " &
+                 
"WisiToken.Parse.LR.Parser.Language_Matching_Begin_Tokens_Access;");
+            Indent_Start
+              ("   Language_String_ID_Set         : in 
WisiToken.Parse.LR.Parser.Language_String_ID_Set_Access");
+         end if;
          if Common_Data.Text_Rep then
-            Indent_Line ("  (Text_Rep_File_Name : in String)");
+            Put_Line (";");
+            Indent_Start ("   Text_Rep_File_Name : in String");
          end if;
-         Indent_Line ("  return WisiToken.Parse.LR.Parse_Table_Ptr;");
-         New_Line;
-         Indent_Line ("function Create_Productions return 
WisiToken.Syntax_Trees.Production_Info_Trees.Vector;");
+         Put_Line (")");
+         Indent_Line
+           ("  return WisiToken.Parse.LR.Parser"  &
+              (if Input_Data.Language_Params.Error_Recover
+               then ""
+               else "_No_Recover") &
+              ".Parser;");
          New_Line;
-         Indent_Line ("function Create_Lexer (Trace : in 
WisiToken.Trace_Access) return WisiToken.Lexer.Handle;");
       end LR_Process;
 
-      procedure Packrat_Process
+      procedure Packrat_Procedural_Process
+      is begin
+         Indent_Line ("function Create_Parser");
+         Indent_Line ("  (Trace      : in WisiToken.Trace_Access;");
+         Indent_Line ("   User_Data  : in 
WisiToken.Syntax_Trees.User_Data_Access)");
+         Indent_Line ("  return WisiToken.Parse.Packrat.Procedural.Parser;");
+         New_Line;
+      end Packrat_Procedural_Process;
+
+      procedure Packrat_Generated_Process
       is begin
          Indent_Line ("function Create_Parser");
          Indent_Line ("  (Trace      : in WisiToken.Trace_Access;");
          Indent_Line ("   User_Data  : in 
WisiToken.Syntax_Trees.User_Data_Access)");
-         Indent_Line ("  return WisiToken.Parse.Base_Parser'Class;");
+         Indent_Line ("  return WisiToken.Parse.Packrat.Generated.Parser;");
          New_Line;
-      end Packrat_Process;
+      end Packrat_Generated_Process;
 
    begin
       if Common_Data.Generate_Algorithm = External then
@@ -288,11 +315,18 @@ package body WisiToken.BNF.Output_Ada_Common is
 
       case Common_Data.Generate_Algorithm is
       when LR_Generate_Algorithm =>
-         Put_Line ("with WisiToken.Lexer;");
-         Put_Line ("with WisiToken.Parse.LR;");
+         Put_Line
+           ("with WisiToken.Parse.LR.Parser"  &
+              (if Input_Data.Language_Params.Error_Recover
+               then ""
+               else "_No_Recover") &
+              ";");
 
-      when Packrat_Generate_Algorithm =>
-         Put_Line ("with WisiToken.Parse;");
+      when Packrat_Proc =>
+         Put_Line ("with WisiToken.Parse.Packrat.Procedural;");
+
+      when Packrat_Gen =>
+         Put_Line ("with WisiToken.Parse.Packrat.Generated;");
 
       when External | Tree_Sitter =>
          null;
@@ -307,8 +341,10 @@ package body WisiToken.BNF.Output_Ada_Common is
          case Common_Data.Generate_Algorithm is
          when LR_Generate_Algorithm =>
             LR_Process;
-         when Packrat_Generate_Algorithm =>
-            Packrat_Process;
+         when Packrat_Proc =>
+            Packrat_Procedural_Process;
+         when Packrat_Gen =>
+            Packrat_Generated_Process;
          when External | Tree_Sitter =>
             null;
          end case;
@@ -319,8 +355,10 @@ package body WisiToken.BNF.Output_Ada_Common is
             case Common_Data.Generate_Algorithm is
             when LR_Generate_Algorithm =>
                LR_Process;
-            when Packrat_Generate_Algorithm =>
-               Packrat_Process;
+            when Packrat_Proc =>
+               Packrat_Procedural_Process;
+            when Packrat_Gen =>
+               Packrat_Generated_Process;
             when External | Tree_Sitter =>
                null;
             end case;
@@ -610,10 +648,9 @@ package body WisiToken.BNF.Output_Ada_Common is
    end Create_LR_Parser_Table;
 
    procedure LR_Create_Create_Parse_Table
-     (Input_Data           :         in     
WisiToken_Grammar_Runtime.User_Data_Type;
-      Common_Data          :         in out Output_Ada_Common.Common_Data;
-      Generate_Data        : aliased in     
WisiToken.BNF.Generate_Utils.Generate_Data;
-      Actions_Package_Name :         in     String)
+     (Input_Data    :         in     WisiToken_Grammar_Runtime.User_Data_Type;
+      Common_Data   :         in out Output_Ada_Common.Common_Data;
+      Generate_Data : aliased in     
WisiToken.BNF.Generate_Utils.Generate_Data)
    is
       Table : WisiToken.Parse.LR.Parse_Table_Ptr renames 
Generate_Data.LR_Parse_Table;
    begin
@@ -666,13 +703,66 @@ package body WisiToken.BNF.Output_Ada_Common is
       Indent := Indent - 3;
       Indent_Line ("end Create_Parse_Table;");
       New_Line;
+   end LR_Create_Create_Parse_Table;
+
+   procedure LR_Create_Create_Parser
+     (Actions_Package_Name :         in     String;
+      Common_Data          :         in out Output_Ada_Common.Common_Data;
+      Generate_Data        : aliased in     
WisiToken.BNF.Generate_Utils.Generate_Data)
+   is
+      Parser_Type : constant String :=
+        "WisiToken.Parse.LR.Parser" &
+        (if Generate_Data.LR_Parse_Table.Error_Recover_Enabled
+         then ""
+         else "_No_Recover") &
+        ".Parser";
+   begin
+      Indent_Line ("function Create_Parser");
+      Indent_Line    ("  (Trace      : in WisiToken.Trace_Access;");
+      Indent_Start   ("   User_Data  : in 
WisiToken.Syntax_Trees.User_Data_Access");
+      if Generate_Data.LR_Parse_Table.Error_Recover_Enabled then
+         Put_Line (";");
+         Indent_Line
+           ("   Language_Fixes                 : in 
WisiToken.Parse.LR.Parser.Language_Fixes_Access;");
+         Indent_Line
+           ("   Language_Matching_Begin_Tokens : in 
WisiToken.Parse.LR.Parser.Language_Matching_Begin_Tokens_Access;");
+         Indent_Start
+           ("   Language_String_ID_Set         : in 
WisiToken.Parse.LR.Parser.Language_String_ID_Set_Access");
+      end if;
+      if Common_Data.Text_Rep then
+         Put_Line (";");
+         Indent_Start ("   Text_Rep_File_Name : in String");
+      end if;
+      Put_Line (")");
+      Indent_Line ("  return " & Parser_Type);
 
-      Indent_Line ("function Create_Lexer (Trace : in WisiToken.Trace_Access) 
return WisiToken.Lexer.Handle");
       Indent_Line ("is begin");
-      Indent_Line ("   return Lexer.New_Lexer (Trace, " & Actions_Package_Name 
& ".Descriptor'Access);");
-      Indent_Line ("end Create_Lexer;");
-      New_Line;
-   end LR_Create_Create_Parse_Table;
+      Indent := Indent + 3;
+      Indent_Line ("return Parser : " & Parser_Type & " do");
+      Indent := Indent + 3;
+      Indent_Line ("Parser.Tree.Lexer := Lexer.New_Lexer (Trace, " & 
Actions_Package_Name & ".Descriptor'Access);");
+      Indent_Line ("Parser.Productions := Create_Productions;");
+      Indent_Line ("Parser.User_Data := User_Data;");
+      if Generate_Data.LR_Parse_Table.Error_Recover_Enabled then
+         Indent_Line ("Parser.Partial_Parse_Active := " & Actions_Package_Name 
& ".Partial_Parse_Active'Access;");
+         Indent_Line ("Parser.Partial_Parse_Byte_Goal := " & 
Actions_Package_Name & ".Partial_Parse_Byte_Goal'Access;");
+      end if;
+
+      if Common_Data.Text_Rep then
+         Indent_Line ("Parser.Table := Create_Parse_Table 
(Text_Rep_File_Name);");
+      else
+         Indent_Line ("Parser.Table := Create_Parse_Table;");
+      end if;
+      if Generate_Data.LR_Parse_Table.Error_Recover_Enabled then
+         Indent_Line ("Parser.Language_Fixes                 := 
Language_Fixes;");
+         Indent_Line ("Parser.Language_Matching_Begin_Tokens := 
Language_Matching_Begin_Tokens;");
+         Indent_Line ("Parser.Language_String_ID_Set         := 
Language_String_ID_Set;");
+      end if;
+      Indent := Indent - 3;
+      Indent_Line ("end return;");
+      Indent := Indent - 3;
+      Indent_Line ("end Create_Parser;");
+   end LR_Create_Create_Parser;
 
    procedure Packrat_Create_Create_Parser
      (Actions_Package_Name :         in     String;
@@ -680,41 +770,19 @@ package body WisiToken.BNF.Output_Ada_Common is
       Generate_Data        : aliased in     
WisiToken.BNF.Generate_Utils.Generate_Data;
       Packrat_Data         :         in     WisiToken.Generate.Packrat.Data)
    is
-      use Ada.Strings.Unbounded;
-
-      Text     : Unbounded_String;
-      Need_Bar : Boolean := True;
-   begin
-      Indent_Line ("function Create_Parser");
-      Indent_Line ("  (Trace      : in WisiToken.Trace_Access;");
-      Indent_Line ("   User_Data  : in 
WisiToken.Syntax_Trees.User_Data_Access)");
-      Indent_Line ("  return WisiToken.Parse.Base_Parser'Class");
-
-      case Packrat_Generate_Algorithm'(Common_Data.Generate_Algorithm) is
-      when Packrat_Gen =>
-         Indent_Line ("is begin");
-         Indent := Indent + 3;
-         Indent_Line ("return Parser : 
WisiToken.Parse.Packrat.Generated.Parser do");
-         Indent := Indent + 3;
-         Indent_Line ("Parser.Tree.Lexer := Lexer.New_Lexer (Trace, " & 
Actions_Package_Name & ".Descriptor'Access);");
-         Indent_Line ("Parser.Productions := Create_Productions;");
-         Indent_Line ("Parser.User_Data := User_Data;");
-         Indent_Line ("Parser.Parse_WisiToken_Accept := 
Parse_wisitoken_accept_1'Access;");
-         Indent := Indent - 3;
-         Indent_Line ("end return;");
+      Descriptor : WisiToken.Descriptor renames Generate_Data.Descriptor.all;
 
-      when Packrat_Proc =>
-         Indent_Line ("is");
-         Indent := Indent + 3;
-         Indent_Line ("use WisiToken;");
-         Indent_Line ("use WisiToken.Productions;");
-         Indent_Line ("Grammar               : Prod_Arrays.Vector;");
+      procedure Put_Direct_Left_Recursive
+      is
+         use Ada.Strings.Unbounded;
+         Text     : Unbounded_String;
+         Need_Bar : Boolean := False;
+      begin
          Indent_Line
            ("Direct_Left_Recursive : constant WisiToken.Token_ID_Set (" &
               Trimmed_Image (Generate_Data.Grammar.First_Index) & " .. " &
               Trimmed_Image (Generate_Data.Grammar.Last_Index) & ") :=");
 
-         Need_Bar := False;
          if Any (Packrat_Data.Direct_Left_Recursive) then
             for I in Packrat_Data.Direct_Left_Recursive'Range loop
                if Packrat_Data.Direct_Left_Recursive (I) then
@@ -734,16 +802,60 @@ package body WisiToken.BNF.Output_Ada_Common is
          else
             Indent_Line ("  (others => False);");
          end if;
+      end Put_Direct_Left_Recursive;
+
+   begin
+      Indent_Line ("function Create_Parser");
+      Indent_Line ("  (Trace      : in WisiToken.Trace_Access;");
+      Indent_Line ("   User_Data  : in 
WisiToken.Syntax_Trees.User_Data_Access)");
+
+      case Packrat_Generate_Algorithm'(Common_Data.Generate_Algorithm) is
+      when Packrat_Gen =>
+         Indent_Line ("  return WisiToken.Parse.Packrat.Generated.Parser");
+         Indent_Line ("is");
+         Indent := @ + 3;
+         Indent := @ - 3;
+         Indent_Line ("begin");
+         Indent := Indent + 3;
+         Indent_Line
+           ("return Parser : WisiToken.Parse.Packrat.Generated.Parser (" &
+              Trimmed_Image (Descriptor.First_Nonterminal) & ", " &
+              Trimmed_Image (Descriptor.Last_Nonterminal) & ") do");
+         Indent := Indent + 3;
+         Indent_Line ("Parser.Tree.Lexer := Lexer.New_Lexer (Trace, " & 
Actions_Package_Name & ".Descriptor'Access);");
+         Indent_Line ("Parser.Productions := Create_Productions;");
+         Indent_Line ("Parser.User_Data := User_Data;");
+         Indent_Line ("Parser.Parse_WisiToken_Accept := 
Parse_wisitoken_accept'Access;");
+         Indent := Indent - 3;
+         Indent_Line ("end return;");
+
+      when Packrat_Proc =>
+         Indent_Line
+           ("  return WisiToken.Parse.Packrat.Procedural.Parser");
+         Indent_Line ("is");
+         Indent := Indent + 3;
+         Indent_Line ("use WisiToken;");
+         Indent_Line ("use WisiToken.Productions;");
+         Indent_Line ("Grammar               : Prod_Arrays.Vector;");
+         Put_Direct_Left_Recursive;
          Indent := Indent - 3;
          Indent_Line ("begin");
          Indent := Indent + 3;
          WisiToken.BNF.Generate_Grammar (Generate_Data.Grammar, 
Generate_Data.Action_Names.all);
 
-         Indent_Line ("return WisiToken.Parse.Packrat.Procedural.Create");
-         Indent_Line ("  (Grammar, Direct_Left_Recursive, " & Trimmed_Image 
(Generate_Data.Descriptor.Accept_ID) &
-                        ", Lexer.New_Lexer");
-         Indent_Line ("     (Trace, " & Actions_Package_Name & 
".Descriptor'Access),");
-         Indent_Line ("   Create_Productions, User_Data);");
+         Indent_Line
+           ("return Parser : WisiToken.Parse.Packrat.Procedural.Parser (" &
+              Trimmed_Image (Descriptor.First_Nonterminal) & ", " &
+              Trimmed_Image (Descriptor.Last_Nonterminal) & ") do");
+         Indent := Indent + 3;
+         Indent_Line ("Parser.Tree.Lexer := Lexer.New_Lexer (Trace, " & 
Actions_Package_Name & ".Descriptor'Access);");
+         Indent_Line ("Parser.Productions := Create_Productions;");
+         Indent_Line ("Parser.User_Data := User_Data;");
+         Indent_Line ("Parser.Grammar := Grammar;");
+         Indent_Line ("Parser.Direct_Left_Recursive := 
Direct_Left_Recursive;");
+         Indent_Line ("Parser.Start_ID := " & Trimmed_Image 
(Generate_Data.Descriptor.Accept_ID) & ";");
+         Indent := Indent - 3;
+         Indent_Line ("end return;");
       end case;
       Indent := Indent - 3;
       Indent_Line ("end Create_Parser;");
diff --git a/wisitoken-bnf-output_ada_common.ads 
b/wisitoken-bnf-output_ada_common.ads
index fd8eb284c2..005cfdcc94 100644
--- a/wisitoken-bnf-output_ada_common.ads
+++ b/wisitoken-bnf-output_ada_common.ads
@@ -65,14 +65,18 @@ package WisiToken.BNF.Output_Ada_Common is
       Input_Data           : in WisiToken_Grammar_Runtime.User_Data_Type);
 
    procedure LR_Create_Create_Parse_Table
-     (Input_Data           :         in     
WisiToken_Grammar_Runtime.User_Data_Type;
-      Common_Data          :         in out Output_Ada_Common.Common_Data;
-      Generate_Data        : aliased in     
WisiToken.BNF.Generate_Utils.Generate_Data;
-      Actions_Package_Name :         in     String);
+     (Input_Data    :         in     WisiToken_Grammar_Runtime.User_Data_Type;
+      Common_Data   :         in out Output_Ada_Common.Common_Data;
+      Generate_Data : aliased in     
WisiToken.BNF.Generate_Utils.Generate_Data);
    --  If not Common_Data.Text_Rep, includes LR parse table in generated
    --  source. Otherwise, includes call to LR.Get_Text_Rep; caller must
    --  call Put_Text_Rep to create file.
 
+   procedure LR_Create_Create_Parser
+     (Actions_Package_Name :         in     String;
+      Common_Data          :         in out Output_Ada_Common.Common_Data;
+      Generate_Data        : aliased in     
WisiToken.BNF.Generate_Utils.Generate_Data);
+
    procedure Packrat_Create_Create_Parser
      (Actions_Package_Name :         in     String;
       Common_Data          :         in out Output_Ada_Common.Common_Data;
diff --git a/wisitoken-bnf-output_ada_emacs.adb 
b/wisitoken-bnf-output_ada_emacs.adb
index 76357dfc79..7d386ae2e7 100644
--- a/wisitoken-bnf-output_ada_emacs.adb
+++ b/wisitoken-bnf-output_ada_emacs.adb
@@ -1655,14 +1655,11 @@ is
       Create (Body_File, Out_File, File_Name);
       Set_Output (Body_File);
       Indent := 1;
+
       Put_File_Header (Ada_Comment, Use_Tuple => True, Tuple => Tuple);
       Put_Raw_Code (Ada_Comment, Input_Data.Raw_Code (Copyright_License));
       New_Line;
 
-      if Input_Data.Action_Count > 0 or Input_Data.Check_Count > 0 then
-         Put_Line ("with " & Actions_Package_Name & "; use " & 
Actions_Package_Name & ";");
-      end if;
-
       case Common_Data.Lexer is
       when None | Tree_Sitter_Lexer =>
          null;
@@ -1676,15 +1673,22 @@ is
 
       case Common_Data.Generate_Algorithm is
       when LR_Generate_Algorithm =>
-         null;
+         if not Input_Data.Language_Params.Error_Recover then
+            Put_Line ("with WisiToken.Parse.LR;");
+         end if;
 
-      when Packrat_Generate_Algorithm =>
-         Put_Line ("with WisiToken.Parse;");
+      when Packrat_Proc =>
+         Put_Line ("with WisiToken.Productions;");
+
+      when Packrat_Gen =>
+         Put_Line ("with WisiToken.Parse.Packrat.Parser;");
 
       when External | Tree_Sitter =>
          null;
       end case;
 
+      Put_Line ("with " & Actions_Package_Name & "; use " & 
Actions_Package_Name & ";");
+
       Put_Line ("package body " & Main_Package_Name & " is");
       Indent := Indent + 3;
       New_Line;
@@ -1699,8 +1703,9 @@ is
 
       case Common_Data.Generate_Algorithm is
       when LR_Generate_Algorithm =>
-         LR_Create_Create_Parse_Table (Input_Data, Common_Data, Generate_Data, 
Actions_Package_Name);
+         LR_Create_Create_Parse_Table (Input_Data, Common_Data, Generate_Data);
          Create_Create_Productions (Generate_Data);
+         LR_Create_Create_Parser (Actions_Package_Name, Common_Data, 
Generate_Data);
 
       when Packrat_Gen =>
          WisiToken.BNF.Generate_Packrat (Packrat_Data, Generate_Data);
@@ -1713,6 +1718,7 @@ is
 
       when External =>
          External_Create_Create_Grammar (Generate_Data);
+
       when Tree_Sitter =>
          null;
       end case;
@@ -1720,6 +1726,7 @@ is
       case Common_Data.Interface_Kind is
       when Process =>
          null;
+
       when Module =>
          Indent_Line ("Parser : LR_Parser.Instance;");
          New_Line;
diff --git a/wisitoken-bnf.ads b/wisitoken-bnf.ads
index f7ccdb43f3..d5c9dc73a7 100644
--- a/wisitoken-bnf.ads
+++ b/wisitoken-bnf.ads
@@ -158,9 +158,8 @@ package WisiToken.BNF is
       Declare_Enums             : Boolean  := True;
       End_Names_Optional_Option : Ada.Strings.Unbounded.Unbounded_String;
       Error_Recover             : Boolean  := False; -- True if grammar 
specifies error recover parameters.
-      LR1_Hash_Table_Size       : Positive := 113; --  Should match 
sal-gen_unbounded_definite_hash_tables.ads
       Language_Runtime_Name     : Ada.Strings.Unbounded.Unbounded_String;
-      Partial_Recursion         : Boolean  := False;
+      Recursion_Strategy        : WisiToken.Recursion_Strategy := Full;
       Start_Token               : Ada.Strings.Unbounded.Unbounded_String;
       Use_Language_Runtime      : Boolean  := True;
    end record;
diff --git a/wisitoken-generate-lr-lalr_generate.adb 
b/wisitoken-generate-lr-lalr_generate.adb
index 5f971dd103..358ab85d33 100644
--- a/wisitoken-generate-lr-lalr_generate.adb
+++ b/wisitoken-generate-lr-lalr_generate.adb
@@ -479,13 +479,14 @@ package body WisiToken.Generate.LR.LALR_Generate is
      (Grammar               : in out WisiToken.Productions.Prod_Arrays.Vector;
       Descriptor            : in     WisiToken.Descriptor;
       Grammar_File_Name     : in     String;
+      Error_Recover         : in     Boolean;
       Known_Conflicts       : in     Conflict_Lists.Tree := 
Conflict_Lists.Empty_Tree;
       McKenzie_Param        : in     McKenzie_Param_Type := 
Default_McKenzie_Param;
       Max_Parallel          : in     SAL.Base_Peek_Type  := 15;
       Parse_Table_File_Name : in     String              := "";
       Include_Extra         : in     Boolean             := False;
       Ignore_Conflicts      : in     Boolean             := False;
-      Partial_Recursion     : in     Boolean             := True;
+      Recursion_Strategy    : in     WisiToken.Recursion_Strategy := Full;
       Use_Cached_Recursions : in     Boolean             := False;
       Recursions            : in out WisiToken.Generate.Recursions)
      return Parse_Table_Ptr
@@ -524,10 +525,17 @@ package body WisiToken.Generate.LR.LALR_Generate is
 
    begin
       if not Use_Cached_Recursions or Recursions = Empty_Recursions then
-         Recursions :=
-           (if Partial_Recursion
-            then WisiToken.Generate.Compute_Partial_Recursion (Grammar, 
Descriptor)
-            else WisiToken.Generate.Compute_Full_Recursion (Grammar, 
Descriptor));
+         case Recursion_Strategy is
+         when None =>
+            null;
+
+         when Partial =>
+            Recursions := WisiToken.Generate.Compute_Partial_Recursion 
(Grammar, Descriptor);
+
+         when Full =>
+            Recursions := WisiToken.Generate.Compute_Full_Recursion (Grammar, 
Descriptor);
+
+         end case;
       end if;
       Set_Grammar_Recursions (Recursions, Grammar);
       Recursions_Time := Ada.Calendar.Clock;
@@ -566,6 +574,8 @@ package body WisiToken.Generate.LR.LALR_Generate is
          First_Nonterminal => Descriptor.First_Nonterminal,
          Last_Nonterminal  => Descriptor.Last_Nonterminal);
 
+      Table.Error_Recover_Enabled := Error_Recover;
+
       if McKenzie_Param = Default_McKenzie_Param then
          --  Descriminants in Default are wrong
          Table.McKenzie_Param :=
@@ -586,11 +596,8 @@ package body WisiToken.Generate.LR.LALR_Generate is
             Check_Delta_Limit           => 
Default_McKenzie_Param.Check_Delta_Limit,
             Enqueue_Limit               => 
Default_McKenzie_Param.Enqueue_Limit);
 
-         Table.Error_Recover_Enabled := False;
-
       else
-         Table.McKenzie_Param        := McKenzie_Param;
-         Table.Error_Recover_Enabled := True;
+         Table.McKenzie_Param := McKenzie_Param;
       end if;
 
       Table.Max_Parallel := Max_Parallel;
diff --git a/wisitoken-generate-lr-lalr_generate.ads 
b/wisitoken-generate-lr-lalr_generate.ads
index b2b3fef5a0..ce4115b7c4 100644
--- a/wisitoken-generate-lr-lalr_generate.ads
+++ b/wisitoken-generate-lr-lalr_generate.ads
@@ -2,7 +2,7 @@
 --
 --  Generalized LALR parse table generator.
 --
---  Copyright (C) 2002 - 2003, 2009 - 2010, 2013 - 2015, 2017 - 2020 Free 
Software Foundation, Inc.
+--  Copyright (C) 2002 - 2003, 2009 - 2010, 2013 - 2015, 2017 - 2020, 2022 
Free Software Foundation, Inc.
 --
 --  This file is part of the WisiToken package.
 --
@@ -28,14 +28,15 @@ package WisiToken.Generate.LR.LALR_Generate is
      (Grammar               : in out WisiToken.Productions.Prod_Arrays.Vector;
       Descriptor            : in     WisiToken.Descriptor;
       Grammar_File_Name     : in     String;
-      Known_Conflicts       : in     Conflict_Lists.Tree := 
Conflict_Lists.Empty_Tree;
-      McKenzie_Param        : in     McKenzie_Param_Type := 
Default_McKenzie_Param;
-      Max_Parallel          : in     SAL.Base_Peek_Type  := 15;
-      Parse_Table_File_Name : in     String              := "";
-      Include_Extra         : in     Boolean             := False;
-      Ignore_Conflicts      : in     Boolean             := False;
-      Partial_Recursion     : in     Boolean             := True;
-      Use_Cached_Recursions : in     Boolean             := False;
+      Error_Recover         : in     Boolean;
+      Known_Conflicts       : in     Conflict_Lists.Tree          := 
Conflict_Lists.Empty_Tree;
+      McKenzie_Param        : in     McKenzie_Param_Type          := 
Default_McKenzie_Param;
+      Max_Parallel          : in     SAL.Base_Peek_Type           := 15;
+      Parse_Table_File_Name : in     String                       := "";
+      Include_Extra         : in     Boolean                      := False;
+      Ignore_Conflicts      : in     Boolean                      := False;
+      Recursion_Strategy    : in     WisiToken.Recursion_Strategy := Full;
+      Use_Cached_Recursions : in     Boolean                      := False;
       Recursions            : in out WisiToken.Generate.Recursions)
      return Parse_Table_Ptr
    with Pre =>
diff --git a/wisitoken-generate-lr-lr1_generate.adb 
b/wisitoken-generate-lr-lr1_generate.adb
index bba1176feb..016baa9284 100644
--- a/wisitoken-generate-lr-lr1_generate.adb
+++ b/wisitoken-generate-lr-lr1_generate.adb
@@ -838,15 +838,15 @@ package body WisiToken.Generate.LR.LR1_Generate is
      (Grammar               : in out WisiToken.Productions.Prod_Arrays.Vector;
       Descriptor            : in     WisiToken.Descriptor;
       Grammar_File_Name     : in     String;
+      Error_Recover         : in     Boolean;
       Known_Conflicts       : in     Conflict_Lists.Tree              := 
Conflict_Lists.Empty_Tree;
       McKenzie_Param        : in     McKenzie_Param_Type              := 
Default_McKenzie_Param;
       Max_Parallel          : in     SAL.Base_Peek_Type               := 15;
       Parse_Table_File_Name : in     String                           := "";
       Include_Extra         : in     Boolean                          := False;
       Ignore_Conflicts      : in     Boolean                          := False;
-      Partial_Recursion     : in     Boolean                          := True;
+      Recursion_Strategy    : in     WisiToken.Recursion_Strategy     := Full;
       Task_Count            : in     System.Multiprocessors.CPU_Range := 1;
-      Hash_Table_Size       : in     Positive                         := 
LR1_Items.Item_Set_Trees.Default_Rows;
       Use_Cached_Recursions : in     Boolean                          := False;
       Recursions            : in out WisiToken.Generate.Recursions)
      return Parse_Table_Ptr
@@ -884,10 +884,9 @@ package body WisiToken.Generate.LR.LR1_Generate is
       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, Hash_Table_Size)
+           (Has_Empty_Production, First_Terminal_Sequence, Grammar, Descriptor)
         else LR1_Item_Sets_Parallel
-           (Has_Empty_Production, First_Terminal_Sequence, Grammar, 
Descriptor, Task_Count,
-            Hash_Table_Size));
+           (Has_Empty_Production, First_Terminal_Sequence, Grammar, 
Descriptor, Task_Count));
 
       Unknown_Conflicts    : Conflict_Lists.Tree;
       Known_Conflicts_Edit : Conflict_Lists.Tree := Known_Conflicts;
@@ -896,11 +895,18 @@ package body WisiToken.Generate.LR.LR1_Generate is
 
    begin
       if not Use_Cached_Recursions or Recursions = Empty_Recursions then
-         Recursions :=
-           (if Partial_Recursion
-            then WisiToken.Generate.Compute_Partial_Recursion (Grammar, 
Descriptor)
-            else WisiToken.Generate.Compute_Full_Recursion (Grammar, 
Descriptor));
+         case Recursion_Strategy is
+         when None =>
+            null;
+
+         when Partial =>
+            Recursions := WisiToken.Generate.Compute_Partial_Recursion 
(Grammar, Descriptor);
+
+         when Full =>
+            Recursions := WisiToken.Generate.Compute_Full_Recursion (Grammar, 
Descriptor);
+         end case;
       end if;
+
       Set_Grammar_Recursions (Recursions, Grammar);
       Recursions_Time := Ada.Calendar.Clock;
 
@@ -929,6 +935,8 @@ package body WisiToken.Generate.LR.LR1_Generate is
          First_Nonterminal => Descriptor.First_Nonterminal,
          Last_Nonterminal  => Descriptor.Last_Nonterminal);
 
+      Table.Error_Recover_Enabled := Error_Recover;
+
       if McKenzie_Param = Default_McKenzie_Param then
          --  Descriminants in Default are wrong
          Table.McKenzie_Param :=
@@ -948,6 +956,7 @@ package body WisiToken.Generate.LR.LR1_Generate is
             Check_Limit                 => Default_McKenzie_Param.Check_Limit,
             Check_Delta_Limit           => 
Default_McKenzie_Param.Check_Delta_Limit,
             Enqueue_Limit               => 
Default_McKenzie_Param.Enqueue_Limit);
+
       else
          Table.McKenzie_Param := McKenzie_Param;
       end if;
diff --git a/wisitoken-generate-lr-lr1_generate.ads 
b/wisitoken-generate-lr-lr1_generate.ads
index b37388fbc2..32f618f941 100644
--- a/wisitoken-generate-lr-lr1_generate.ads
+++ b/wisitoken-generate-lr-lr1_generate.ads
@@ -7,7 +7,7 @@
 --  [dragon] "Compilers Principles, Techniques, and Tools" by Aho,
 --  Sethi, and Ullman (aka: "The [Red] Dragon Book").
 --
---  Copyright (C) 2017 - 2020 Free Software Foundation, Inc.
+--  Copyright (C) 2017 - 2020, 2022 Free Software Foundation, Inc.
 --
 --  This file is part of the WisiToken package.
 --
@@ -34,15 +34,15 @@ package WisiToken.Generate.LR.LR1_Generate is
      (Grammar               : in out WisiToken.Productions.Prod_Arrays.Vector;
       Descriptor            : in     WisiToken.Descriptor;
       Grammar_File_Name     : in     String;
+      Error_Recover         : in     Boolean;
       Known_Conflicts       : in     Conflict_Lists.Tree              := 
Conflict_Lists.Empty_Tree;
       McKenzie_Param        : in     McKenzie_Param_Type              := 
Default_McKenzie_Param;
       Max_Parallel          : in     SAL.Base_Peek_Type               := 15;
       Parse_Table_File_Name : in     String                           := "";
       Include_Extra         : in     Boolean                          := False;
       Ignore_Conflicts      : in     Boolean                          := False;
-      Partial_Recursion     : in     Boolean                          := True;
+      Recursion_Strategy    : in     WisiToken.Recursion_Strategy     := Full;
       Task_Count            : in     System.Multiprocessors.CPU_Range := 1;
-      Hash_Table_Size       : in     Positive                         := 
LR1_Items.Item_Set_Trees.Default_Rows;
       Use_Cached_Recursions : in     Boolean                          := False;
       Recursions            : in out WisiToken.Generate.Recursions)
      return Parse_Table_Ptr
diff --git a/wisitoken-lexer-re2c.adb b/wisitoken-lexer-re2c.adb
index c6b485f719..41d57e7403 100644
--- a/wisitoken-lexer-re2c.adb
+++ b/wisitoken-lexer-re2c.adb
@@ -412,7 +412,11 @@ package body WisiToken.Lexer.re2c is
       Line  : in Line_Number_Type)
      return Base_Buffer_Pos
    is begin
-      return Line_Begin_Char_Pos (Lexer.Source, Token, Line);
+      if Token.ID = Lexer.Descriptor.New_Line_ID then
+         return Token.Char_Region.First + 1;
+      else
+         return Line_Begin_Char_Pos (Lexer.Source, Token, Line);
+      end if;
    end Line_Begin_Char_Pos;
 
    overriding
diff --git a/wisitoken-lexer.adb b/wisitoken-lexer.adb
index 54f559eeee..1d0981b936 100644
--- a/wisitoken-lexer.adb
+++ b/wisitoken-lexer.adb
@@ -162,7 +162,9 @@ package body WisiToken.Lexer is
       First       : in Boolean)
      return Base_Buffer_Pos
    is begin
-      if Instance'Class (Lexer).Can_Contain_New_Line (ID) then
+      if ID = Lexer.Descriptor.New_Line_ID then
+         return Byte_Region.First;
+      elsif Instance'Class (Lexer).Can_Contain_New_Line (ID) then
          return Contains_New_Line (Lexer.Source, Byte_Region, First);
       else
          return Invalid_Buffer_Pos;
diff --git a/wisitoken-parse-lr-mckenzie_recover-explore.adb 
b/wisitoken-parse-lr-mckenzie_recover-explore.adb
index e5f116bfa0..ebc530855d 100644
--- a/wisitoken-parse-lr-mckenzie_recover-explore.adb
+++ b/wisitoken-parse-lr-mckenzie_recover-explore.adb
@@ -839,7 +839,7 @@ package body WisiToken.Parse.LR.McKenzie_Recover.Explore is
       Orig_Config       : in out Configuration;
       Local_Config_Heap : in out Config_Heaps.Heap_Type)
      return Token_ID_Arrays.Vector
-      --  Return tokens inserted (empty if none).
+   --  Return tokens inserted (empty if none).
    is
       use Ada.Containers;
 
@@ -1915,8 +1915,7 @@ package body WisiToken.Parse.LR.McKenzie_Recover.Explore 
is
                   else Invalid_Line_Number)
                elsif not Config.Error_Token.Virtual and then
                  Config.Error_Token.Node = Config.Input_Stream 
(Config.Input_Stream.First)
-               then Tree.Line_Region (Super.Stream (Parser_Index), 
Config.Error_Token).First
-               --  Null_Line_Region if unknown.
+               then Tree.Line_At_Node (Super.Stream (Parser_Index), 
Config.Error_Token)
                else Invalid_Line_Number);
 
          begin
@@ -1962,7 +1961,7 @@ package body WisiToken.Parse.LR.McKenzie_Recover.Explore 
is
                         then Tree.Lexer.Descriptor.EOI_ID
                         else Tree.Lexer.Descriptor.SOI_ID);
 
-                     exit when Tree.Line_Region (Term, Super.Stream 
(Parser_Index)).First /= Current_Line;
+                     exit when Tree.Line_At_Node (Term, Super.Stream 
(Parser_Index)) /= Current_Line;
 
                      if Forward then
                         Tree.Next_Terminal (Term, Following => True);
diff --git a/wisitoken-parse-lr-mckenzie_recover.adb 
b/wisitoken-parse-lr-mckenzie_recover.adb
index 12d6f97fb9..02356ce996 100644
--- a/wisitoken-parse-lr-mckenzie_recover.adb
+++ b/wisitoken-parse-lr-mckenzie_recover.adb
@@ -355,7 +355,8 @@ package body WisiToken.Parse.LR.McKenzie_Recover is
                      --  we've applied all of Result.Ops, to avoid copying the 
error node
                      --  for each op.
                      Error_Recover_Ops : Recover_Op_Nodes_Arrays.Vector := 
To_Recover_Op_Nodes (Result.Ops);
-                     --  WORKAROUND: GNAT Community 2021 is confused about 
this being constant
+                     --  WORKAROUND: GNAT Community 2021 is confused about 
this being
+                     --  constant. AdaCore Eurocontrol contract ticket 
V707-027.
                      pragma Warnings (Off, Error_Recover_Ops);
 
                      Op_Index : SAL.Base_Peek_Type := No_Insert_Delete;
@@ -520,7 +521,7 @@ package body WisiToken.Parse.LR.McKenzie_Recover is
                               --  Config stack, not a parser stack. So we 
duplicate part of it.
                               if Stack_Matches_Ops then
                                  if not (Nonterm = Tree.Label (Tree.Peek 
(Stack)) and
-                                           Op.Nonterm = Tree.ID 
(Parser_State.Stream, Tree.Peek (Stack)))
+                                           Op.Nonterm = Tree.ID (Tree.Peek 
(Stack)))
                                  then
                                     Raise_Bad_Config ("Undo_Reduce does not 
match stack top in apply config");
                                  end if;
@@ -540,7 +541,7 @@ package body WisiToken.Parse.LR.McKenzie_Recover is
                               --  encounter an error; 
test_mckenzie_recover.adb Error_3.
 
                               if Stack_Matches_Ops then
-                                 if not (Op.PB_ID = Tree.ID 
(Parser_State.Stream, Tree.Peek (Stack))) then
+                                 if not (Op.PB_ID = Tree.ID (Tree.Peek 
(Stack))) then
                                     Raise_Bad_Config
                                       ("Push_Back does not match stack top in 
apply config: " &
                                          Image (Op, 
Tree.Lexer.Descriptor.all));
@@ -620,7 +621,8 @@ package body WisiToken.Parse.LR.McKenzie_Recover is
 
                                     declare
                                        --  WORKAROUND: GNAT Community 2021 
reports "'Op' must be a variable"
-                                       --  if we use this expression for the 
Op parameter.
+                                       --  if we use this expression for the 
Op parameter. AdaCore
+                                       --  Eurocontrol contract ticket 
V707-027.
                                        Op : Recover_Op_Nodes renames 
Error_Recover_Ops (Op_Index);
                                     begin
                                        Parser_State.Do_Delete
diff --git a/wisitoken-parse-lr-parser-parse.adb 
b/wisitoken-parse-lr-parser-parse.adb
index 187b74ad28..ea3c5d7b13 100644
--- a/wisitoken-parse-lr-parser-parse.adb
+++ b/wisitoken-parse-lr-parser-parse.adb
@@ -84,7 +84,9 @@ begin
          if Trace_Parse > Outline then
             Trace.Put_Line ("edited tree does not need parse; no or only 
non_grammar changes");
          end if;
-         Shared_Parser.Tree.Clear_Parse_Streams;
+         Shared_Parser.Tree.Set_Root
+           (Shared_Parser.Tree.Stream_First (Shared_Parser.Tree.Shared_Stream, 
Skip_SOI => True).Node);
+         Shared_Parser.Tree.Finish_Parse;
          Shared_Parser.Parsers.Clear;
          return;
       end if;
@@ -636,7 +638,7 @@ when Partial_Parse =>
       Trace.Put_Clock ("finish partial parse");
    end if;
 
-when Syntax_Error | WisiToken.Parse_Error =>
+when Syntax_Error | WisiToken.Parse_Error | WisiToken.Validate_Error =>
    if Trace_Time then
       Trace.Put_Clock ("finish - error");
    end if;
diff --git a/wisitoken-parse-lr-parser.adb b/wisitoken-parse-lr-parser.adb
index 2f6e4e56dd..5736c89f63 100644
--- a/wisitoken-parse-lr-parser.adb
+++ b/wisitoken-parse-lr-parser.adb
@@ -18,12 +18,9 @@
 --  see file GPL.txt. If not, write to the Free Software Foundation,
 --  59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 --
---  As a special exception, if other files instantiate generics from
---  this unit, or you link this unit with other files to produce an
---  executable, this unit does not by itself cause the resulting
---  executable to be covered by the GNU General Public License. This
---  exception does not however invalidate any other reasons why the
---  executable file might be covered by the GNU Public License.
+--  As a special exception under Section 7 of GPL version 3, you are granted
+--  additional permissions described in the GCC Runtime Library Exception,
+--  version 3.1, as published by the Free Software Foundation.
 
 pragma License (Modified_GPL);
 
@@ -386,12 +383,10 @@ package body WisiToken.Parse.LR.Parser is
                      declare
                         Current_Token : constant Syntax_Trees.Rooted_Ref := 
Shared_Parser.Tree.Current_Token
                           (Parser_State.Stream);
+                        Tree_Root : constant Syntax_Trees.Rooted_Ref := 
Shared_Parser.Tree.Stream_Prev (Current_Token);
                      begin
-
-                        --  Insert EOI on Shared_Stream
-                        if Shared_Parser.Tree.ID (Current_Token.Node) /=
-                          Shared_Parser.Tree.Lexer.Descriptor.EOI_ID
-                        then
+                        if Shared_Parser.Tree.ID (Current_Token.Node) /= 
Shared_Parser.Tree.Lexer.Descriptor.EOI_ID then
+                           --  Insert EOI on Shared_Stream
                            declare
                               Last_Token_Byte_Region_Last : constant 
Buffer_Pos := Shared_Parser.Tree.Byte_Region
                                 (Current_Token.Node, Trailing_Non_Grammar => 
False).Last;
@@ -417,6 +412,22 @@ package body WisiToken.Parse.LR.Parser is
                                  Errors   => Syntax_Trees.Null_Error_List);
                            end;
                         end if;
+
+                        if Shared_Parser.Tree.ID (Tree_Root.Node) /= 
Shared_Parser.Tree.Lexer.Descriptor.Accept_ID then
+                           --  Add Accept_ID node.
+                           declare
+                              Accept_Node : constant Syntax_Trees.Rooted_Ref 
:= Shared_Parser.Tree.Reduce
+                                (Parser_State.Stream,
+                                 Production       =>
+                                   (LHS           => 
Shared_Parser.Tree.Lexer.Descriptor.Accept_ID,
+                                    RHS           => 1),
+                                 Child_Count      => 1,
+                                 State            => Accept_State,
+                                 Recover_Conflict => False);
+                           begin
+                              Shared_Parser.Tree.Set_Root (Accept_Node.Node);
+                           end;
+                        end if;
                      end;
                      raise;
                   end if;
@@ -960,6 +971,7 @@ package body WisiToken.Parse.LR.Parser is
    procedure Finish_Parse
      (Parser            : in out LR.Parser.Parser;
       Incremental_Parse : in     Boolean)
+   with Pre => Parser.Parsers.Count = 1
    --  Final actions after LR accept state reached; call
    --  User_Data.Insert_Token, Delete_Token.
    is
@@ -969,19 +981,31 @@ package body WisiToken.Parse.LR.Parser is
 
       Last_Deleted_Node_Parent : Node_Access;
    begin
+      Parser.Tree.Set_Root (Get_Node (Parser.Tree.Peek 
(Parser.Tree.First_Parse_Stream)));
+
       --  We need parents set in the following code.
+      Parser.Tree.Finish_Parse;
       Parser_State.Clear_Stream;
-      Parser.Tree.Clear_Parse_Streams;
+
+      if Debug_Mode then
+         declare
+            I : Integer := 1;
+         begin
+            for Node of Parser_State.Recover_Insert_Delete loop
+               if not Parser.Tree.In_Tree (Node) then
+                  raise SAL.Programmer_Error with "recover_insert_delete node" 
& I'Image & " not in tree";
+               end if;
+               I := @ + 1;
+            end loop;
+         end;
+      end if;
 
       if Trace_Parse > Extra and then 
Parser_State.Recover_Insert_Delete.Length > 0 then
          Parser.Tree.Lexer.Trace.New_Line;
          Parser.Tree.Lexer.Trace.Put_Line ("before insert/delete tree:");
-         Parser.Tree.Lexer.Trace.Put_Line
-           (Parser.Tree.Image
-              (Children     => True,
-               Non_Grammar  => True,
-               Augmented    => True,
-               Line_Numbers => True));
+         Parser.Tree.Print_Tree
+           (Non_Grammar  => True,
+            Line_Numbers => True);
          Parser.Tree.Lexer.Trace.Put_Line
            ("recover_insert_delete: " & Parser_Lists.Recover_Image 
(Parser_State, Parser.Tree));
          Parser.Tree.Lexer.Trace.New_Line;
@@ -1019,7 +1043,7 @@ package body WisiToken.Parse.LR.Parser is
          end loop;
       end loop;
 
-      if Trace_Parse > Extra or Trace_Action > Extra then
+      if Trace_Parse > Extra or Trace_Action > Detail then
          Parser.Tree.Lexer.Trace.Put_Line ("post-parse tree:");
          Parser.Tree.Lexer.Trace.Put_Line
            (Parser.Tree.Image
@@ -1052,11 +1076,12 @@ package body WisiToken.Parse.LR.Parser is
                end;
                Parser.Tree.Clear_Augmented;
             else
-               Parser.Tree.Validate_Tree (Parser.User_Data.all, 
Error_Reported, Node_Index_Order => False);
+               Parser.Tree.Validate_Tree
+                 (Parser.User_Data.all, Error_Reported, Node_Index_Order => 
not Incremental_Parse);
             end if;
 
             if Error_Reported.Count /= 0 then
-               raise WisiToken.Parse_Error with "parser: validate_tree failed";
+               raise WisiToken.Validate_Error with "parser: validate_tree 
failed";
             end if;
          end;
       end if;
@@ -1742,7 +1767,7 @@ package body WisiToken.Parse.LR.Parser is
                                           Inserted  => True,
                                           Start     => True);
 
-                                       if Tree.ID (Prev_Terminal) = Tree.ID 
(Node) and then
+                                       if Tree.ID (Prev_Terminal.Node) = 
Tree.ID (Node) and then
                                          Tree.Byte_Region (Prev_Terminal, 
Trailing_Non_Grammar => False).Last + 1 =
                                          Node_Byte_Region.First and then
                                          Tree.Lexer.Escape_Delimiter_Doubled 
(Node_ID)
@@ -1861,7 +1886,7 @@ package body WisiToken.Parse.LR.Parser is
                      --  partly past or adjacent to Stable_Region.Last. Also 
exit when last
                      --  KMN is done.
                      exit Unchanged_Loop when
-                       Tree.ID (Terminal) /= Tree.Lexer.Descriptor.SOI_ID and 
then
+                       Tree.ID (Terminal.Node) /= Tree.Lexer.Descriptor.SOI_ID 
and then
                        (if Length (Inserted_Region) = 0 and Length 
(Deleted_Region) = 0
                         then Tree.Byte_Region (Terminal.Node, 
Trailing_Non_Grammar => False).Last >
                           Stable_Region.Last -- Last KMN
@@ -2180,7 +2205,7 @@ package body WisiToken.Parse.LR.Parser is
 
                               if Trace_Incremental_Parse > Detail then
                                  Tree.Lexer.Trace.Put_Line
-                                   ("float non_grammar " & Lexer.Full_Image 
(Token, Tree.Lexer.Descriptor.all));
+                                   ("float non_grammar.1 " & Lexer.Full_Image 
(Token, Tree.Lexer.Descriptor.all));
                               end if;
                            end case;
                         end;
@@ -2490,13 +2515,13 @@ package body WisiToken.Parse.LR.Parser is
                               Do_Scan        := True;
                               Lex_Start_Byte := Inserted_Region.First;
                               Lex_Start_Char := Inserted_Region_Chars.First;
-                              Lex_Start_Line := Tree.Line_Region (Terminal, 
Trailing_Non_Grammar => False).First;
+                              Lex_Start_Line := Tree.Line_At_Node (Terminal, 
Tree.Shared_Stream);
                               Scan_End       := Data.Scan_End;
                            else
                               Do_Scan        := True;
                               Lex_Start_Byte := Terminal_Byte_Region.First;
                               Lex_Start_Char := Tree.Char_Region (Data.Node, 
Trailing_Non_Grammar => False).First;
-                              Lex_Start_Line := Tree.Line_Region (Terminal, 
Trailing_Non_Grammar => False).First;
+                              Lex_Start_Line := Tree.Line_At_Node (Terminal, 
Tree.Shared_Stream);
                               Scan_End       := Data.Scan_End;
                            end if;
                         end;
@@ -2520,7 +2545,7 @@ package body WisiToken.Parse.LR.Parser is
                         Do_Scan        := True;
                         Lex_Start_Byte := Tree.Byte_Region (Data.Node, 
Trailing_Non_Grammar => False).First;
                         Lex_Start_Char := Tree.Char_Region (Data.Node, 
Trailing_Non_Grammar => False).First;
-                        Lex_Start_Line := Tree.Line_Region (Ref, 
Trailing_Non_Grammar => False).First;
+                        Lex_Start_Line := Tree.Line_At_Node (Ref, 
Tree.Shared_Stream);
                         Scan_End       := Data.Scan_End;
 
                         if Terminal_Non_Grammar_Next /= 
Lexer.Token_Arrays.No_Index then
@@ -2616,9 +2641,7 @@ package body WisiToken.Parse.LR.Parser is
                               Lex_Start_Line :=
                                 (if Terminal_Non_Grammar_Next > 
Non_Grammar.First_Index
                                  then Non_Grammar (Terminal_Non_Grammar_Next - 
1).Line_Region.Last
-                                 else Tree.Line_Region
-                                   (Tree.Prev_Source_Terminal (Terminal, 
Trailing_Non_Grammar => True),
-                                    Trailing_Non_Grammar => True).Last);
+                                 else Tree.Line_At_Node (Terminal, 
Tree.Shared_Stream));
                               Do_Scan := True;
                            else
                               --  Edit start is in or just after Token
@@ -2663,13 +2686,13 @@ package body WisiToken.Parse.LR.Parser is
                                     Delayed_Lex_Start_Line := Lex_Start_Line;
                                     if Trace_Incremental_Parse > Detail then
                                        Tree.Lexer.Trace.Put_Line
-                                         ("scan delayed" & 
Lex_Start_Byte'Image &
+                                         ("scan delayed 1" & 
Lex_Start_Byte'Image &
                                             (if Scan_End /= Invalid_Buffer_Pos
                                              then " .." & Scan_End'Image
                                              else ""));
                                        if Trace_Incremental_Parse > Extra then
                                           Tree.Lexer.Trace.Put_Line
-                                            ("float non_grammar" & I'Image & 
":" &
+                                            ("float non_grammar.2" & I'Image & 
":" &
                                                Lexer.Full_Image (Non_Grammar 
(I), Tree.Lexer.Descriptor.all));
                                        end if;
                                     end if;
@@ -2695,7 +2718,7 @@ package body WisiToken.Parse.LR.Parser is
                                  Floating_Non_Grammar.Append (Non_Grammar (I));
                                  if Trace_Incremental_Parse > Extra then
                                     Tree.Lexer.Trace.Put_Line
-                                      ("float non_grammar" & I'Image & ":" &
+                                      ("float non_grammar.3" & I'Image & ":" &
                                          Lexer.Full_Image (Non_Grammar (I), 
Tree.Lexer.Descriptor.all));
                                  end if;
                                  Last_Floated := I;
@@ -2712,7 +2735,7 @@ package body WisiToken.Parse.LR.Parser is
                         if Trace_Incremental_Parse > Detail then
                            if Last_Floated /= Lexer.Token_Arrays.No_Index then
                               Tree.Lexer.Trace.Put_Line
-                                ("float non_grammar" & 
Terminal_Non_Grammar_Next'Image & " .." &
+                                ("float non_grammar.4" & 
Terminal_Non_Grammar_Next'Image & " .." &
                                    Last_Floated'Image);
                            end if;
                         end if;
@@ -2734,8 +2757,7 @@ package body WisiToken.Parse.LR.Parser is
                            Lex_Start_Char := Tree.Char_Region (Terminal.Node, 
Trailing_Non_Grammar => False).First +
                              Shift_Chars;
 
-                           --  Line_Region.First is from 
prev_terminal.non_grammar, which is shifted
-                           Lex_Start_Line := Tree.Line_Region (Terminal, 
Trailing_Non_Grammar => False).First;
+                           Lex_Start_Line := Tree.Line_At_Node (Terminal, 
Tree.Shared_Stream);
                         else
                            --  We never re-scan eoi; we just shift it.
                            null;
@@ -2746,8 +2768,7 @@ package body WisiToken.Parse.LR.Parser is
                         Lex_Start_Char := Tree.Char_Region (Terminal.Node, 
Trailing_Non_Grammar => False).First +
                           Shift_Chars;
 
-                        --  Line_Region.First is from 
prev_terminal.non_grammar, which is shifted
-                        Lex_Start_Line := Tree.Line_Region (Terminal, 
Trailing_Non_Grammar => False).First;
+                        Lex_Start_Line := Tree.Line_At_Node (Terminal, 
Tree.Shared_Stream);
 
                         if Tree.Lexer.Is_Block_Delimited (Tree.ID 
(Terminal.Node)) then
                            Check_Scan_End (Terminal.Node);
@@ -2980,7 +3001,7 @@ package body WisiToken.Parse.LR.Parser is
                      Delayed_Lex_Start_Line := Lex_Start_Line;
 
                      if Trace_Incremental_Parse > Detail then
-                        Tree.Lexer.Trace.Put_Line ("scan delayed");
+                        Tree.Lexer.Trace.Put_Line ("scan delayed 2");
                      end if;
                   end if;
                end if;
@@ -3167,7 +3188,7 @@ package body WisiToken.Parse.LR.Parser is
                        (if Tree.Byte_Region (Terminal.Node, 
Trailing_Non_Grammar => False).First <= Stable_Region.Last
                         then -KMN.Deleted_Bytes + KMN.Inserted_Bytes else 0) > 
Scanned_Byte_Pos;
 
-                     if Tree.ID (Terminal) = Tree.Lexer.Descriptor.SOI_ID then
+                     if Tree.ID (Terminal.Node) = Tree.Lexer.Descriptor.SOI_ID 
then
                         Tree.Next_Terminal (Terminal);
 
                      else
@@ -3203,7 +3224,7 @@ package body WisiToken.Parse.LR.Parser is
                               else
                                  if Trace_Incremental_Parse > Detail then
                                     Tree.Lexer.Trace.Put_Line
-                                      ("float non_grammar " & Lexer.Full_Image 
(Token, Tree.Lexer.Descriptor.all));
+                                      ("float non_grammar.5 " & 
Lexer.Full_Image (Token, Tree.Lexer.Descriptor.all));
                                  end if;
                                  Floating_Non_Grammar.Append (Token);
                               end if;
@@ -3251,7 +3272,7 @@ package body WisiToken.Parse.LR.Parser is
                   begin
                      loop
                         if Searching_Back then
-                           if Tree.ID (Terminal) = 
Tree.Lexer.Descriptor.SOI_ID then
+                           if Tree.ID (Terminal.Node) = 
Tree.Lexer.Descriptor.SOI_ID then
                               return Terminal;
                            end if;
 
@@ -3435,87 +3456,4 @@ package body WisiToken.Parse.LR.Parser is
       Pre_Edited       : in     Boolean        := False)
    is separate;
 
-   overriding procedure Execute_Actions
-     (Parser              : in out LR.Parser.Parser;
-      Action_Region_Bytes : in     WisiToken.Buffer_Region)
-   is
-      use all type Syntax_Trees.Post_Parse_Action;
-      use all type Syntax_Trees.User_Data_Access;
-
-      procedure Process_Node
-        (Tree : in out Syntax_Trees.Tree;
-         Node : in     Syntax_Trees.Valid_Node_Access)
-      is
-         use all type Syntax_Trees.Node_Label;
-         Node_Byte_Region : constant Buffer_Region := Tree.Byte_Region
-           (Node, Trailing_Non_Grammar => True);
-      begin
-         if Tree.Label (Node) /= Nonterm or else
-           not (Node_Byte_Region = Null_Buffer_Region or
-                  Overlaps (Node_Byte_Region, Action_Region_Bytes))
-         then
-            return;
-         end if;
-
-         for Child of Tree.Children (Node) loop
-            if Child /= Syntax_Trees.Invalid_Node_Access then
-               --  Child can be null in an edited tree
-               Process_Node (Tree, Child);
-            end if;
-         end loop;
-
-         Parser.User_Data.Reduce (Tree, Node);
-         declare
-            Post_Parse_Action : constant Syntax_Trees.Post_Parse_Action := 
Parser.Get_Post_Parse_Action
-              (Tree.Production_ID (Node));
-         begin
-            if Post_Parse_Action /= null then
-               begin
-                  Post_Parse_Action (Parser.User_Data.all, Tree, Node);
-               exception
-               when E : others =>
-                  if WisiToken.Debug_Mode then
-                     Parser.Tree.Lexer.Trace.Put_Line
-                       (Ada.Exceptions.Exception_Name (E) & ": " & 
Ada.Exceptions.Exception_Message (E));
-                     Parser.Tree.Lexer.Trace.Put_Line 
(GNAT.Traceback.Symbolic.Symbolic_Traceback (E));
-                     Parser.Tree.Lexer.Trace.New_Line;
-                  end if;
-
-                  raise WisiToken.Parse_Error with Tree.Error_Message
-                    (Node,
-                     "action raised exception " & 
Ada.Exceptions.Exception_Name (E) & ": " &
-                       Ada.Exceptions.Exception_Message (E));
-               end;
-            end if;
-         end;
-      end Process_Node;
-
-   begin
-      if Parser.User_Data = null then
-         return;
-      end if;
-
-      if Parser.Tree.Root = Syntax_Trees.Invalid_Node_Access then
-         --  No code in file, and error recovery failed to insert valid code.
-         --  Or ambiguous parse; Finish_Parse not called.
-         return;
-      end if;
-
-      Parser.User_Data.Initialize_Actions (Parser.Tree);
-
-      Process_Node (Parser.Tree, Parser.Tree.Root);
-   exception
-   when WisiToken.Parse_Error =>
-      raise;
-
-   when E : others =>
-      if Debug_Mode then
-         Parser.Tree.Lexer.Trace.Put_Line
-           (Ada.Exceptions.Exception_Name (E) & ": " & 
Ada.Exceptions.Exception_Message (E));
-         Parser.Tree.Lexer.Trace.Put_Line 
(GNAT.Traceback.Symbolic.Symbolic_Traceback (E));
-         Parser.Tree.Lexer.Trace.New_Line;
-      end if;
-      raise;
-   end Execute_Actions;
-
 end WisiToken.Parse.LR.Parser;
diff --git a/wisitoken-parse-lr-parser.ads b/wisitoken-parse-lr-parser.ads
index 1aafb8a2c6..da9495faf5 100644
--- a/wisitoken-parse-lr-parser.ads
+++ b/wisitoken-parse-lr-parser.ads
@@ -92,12 +92,10 @@ package WisiToken.Parse.LR.Parser is
       Max_Sequential_Index : Syntax_Trees.Sequential_Index := 
Syntax_Trees.Sequential_Index'First;
 
       Parsers : aliased Parser_Lists.List;
-
-      Partial_Parse_Active    : access Boolean;
-      Partial_Parse_Byte_Goal : access WisiToken.Buffer_Pos;
-      --  Used by In_Parse_Actions to terminate Partial_Parse.
    end record;
 
+   type Parser_Access is access 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
@@ -129,14 +127,4 @@ package WisiToken.Parse.LR.Parser is
       Edits            : in     KMN_Lists.List := KMN_Lists.Empty_List;
       Pre_Edited       : in     Boolean        := False);
 
-   overriding procedure Execute_Actions
-     (Parser              : in out LR.Parser.Parser;
-      Action_Region_Bytes : in     WisiToken.Buffer_Region);
-   --  Call Parser.User_Data.Insert_Token, Parser.User_Data.Delete_Token
-   --  on any tokens inserted/deleted by error recovery. Update
-   --  Parser.Line_Begin_Tokens to reflect error recovery. Then call
-   --  User_Data.Reduce and the grammar post parse actions on all
-   --  nonterms in the syntax tree that overlap Action_Region_Bytes, by
-   --  traversing the tree in depth-first order.
-
 end WisiToken.Parse.LR.Parser;
diff --git a/wisitoken-parse-lr-parser_no_recover.adb 
b/wisitoken-parse-lr-parser_no_recover.adb
index 035ad13eb5..d1296e94ef 100644
--- a/wisitoken-parse-lr-parser_no_recover.adb
+++ b/wisitoken-parse-lr-parser_no_recover.adb
@@ -27,8 +27,6 @@
 
 pragma License (Modified_GPL);
 
-with Ada.Exceptions;
-with GNAT.Traceback.Symbolic;
 package body WisiToken.Parse.LR.Parser_No_Recover is
 
    procedure Reduce_Stack_1
@@ -419,7 +417,9 @@ package body WisiToken.Parse.LR.Parser_No_Recover is
          end;
       end loop Main_Loop;
 
-      Shared_Parser.Tree.Clear_Parse_Streams;
+      Shared_Parser.Tree.Set_Root
+        (Syntax_Trees.Get_Node (Shared_Parser.Tree.Peek 
(Shared_Parser.Tree.First_Parse_Stream)));
+      Shared_Parser.Tree.Finish_Parse;
 
       if Trace_Action > Extra then
          Trace.Put_Line
@@ -436,70 +436,4 @@ package body WisiToken.Parse.LR.Parser_No_Recover is
       --  character.
    end Parse;
 
-   procedure Execute_Actions
-     (Tree        : in out Syntax_Trees.Tree;
-      Productions : in     Syntax_Trees.Production_Info_Trees.Vector;
-      User_Data   : in     Syntax_Trees.User_Data_Access)
-   is
-      use all type Syntax_Trees.User_Data_Access;
-      procedure Process_Node
-        (Tree : in out Syntax_Trees.Tree;
-         Node : in     Syntax_Trees.Valid_Node_Access)
-      is
-         use Syntax_Trees;
-      begin
-         if Tree.Label (Node) /= Nonterm then
-            return;
-         end if;
-
-         User_Data.Reduce (Tree, Node);
-
-         declare
-            Action : constant Syntax_Trees.Post_Parse_Action := 
Get_Post_Parse_Action
-              (Productions, Tree.Production_ID (Node));
-         begin
-            if Action /= null then
-               begin
-                  Action (User_Data.all, Tree, Node);
-               exception
-               when E : others =>
-                  if Trace_Tests > Outline then
-                     --  running a unit test; exception may be AUnit assert 
fail
-                     raise;
-
-                  elsif WisiToken.Debug_Mode then
-                     Tree.Lexer.Trace.Put_Line
-                       (GNAT.Traceback.Symbolic.Symbolic_Traceback (E)); -- 
includes Prefix
-                     Tree.Lexer.Trace.New_Line;
-                  end if;
-
-                  raise WisiToken.Parse_Error with Tree.Error_Message
-                    (Node, "action raised exception " & 
Ada.Exceptions.Exception_Name (E) & ": " &
-                       Ada.Exceptions.Exception_Message (E));
-               end;
-            end if;
-         end;
-      end Process_Node;
-
-   begin
-      User_Data.Initialize_Actions (Tree);
-      Tree.Process_Tree (Process_Node'Access);
-   end Execute_Actions;
-
-   overriding procedure Execute_Actions
-     (Parser              : in out LR.Parser_No_Recover.Parser;
-      Action_Region_Bytes : in     WisiToken.Buffer_Region := 
WisiToken.Null_Buffer_Region)
-   is
-      use all type WisiToken.Syntax_Trees.User_Data_Access;
-      pragma Unreferenced (Action_Region_Bytes);
-   begin
-      if Parser.User_Data /= null then
-         if Parser.Parsers.Count > 1 then
-            raise Syntax_Error with "ambiguous parse; can't execute actions";
-         end if;
-      end if;
-
-      Execute_Actions (Parser.Tree, Parser.Productions, Parser.User_Data);
-   end Execute_Actions;
-
 end WisiToken.Parse.LR.Parser_No_Recover;
diff --git a/wisitoken-parse-lr-parser_no_recover.ads 
b/wisitoken-parse-lr-parser_no_recover.ads
index ac5169d8b1..cea1eba955 100644
--- a/wisitoken-parse-lr-parser_no_recover.ads
+++ b/wisitoken-parse-lr-parser_no_recover.ads
@@ -53,16 +53,4 @@ package WisiToken.Parse.LR.Parser_No_Recover is
    --  Raises SAL.Programmer_Error if Edits is not empty. Pre_Edited and
    --  Log_File are ignored.
 
-   overriding procedure Execute_Actions
-     (Parser              : in out LR.Parser_No_Recover.Parser;
-      Action_Region_Bytes : in     WisiToken.Buffer_Region := 
WisiToken.Null_Buffer_Region);
-   --  Action_Region_Bytes is ignored (all nodes always processed).
-
-   procedure Execute_Actions
-     (Tree        : in out Syntax_Trees.Tree;
-      Productions : in     Syntax_Trees.Production_Info_Trees.Vector;
-      User_Data   : in     Syntax_Trees.User_Data_Access);
-   --  Implements Execute_Actions, allows specifying different tree
-   --  (needed by wisitoken-bnf-generate).
-
 end WisiToken.Parse.LR.Parser_No_Recover;
diff --git a/wisitoken-parse-lr.adb b/wisitoken-parse-lr.adb
index 7c82f23144..86e230fe9c 100644
--- a/wisitoken-parse-lr.adb
+++ b/wisitoken-parse-lr.adb
@@ -335,6 +335,19 @@ package body WisiToken.Parse.LR is
       end loop;
    end Set_McKenzie_Options;
 
+   procedure Set_McKenzie_Help
+   is
+      use Ada.Text_IO;
+   begin
+      --  param alphabetical order
+      Put_Line ("check_delta_limit|check_delta");
+      Put_Line ("check_limit");
+      Put_Line ("enqueue_limit");
+      Put_Line ("full_explore");
+      Put_Line ("high_cost");
+      Put_Line ("zombie_limit");
+   end Set_McKenzie_Help;
+
    function Goto_For
      (Table : in Parse_Table;
       State : in State_Index;
diff --git a/wisitoken-parse-lr.ads b/wisitoken-parse-lr.ads
index c6bc218455..bcc4b2fd92 100644
--- a/wisitoken-parse-lr.ads
+++ b/wisitoken-parse-lr.ads
@@ -319,6 +319,10 @@ package WisiToken.Parse.LR is
    --  Set options from Config. Config contains space-separated name=value
    --  pairs. See body for exact names.
 
+   procedure Set_McKenzie_Help;
+   --  Output to Ada.Text_IO.Current_Output the list of keys for
+   --  Set_Mckenzie_Options.
+
    type Parse_Table
      (State_First       : State_Index;
       State_Last        : State_Index;
@@ -330,7 +334,7 @@ package WisiToken.Parse.LR is
    record
       States                : Parse_State_Array (State_First .. State_Last);
       Error_Action          : Parse_Action_Node_Ptr;
-      Error_Recover_Enabled : Boolean;
+      Error_Recover_Enabled : Boolean := False;
       McKenzie_Param        : McKenzie_Param_Type (First_Terminal, 
Last_Terminal, First_Nonterminal, Last_Nonterminal);
       Max_Parallel          : SAL.Base_Peek_Type := 15;
    end record;
diff --git a/wisitoken-parse-packrat-generated.adb 
b/wisitoken-parse-packrat-generated.adb
index 54ee0faf5c..81589db173 100644
--- a/wisitoken-parse-packrat-generated.adb
+++ b/wisitoken-parse-packrat-generated.adb
@@ -28,27 +28,18 @@ package body WisiToken.Parse.Packrat.Generated is
       pragma Unreferenced (Log_File, Pre_Edited);
       use all type WisiToken.Syntax_Trees.User_Data_Access;
       use all type Ada.Containers.Count_Type;
-      Descriptor : WisiToken.Descriptor renames 
Parser.Tree.Lexer.Descriptor.all;
-
-      Result : Memo_Entry;
+      Trace      : WisiToken.Trace'Class renames Parser.Tree.Lexer.Trace.all;
+      Result     : Memo_Entry;
    begin
       if Edits.Length > 0 then
          raise WisiToken.Parse_Error;
       end if;
 
-      for Deriv of Parser.Derivs loop
-         for Memo of Deriv loop
-            case Memo.State is
-            when No_Result | Failure =>
-               null;
-            when Success =>
-               Memo.Last_Pos := Syntax_Trees.Invalid_Stream_Index;
-            end case;
-         end loop;
-      end loop;
-
-      Parser.Derivs.Set_First_Last (Descriptor.First_Nonterminal, 
Descriptor.Last_Nonterminal);
+      if Trace_Time then
+         Trace.Put_Clock ("start");
+      end if;
 
+      Clear (Parser.Derivs);
       Parser.Tree.Clear;
 
       if Parser.User_Data /= null then
@@ -56,31 +47,13 @@ package body WisiToken.Parse.Packrat.Generated is
       end if;
       Parser.Lex_All; -- Creates Tree.Shared_Stream
 
-      --  WORKAROUND: there appears to be a bug in GNAT Community 2021 that 
makes
-      --  ref_count fail in this usage. May be related to AdaCore ticket 
V107-045.
+      --  FIXME: ref_count fails in this usage; works in procedural.
       Parser.Tree.Enable_Ref_Count_Check (Parser.Tree.Shared_Stream, Enable => 
False);
 
-      for Nonterm in Descriptor.First_Nonterminal .. 
Descriptor.Last_Nonterminal loop
-         Parser.Derivs (Nonterm).Clear (Free_Memory => True);
-         Parser.Derivs (Nonterm).Set_First_Last
-           (Parser.Tree.Get_Node_Index
-              (Parser.Tree.Shared_Stream, Parser.Tree.Stream_First 
(Parser.Tree.Shared_Stream, Skip_SOI => True)),
-            Parser.Tree.Get_Node_Index
-              (Parser.Tree.Shared_Stream, Parser.Tree.Stream_Last 
(Parser.Tree.Shared_Stream, Skip_EOI => False)));
-      end loop;
-
       Result := Parser.Parse_WisiToken_Accept
         (Parser, Parser.Tree.Stream_First (Parser.Tree.Shared_Stream, Skip_SOI 
=> False));
 
-      if Result.State /= Success then
-         if Trace_Parse > Outline then
-            Parser.Tree.Lexer.Trace.Put_Line ("parse failed");
-         end if;
-
-         raise Syntax_Error with "parse failed"; --  FIXME packrat: need 
better error message!
-      else
-         Parser.Tree.Set_Root (Result.Result);
-      end if;
+      Parser.Finish_Parse (Result);
 
    end Parse;
 
diff --git a/wisitoken-parse-packrat-generated.ads 
b/wisitoken-parse-packrat-generated.ads
index fe4153a851..d36600dc02 100644
--- a/wisitoken-parse-packrat-generated.ads
+++ b/wisitoken-parse-packrat-generated.ads
@@ -26,44 +26,15 @@ package WisiToken.Parse.Packrat.Generated is
 
    Recursive : exception;
 
-   type Memo_State is (No_Result, Failure, Success);
-   subtype Result_States is Memo_State range Failure .. Success;
-
-   type Memo_Entry (State : Memo_State := No_Result) is record
-
-      case State is
-      when No_Result =>
-         Recursive : Boolean := False;
-
-      when Failure =>
-         null;
-
-      when Success =>
-         Result : aliased Syntax_Trees.Node_Access;
-
-         Last_Pos : Syntax_Trees.Stream_Index;
-      end case;
-   end record;
-
-   subtype Positive_Node_Index is Syntax_Trees.Node_Index range 1 .. 
Syntax_Trees.Node_Index'Last;
-   package Memos is new SAL.Gen_Unbounded_Definite_Vectors
-     (Positive_Node_Index, Memo_Entry, Default_Element => (others => <>));
-   --  Memos is indexed by Node_Index of terminals in Shared_Stream
-   --  (incremental parse is not supported).
-
-   subtype Result_Type is Memo_Entry
-   with Dynamic_Predicate => Result_Type.State in Result_States;
-
-   package Derivs is new SAL.Gen_Unbounded_Definite_Vectors
-     (Token_ID, Memos.Vector, Default_Element => Memos.Empty_Vector);
+   type Parser;
 
    type Parse_WisiToken_Accept is access
-     --  WORKAROUND: using Packrat.Parser'Class here hits a GNAT Bug box in 
GPL 2018.
-     function (Parser : in out Base_Parser'Class; Last_Pos : in 
Syntax_Trees.Stream_Index) return Result_Type;
-
-   type Parser is new Packrat.Parser with record
-      Derivs : Generated.Derivs.Vector; --  FIXME packrat: use discriminated 
array, as in procedural
+     function (Parser : in out Packrat.Generated.Parser; Last_Pos : in 
Syntax_Trees.Stream_Index) return Result_Type;
 
+   type Parser (First_Nonterminal, Last_Nonterminal : Token_ID) is new 
WisiToken.Parse.Packrat.Parser
+     (First_Nonterminal => First_Nonterminal,
+      Last_Nonterminal  => Last_Nonterminal)
+   with record
       Parse_WisiToken_Accept : Generated.Parse_WisiToken_Accept;
    end record;
 
diff --git a/wisitoken-parse-packrat-procedural.adb 
b/wisitoken-parse-packrat-procedural.adb
index 3e70804e40..be74ebe175 100644
--- a/wisitoken-parse-packrat-procedural.adb
+++ b/wisitoken-parse-packrat-procedural.adb
@@ -17,6 +17,7 @@
 
 pragma License (Modified_GPL);
 
+with WisiToken.In_Parse_Actions;
 package body WisiToken.Parse.Packrat.Procedural is
 
    function Apply_Rule
@@ -36,6 +37,31 @@ package body WisiToken.Parse.Packrat.Procedural is
    ----------
    --  bodies
 
+   procedure Trace_Deriv_Success
+     (Parser : in out Procedural.Parser;
+      Pos    : in     WisiToken.Syntax_Trees.Stream_Index;
+      Memo   : in     Success_Memo_Entry)
+   is
+      use Syntax_Trees;
+      Tree : Syntax_Trees.Tree renames Parser.Tree;
+   begin
+      --  match LR parse trace with trace_parse=2
+      Tree.Lexer.Trace.Put_Line
+        ((if Trace_Parse > Extra
+          then Node_Index'Image (Tree.Get_Node_Index (Tree.Shared_Stream, 
Pos)) & "; "
+          else "") &
+           Tree.Image
+             (Memo.Result,
+              Children              => True,
+              Node_Numbers          => Trace_Parse > Extra,
+              Terminal_Node_Numbers => True,
+              RHS_Index             => True) &
+           (if Trace_Parse > Extra
+            then " last_pos" & Node_Index'Image (Tree.Get_Node_Index 
(Tree.Shared_Stream, Memo.Last_Pos)) &
+              " max_ex_pos" & Node_Index'Image (Tree.Get_Node_Index 
(Tree.Shared_Stream, Memo.Max_Examined_Pos))
+            else ""));
+   end Trace_Deriv_Success;
+
    function Eval
      (Parser   : in out Procedural.Parser;
       R        : in     Token_ID;
@@ -46,12 +72,31 @@ package body WisiToken.Parse.Packrat.Procedural is
 
       Tree       : Syntax_Trees.Tree renames Parser.Tree;
       Descriptor : WisiToken.Descriptor renames Tree.Lexer.Descriptor.all;
+      Trace      : WisiToken.Trace'Class renames Tree.Lexer.Trace.all;
 
       subtype Terminal is Token_ID range Descriptor.First_Terminal .. 
Descriptor.Last_Terminal;
 
       Pos      : Syntax_Trees.Stream_Index := Last_Pos; --  last token parsed.
       Next_Pos : Syntax_Trees.Stream_Index := Tree.Stream_Next 
(Tree.Shared_Stream, Pos);
+
+      Max_Examined_Pos : Syntax_Trees.Stream_Index := Last_Pos;
+
+      procedure Update_Max_Examined_Pos (New_Pos : in 
Syntax_Trees.Stream_Index)
+      is begin
+         if Tree.Byte_Region
+           (Tree.Get_Node (Tree.Shared_Stream, New_Pos), Trailing_Non_Grammar 
=> False).First >
+           Tree.Byte_Region
+             (Tree.Get_Node (Tree.Shared_Stream, Max_Examined_Pos), 
Trailing_Non_Grammar => False).First
+         then
+            Max_Examined_Pos := New_Pos;
+         end if;
+      end Update_Max_Examined_Pos;
+
    begin
+      if Trace_Parse > Extra then
+         Trace.Put_Line ("eval: " & Image (R, Descriptor) & " @" & Image_Pos 
(Next_Pos));
+      end if;
+
       for RHS_Index in Parser.Grammar (R).RHSs.First_Index .. Parser.Grammar 
(R).RHSs.Last_Index loop
          declare
             use all type Ada.Containers.Count_Type;
@@ -59,40 +104,78 @@ package body WisiToken.Parse.Packrat.Procedural is
             Memo : Memo_Entry; --  for temporary or intermediate results
          begin
             if RHS.Tokens.Length = 0 then
-               return
+               return Result : constant Memo_Entry :=
                  (State            => Success,
+                  Max_Examined_Pos => Max_Examined_Pos,
                   Result           => Tree.Add_Nonterm
                     (Production    => (R, RHS_Index),
                      Children      => (1 .. 0 => 
Syntax_Trees.Invalid_Node_Access),
                      Clear_Parents => False),
-                  Last_Pos         => Pos);
+                  Last_Pos         => Pos)
+               do
+                  if Trace_Parse > Extra then
+                     Trace.Put_Line (Image (Result, R, RHS_Index, Pos, Tree));
+                  end if;
+               end return;
             else
                declare
+                  use all type 
WisiToken.Syntax_Trees.In_Parse_Actions.In_Parse_Action;
+                  use all type WisiToken.Syntax_Trees.Node_Access;
                   Children : Syntax_Trees.Node_Access_Array
                     (SAL.Base_Peek_Type (RHS.Tokens.First_Index) .. 
SAL.Base_Peek_Type (RHS.Tokens.Last_Index));
+
+                  In_Parse_Action : constant 
Syntax_Trees.In_Parse_Actions.In_Parse_Action :=
+                    Parser.Get_In_Parse_Action ((R, RHS_Index));
                begin
                   for I in RHS.Tokens.First_Index .. RHS.Tokens.Last_Index loop
+                     if Trace_Parse > Extra then
+                        Trace.Put (Image (Production_ID'(R, RHS_Index), 
Descriptor) & "," & I'Image & ": ");
+                     end if;
+
                      if RHS.Tokens (I) in Terminal then
                         if Next_Pos = Syntax_Trees.Invalid_Stream_Index then
+                           --  We don't update Max_Examined_Pos here; it must 
already be EOI
+                           pragma Assert (Tree.Get_Node (Tree.Shared_Stream, 
Max_Examined_Pos) = Tree.EOI);
                            goto Fail_RHS;
 
-                        elsif Tree.ID (Tree.Shared_Stream, Next_Pos) = 
RHS.Tokens (I) then
-                           Pos := Next_Pos;
-                           Next_Pos := Tree.Stream_Next (Tree.Shared_Stream, 
Pos);
-                           Children (SAL.Base_Peek_Type (I)) := Tree.Get_Node 
(Tree.Shared_Stream, Pos);
                         else
-                           goto Fail_RHS;
+                           if Children (SAL.Base_Peek_Type (I)) = 
Syntax_Trees.Invalid_Node_Access then
+                              if Tree.ID (Next_Pos) = RHS.Tokens (I) then
+                                 Pos := Next_Pos;
+                                 Next_Pos := Tree.Stream_Next 
(Tree.Shared_Stream, Pos);
+                                 Children (SAL.Base_Peek_Type (I)) := 
Tree.Get_Node (Tree.Shared_Stream, Pos);
+                                 --  FIXME: why not Update_Max_Examined_Pos 
here?
+
+                                 if Trace_Parse > Extra then
+                                    Trace.Put_Line
+                                      (Tree.Image (Children 
(SAL.Base_Peek_Type (I)), Node_Numbers => True));
+                                 end if;
+
+                              else
+                                 Update_Max_Examined_Pos (Next_Pos);
+                                 goto Fail_RHS;
+                              end if;
+                           end if;
                         end if;
-                     else
+
+                     else -- not Terminal
                         Memo := Apply_Rule (Parser, RHS.Tokens (I), Pos);
+                        Update_Max_Examined_Pos (Memo.Max_Examined_Pos);
+
                         case Memo.State is
                         when Success =>
+                           if Trace_Parse > Extra then
+                              Trace.Put_Line
+                                (Image (Production_ID'(R, RHS_Index), 
Descriptor) & "," & I'Image & ": " &
+                                   Tree.Image (Memo.Result, Node_Numbers => 
True, RHS_Index => True));
+                           end if;
                            Children (SAL.Base_Peek_Type (I)) := Memo.Result;
                            Pos := Memo.Last_Pos;
                            Next_Pos := Tree.Stream_Next (Tree.Shared_Stream, 
Pos);
 
                         when Failure =>
                            goto Fail_RHS;
+
                         when No_Result =>
                            raise SAL.Programmer_Error;
                         end case;
@@ -100,22 +183,63 @@ package body WisiToken.Parse.Packrat.Procedural is
                   end loop;
 
                   return Result : constant Memo_Entry :=
-                    (State              => Success,
-                     Result             => Parser.Tree.Add_Nonterm
-                       (Production      => (R, RHS_Index),
-                        Children        => Syntax_Trees.To_Valid_Node_Access 
(Children),
-                        Clear_Parents   => True),
+                    (State            => Success,
+                     Max_Examined_Pos => Max_Examined_Pos,
+                     Result           => Parser.Tree.Add_Nonterm
+                       (Production    => (R, RHS_Index),
+                        Children      => Syntax_Trees.To_Valid_Node_Access 
(Children),
+                        Clear_Parents => True),
                      --  We must be able to steal nodes from failed nonterms;
                      --  body_instantiation_conflict.wy.
-                     Last_Pos           => Pos)
+                     Last_Pos         => Pos)
                   do
                      if Trace_Parse > Extra then
-                        Parser.Tree.Lexer.Trace.Put_Line
-                          ("eval: " & Parser.Tree.Image (Root => 
Result.Result, Children => True));
+                        Trace.Put_Line (Image (Result, R, RHS_Index, Pos, 
Tree));
+                     end if;
+
+                     if In_Parse_Action = null then
+                        null;
+
+                     else
+                        declare
+                           Nonterm_Token : Syntax_Trees.Recover_Token := 
Parser.Tree.Get_Recover_Token (Result.Result);
+
+                           Children_Token : constant 
Syntax_Trees.Recover_Token_Array :=
+                             Parser.Tree.Children_Recover_Tokens 
(Result.Result);
+                           Status         : constant 
Syntax_Trees.In_Parse_Actions.Status := In_Parse_Action
+                             (Parser.Tree, Nonterm_Token, Children_Token, 
Recover_Active => False);
+                        begin
+                           if Trace_Parse > Extra then
+                              Trace.Put_Line
+                                ("in_parse_action " & 
WisiToken.In_Parse_Actions.Image
+                                   (Status, Tree, Result.Result));
+                           end if;
+
+                           case Status.Label is
+                           when Syntax_Trees.In_Parse_Actions.Ok =>
+                              null;
+
+                           when Syntax_Trees.In_Parse_Actions.Error =>
+                              raise SAL.Not_Implemented with "packrat 
in_parse_actions fail";
+                              --  FIXME: store the error somewhere, raise a 
different exception?
+                              --  Parser.Tree.Add_Error_To_Stack_Top
+                              --    (Parser_State.Stream,
+                              --     In_Parse_Action_Error'
+                              --       (Status       => Status,
+                              --        Recover_Ops  => 
Recover_Op_Arrays.Empty_Vector,
+                              --        Recover_Cost => 0),
+                              --     Parser.User_Data);
+                           end case;
+                        end;
                      end if;
                   end return;
 
                   <<Fail_RHS>>
+                  if Trace_Parse > Extra then
+                     Trace.Put_Line
+                       (Image (Production_ID'(R, RHS_Index), Descriptor) & " 
@" &
+                          Image_Pos (Next_Pos) & ": fail");
+                  end if;
                   Pos := Last_Pos;
                   Next_Pos := Tree.Stream_Next (Tree.Shared_Stream, Pos);
                end;
@@ -124,7 +248,7 @@ package body WisiToken.Parse.Packrat.Procedural is
       end loop;
       --  get here when all RHSs fail
 
-      return (State => Failure);
+      return (Failure, Max_Examined_Pos);
    end Eval;
 
    function Apply_Rule
@@ -138,47 +262,48 @@ package body WisiToken.Parse.Packrat.Procedural is
 
       Tree       : Syntax_Trees.Tree renames Parser.Tree;
       Descriptor : WisiToken.Descriptor renames Tree.Lexer.Descriptor.all;
+      Trace      : WisiToken.Trace'Class renames Parser.Tree.Lexer.Trace.all;
 
       Pos       : Syntax_Trees.Stream_Index          := Last_Pos; --  last 
token parsed.
       Start_Pos : constant Syntax_Trees.Stream_Index := Tree.Stream_Next
         (Tree.Shared_Stream, Last_Pos);                         --  first 
token in current nonterm
-      Memo      : Memo_Entry                         := Parser.Derivs (R)
-        (Tree.Get_Node_Index (Tree.Shared_Stream, Start_Pos));
+      Memo      : Memo_Entry                         := Get_Deriv
+        (Parser.Derivs, R, Tree.Get_Node_Index (Tree.Shared_Stream, 
Start_Pos));
 
       Pos_Recurse_Last : Syntax_Trees.Stream_Index := Last_Pos;
       Result_Recurse   : Memo_Entry;
    begin
       case Memo.State is
-      when Success =>
+      when Success | Failure =>
+         if Trace_Parse > Extra then
+            Trace.Put_Line ("apply memo:" & Image (Memo, R, Start_Pos, Tree));
+         end if;
          return Memo;
 
-      when Failure =>
-         return (State => Failure);
-
       when No_Result =>
          if Parser.Direct_Left_Recursive (R) then
-            Parser.Derivs (R).Replace_Element
-              (Tree.Get_Node_Index (Tree.Shared_Stream, Start_Pos), (State => 
Failure));
+            Set_Deriv
+              (Parser.Derivs, R, Tree.Get_Node_Index (Tree.Shared_Stream, 
Start_Pos),
+               (Failure, Last_Pos));
          else
             Memo := Eval (Parser, R, Last_Pos);
 
-            if (Trace_Parse > Detail and Memo.State = Success) or Trace_Parse 
> Extra then
-               case Memo.State is
-               when Success =>
-                  Parser.Tree.Lexer.Trace.Put_Line
-                    (Parser.Tree.Image (Memo.Result, Children => True, 
Terminal_Node_Numbers => True));
-               when Failure =>
-                  Parser.Tree.Lexer.Trace.Put_Line
-                    (Image (R, Descriptor) & " failed at pos " & Image_Pos 
(Tree, Tree.Shared_Stream, Last_Pos));
-               when No_Result =>
-                  raise SAL.Programmer_Error;
-               end case;
+            if Trace_Parse > Extra then
+               Trace.Put_Line ("apply memo:" & Image (Memo, R, Start_Pos, 
Tree));
+
+            elsif Trace_Parse > Detail and Memo.State = Success then
+               --  Match LR parse trace detail
+               Trace_Deriv_Success (Parser, Start_Pos, Memo);
             end if;
-            Parser.Derivs (R).Replace_Element (Tree.Get_Node_Index 
(Tree.Shared_Stream, Start_Pos), Memo);
+            Set_Deriv (Parser.Derivs, R, Tree.Get_Node_Index 
(Tree.Shared_Stream, Start_Pos), Memo);
             return Memo;
          end if;
       end case;
 
+      if Trace_Parse > Extra then
+         Trace.Put_Line ("apply recursive " & Image (R, Descriptor));
+      end if;
+
       loop
          --  Production is like: list : list element | element
          --
@@ -193,22 +318,22 @@ package body WisiToken.Parse.Packrat.Procedural is
             if Tree.Get_Node_Index (Tree.Shared_Stream, 
Result_Recurse.Last_Pos) >
               Tree.Get_Node_Index (Tree.Shared_Stream, Pos_Recurse_Last)
             then
-               Parser.Derivs (R).Replace_Element
-                 (Tree.Get_Node_Index (Tree.Shared_Stream, Start_Pos), 
Result_Recurse);
+               Set_Deriv (Parser.Derivs, R, Tree.Get_Node_Index 
(Tree.Shared_Stream, Start_Pos), Result_Recurse);
                Pos              := Result_Recurse.Last_Pos;
                Pos_Recurse_Last := Pos;
 
                if WisiToken.Trace_Parse > Detail then
-                  Parser.Tree.Lexer.Trace.Put_Line
-                    (Parser.Tree.Image
-                       (Result_Recurse.Result, Children => True, 
Terminal_Node_Numbers => True));
+                  Trace_Deriv_Success (Parser, Start_Pos, Result_Recurse);
+                  if Trace_Parse > Extra then
+                     Trace.Put_Line ("apply recursive continue");
+                  end if;
                end if;
                --  continue looping
 
             elsif Result_Recurse.Last_Pos = Pos_Recurse_Last then
                if Parser.Tree.Is_Empty_Nonterm (Result_Recurse.Result) then
-                  Parser.Derivs (R).Replace_Element
-                    (Tree.Get_Node_Index (Tree.Shared_Stream, Start_Pos), 
Result_Recurse);
+                  Set_Deriv
+                    (Parser.Derivs, R, Tree.Get_Node_Index 
(Tree.Shared_Stream, Start_Pos), Result_Recurse);
                end if;
                exit;
             else
@@ -219,7 +344,18 @@ package body WisiToken.Parse.Packrat.Procedural is
             exit;
          end if;
       end loop;
-      return Parser.Derivs (R)(Tree.Get_Node_Index (Tree.Shared_Stream, 
Start_Pos));
+
+      declare
+         Result : Memo_Entry renames Parser.Derivs (R)(Tree.Get_Node_Index 
(Tree.Shared_Stream, Start_Pos));
+      begin
+         Result.Max_Examined_Pos := Result_Recurse.Max_Examined_Pos;
+         if Trace_Parse > Extra then
+            Trace.Put_Line
+              ("apply recursive " & Image (R, Descriptor) & " end: " & Image 
(Result, R, Pos, Tree));
+         end if;
+
+         return Result;
+      end;
    end Apply_Rule;
 
    ----------
@@ -253,8 +389,7 @@ package body WisiToken.Parse.Packrat.Procedural is
       pragma Unreferenced (Log_File, Pre_Edited);
       use all type Ada.Containers.Count_Type;
       use all type WisiToken.Syntax_Trees.User_Data_Access;
-
-      Descriptor : WisiToken.Descriptor renames 
Parser.Tree.Lexer.Descriptor.all;
+      Trace      : WisiToken.Trace'Class renames Parser.Tree.Lexer.Trace.all;
 
       Result : Memo_Entry;
    begin
@@ -262,40 +397,25 @@ package body WisiToken.Parse.Packrat.Procedural is
          raise WisiToken.Parse_Error;
       end if;
 
+      if Trace_Time then
+         Trace.Put_Clock ("start");
+      end if;
+
       Parser.Tree.Clear;
       --  Creates Shared_Stream, but no parse stream; packrat does not
       --  use a parse stream.
 
+      Clear (Parser.Derivs);
+
       if Parser.User_Data /= null then
          Parser.User_Data.Reset;
       end if;
       Parser.Lex_All;
 
-      --  WORKAROUND: there appears to be a bug in GNAT Community 2021 that 
makes
-      --  ref_count fail in this usage. May be related to AdaCore ticket 
V107-045.
-      Parser.Tree.Enable_Ref_Count_Check (Parser.Tree.Shared_Stream, Enable => 
False);
-
-      for Nonterm in Descriptor.First_Nonterminal .. 
Descriptor.Last_Nonterminal loop
-         Parser.Derivs (Nonterm).Clear (Free_Memory => True);
-         Parser.Derivs (Nonterm).Set_First_Last
-           (Parser.Tree.Get_Node_Index
-              (Parser.Tree.Shared_Stream, Parser.Tree.Stream_First 
(Parser.Tree.Shared_Stream, Skip_SOI => True)),
-            Parser.Tree.Get_Node_Index
-              (Parser.Tree.Shared_Stream, Parser.Tree.Stream_Last 
(Parser.Tree.Shared_Stream, Skip_EOI => False)));
-      end loop;
-
       Result := Apply_Rule
         (Parser, Parser.Start_ID,  Parser.Tree.Stream_First 
(Parser.Tree.Shared_Stream, Skip_SOI => False));
 
-      if Result.State /= Success then
-         if Trace_Parse > Outline then
-            Parser.Tree.Lexer.Trace.Put_Line ("parse failed");
-         end if;
-
-         raise Syntax_Error with "parse failed"; --  FIXME packrat: need 
better error message!
-      else
-         Parser.Tree.Set_Root (Result.Result);
-      end if;
+      Parser.Finish_Parse (Result);
    end Parse;
 
 end WisiToken.Parse.Packrat.Procedural;
diff --git a/wisitoken-parse-packrat-procedural.ads 
b/wisitoken-parse-packrat-procedural.ads
index 9abc754ec5..aaf7f4beda 100644
--- a/wisitoken-parse-packrat-procedural.ads
+++ b/wisitoken-parse-packrat-procedural.ads
@@ -27,42 +27,12 @@ pragma License (Modified_GPL);
 with WisiToken.Productions;
 package WisiToken.Parse.Packrat.Procedural is
 
-   --  These types duplicate Packrat.Generated. We keep them separate so
-   --  we can experiment with ways of implementing indirect left
-   --  recursion.
-
-   type Memo_State is (No_Result, Failure, Success);
-   subtype Result_States is Memo_State range Failure .. Success;
-
-   type Memo_Entry (State : Memo_State := No_Result) is record
-      case State is
-      when No_Result =>
-         null;
-
-      when Failure =>
-         null;
-
-      when Success =>
-         Result   : Syntax_Trees.Node_Access;
-         Last_Pos : Syntax_Trees.Stream_Index;
-
-      end case;
-   end record;
-
-   subtype Positive_Node_Index is Syntax_Trees.Node_Index range 1 .. 
Syntax_Trees.Node_Index'Last;
-   package Memos is new SAL.Gen_Unbounded_Definite_Vectors
-     (Positive_Node_Index, Memo_Entry, Default_Element => (others => <>));
-   --  Memos is indexed by Node_Index of terminals in Shared_Stream
-   --  (incremental parse is not supported).
-
-   type Derivs is array (Token_ID range <>) of Memos.Vector;
-
-   type Parser (First_Nonterminal, Last_Nonterminal : Token_ID) is new 
Packrat.Parser
+   type Parser (First_Nonterminal, Last_Nonterminal : Token_ID) is new 
WisiToken.Parse.Packrat.Parser
+     (First_Nonterminal => First_Nonterminal,
+      Last_Nonterminal  => Last_Nonterminal)
    with record
-      Grammar               : WisiToken.Productions.Prod_Arrays.Vector;
-      Start_ID              : Token_ID;
-      Direct_Left_Recursive : Token_ID_Set (First_Nonterminal .. 
Last_Nonterminal);
-      Derivs                : Procedural.Derivs (First_Nonterminal .. 
Last_Nonterminal);
+      Grammar  : WisiToken.Productions.Prod_Arrays.Vector;
+      Start_ID : Token_ID;
    end record;
 
    function Create
diff --git a/wisitoken-parse-packrat.adb b/wisitoken-parse-packrat.adb
index b01bc0c881..982bab79ea 100644
--- a/wisitoken-parse-packrat.adb
+++ b/wisitoken-parse-packrat.adb
@@ -17,91 +17,163 @@
 
 pragma License (Modified_GPL);
 
-with Ada.Exceptions;
-with GNAT.Traceback.Symbolic;
 package body WisiToken.Parse.Packrat is
 
-   overriding
-   procedure Execute_Actions
-     (Parser              : in out Packrat.Parser;
-      Action_Region_Bytes : in     WisiToken.Buffer_Region := 
WisiToken.Null_Buffer_Region)
-   is
-      use all type WisiToken.Syntax_Trees.User_Data_Access;
-
-      procedure Process_Node
-        (Tree : in out Syntax_Trees.Tree;
-         Node : in     Syntax_Trees.Valid_Node_Access)
-      is
-         use all type Syntax_Trees.Node_Label;
-         use all type Syntax_Trees.Post_Parse_Action;
-         use all type WisiToken.Syntax_Trees.Node_Access;
-      begin
-         if Tree.Label (Node) /= Nonterm or else
-           not Overlaps (Tree.Byte_Region (Node, Trailing_Non_Grammar => 
False), Action_Region_Bytes)
-         then
-            return;
-         end if;
-
-         declare
-            Tree_Children     : constant Syntax_Trees.Node_Access_Array := 
Tree.Children (Node);
-            Post_Parse_Action : constant Syntax_Trees.Post_Parse_Action := 
Parser.Get_Post_Parse_Action
-              (Tree.Production_ID (Node));
-         begin
-            for Child of Tree_Children loop
-               if Child /= null and then Overlaps
-                 (Tree.Byte_Region (Child, Trailing_Non_Grammar => False), 
Action_Region_Bytes)
-               then
-                  Process_Node (Tree, Child);
-               end if;
-            end loop;
-
-            Parser.User_Data.Reduce (Tree, Node);
-
-            if Post_Parse_Action /= null then
-               Post_Parse_Action (Parser.User_Data.all, Tree, Node);
-            end if;
-         end;
-      end Process_Node;
+   function Image (Item : in Memo_Entry; Tree : in Syntax_Trees.Tree) return 
String
+   is begin
+      return
+        (case Item.State is
+         when No_Result => "",
+         when Failure => "fail @" & Image_Pos (Item.Max_Examined_Pos),
+         when Success => Tree.Image (Item.Result, Node_Numbers => True) &
+           " @" & Image_Pos (Item.Max_Examined_Pos) &
+           "," & Image_Pos (Item.Last_Pos));
+   end Image;
 
+   function Image
+     (Item      : in Memo_Entry;
+      Nonterm   : in Token_ID;
+      Pos       : in Syntax_Trees.Node_Index;
+      Tree      : in Syntax_Trees.Tree)
+     return String
+   is
+      Descriptor : WisiToken.Descriptor renames Tree.Lexer.Descriptor.all;
    begin
-      if Parser.User_Data = null then
-         return;
-      end if;
+      return
+        Syntax_Trees.Trimmed_Image (Pos) & ", " &
+        (case Item.State is
+         when No_Result => "",
+         when Failure => Image (Nonterm, Descriptor) & " fail @" &
+           Image_Pos (Item.Max_Examined_Pos),
+         when Success => Tree.Image (Item.Result, Node_Numbers => True, 
RHS_Index => True) &
+           "," & Image_Pos (Item.Max_Examined_Pos) &
+           "," & Image_Pos (Item.Last_Pos));
+   end Image;
 
-      if Trace_Action > Outline then
-         if Trace_Action > Extra then
-            Parser.Tree.Print_Tree (Parser.Tree.Root);
-            Parser.Tree.Lexer.Trace.New_Line;
-         end if;
-         Parser.Tree.Lexer.Trace.Put_Line ("root node: " & Parser.Tree.Image 
(Parser.Tree.Root));
-      end if;
+   function Image
+     (Item      : in Memo_Entry;
+      Nonterm   : in Token_ID;
+      RHS_Index : in Natural;
+      Pos       : in Syntax_Trees.Node_Index;
+      Tree      : in Syntax_Trees.Tree)
+     return String
+   is
+      Descriptor : WisiToken.Descriptor renames Tree.Lexer.Descriptor.all;
+   begin
+      return
+        Pos'Image & ", " &
+        (case Item.State is
+         when No_Result => "",
+         when Failure => Image (Production_ID'(Nonterm, RHS_Index), 
Descriptor) & " fail @" &
+           Image_Pos (Item.Max_Examined_Pos),
+         when Success => Tree.Image (Item.Result, Node_Numbers => True, 
RHS_Index => True) &
+           "," & Image_Pos (Item.Max_Examined_Pos) &
+           "," & Image_Pos (Item.Last_Pos));
+   end Image;
 
-      Parser.User_Data.Initialize_Actions (Parser.Tree);
-      Process_Node (Parser.Tree, Parser.Tree.Root);
-   exception
-   when E : others =>
-      if Debug_Mode then
-         Parser.Tree.Lexer.Trace.Put_Line
-           (Ada.Exceptions.Exception_Name (E) & ": " & 
Ada.Exceptions.Exception_Message (E));
-         Parser.Tree.Lexer.Trace.Put_Line 
(GNAT.Traceback.Symbolic.Symbolic_Traceback (E));
-         Parser.Tree.Lexer.Trace.New_Line;
-      end if;
-      raise;
-   end Execute_Actions;
+   function Image
+     (Item      : in Memo_Entry;
+      Nonterm   : in Token_ID;
+      Pos       : in Syntax_Trees.Stream_Index;
+      Tree      : in Syntax_Trees.Tree)
+     return String
+   is begin
+      return Image (Item, Nonterm, Tree.Get_Node_Index (Tree.Shared_Stream, 
Pos), Tree);
+   end Image;
 
-   function Image_Pos
-     (Tree    : in Syntax_Trees.Tree;
-      Stream  : in Syntax_Trees.Stream_ID;
-      Element : in Syntax_Trees.Stream_Index)
+   function Image
+     (Item      : in Memo_Entry;
+      Nonterm   : in Token_ID;
+      RHS_Index : in Natural;
+      Pos       : in Syntax_Trees.Stream_Index;
+      Tree      : in Syntax_Trees.Tree)
      return String
+   is begin
+      return Image (Item, Nonterm, RHS_Index, Tree.Get_Node_Index 
(Tree.Shared_Stream, Pos), Tree);
+   end Image;
+
+   function Image_Pos (Element : in Syntax_Trees.Stream_Index) return String
    is
       use Syntax_Trees;
    begin
       if Element = Invalid_Stream_Index then
          return "0";
       else
-         return Tree.Get_Node_Index (Stream, Element)'Image;
+         return Get_Node_Index (Element)'Image;
       end if;
    end Image_Pos;
 
+   procedure Clear (Derivs : in out Packrat.Derivs)
+   is begin
+      for D of Derivs loop
+         D.Clear (Free_Memory => True);
+      end loop;
+   end Clear;
+
+   function Get_Deriv
+     (Derivs  : in out Packrat.Derivs;
+      Nonterm : in     Token_ID;
+      Pos     : in     Positive_Node_Index)
+     return Memo_Entry
+   is begin
+      if Pos in Derivs (Nonterm).First_Index .. Derivs (Nonterm).Last_Index 
then
+         return Derivs (Nonterm)(Pos);
+      else
+         return No_Result_Memo;
+      end if;
+   end Get_Deriv;
+
+   procedure Set_Deriv
+     (Derivs  : in out Packrat.Derivs;
+      Nonterm : in     Token_ID;
+      Pos     : in     Positive_Node_Index;
+      Memo    : in     Memo_Entry)
+   is
+      use all type WisiToken.Syntax_Trees.Node_Index;
+   begin
+      if Pos < Derivs (Nonterm).First_Index then
+         Derivs (Nonterm).Set_First_Last (Pos, Derivs (Nonterm).Last_Index);
+
+      elsif Pos > Derivs (Nonterm).Last_Index then
+         Derivs (Nonterm).Set_First_Last (Derivs (Nonterm).First_Index, Pos);
+      end if;
+
+      Derivs (Nonterm).Replace_Element (Pos, Memo);
+   end Set_Deriv;
+
+   overriding procedure Finalize (Object : in out Parser)
+   is begin
+      Clear (Object.Derivs);
+   end Finalize;
+
+
+   procedure Finish_Parse
+     (Parser : in out Packrat.Parser'Class;
+      Result : in out Memo_Entry)
+   is
+      use WisiToken.Syntax_Trees;
+
+      Tree  : Syntax_Trees.Tree renames Parser.Tree;
+      Trace : WisiToken.Trace'Class renames Tree.Lexer.Trace.all;
+
+   begin
+      if Result.State = Packrat.Success then
+         Tree.Set_Root (Result.Result);
+         Result := No_Result_Memo;
+         Clear (Parser.Derivs);
+         Tree.Finish_Parse;
+
+         if Trace_Parse > Outline then
+            Trace.Put_Line ("packrat parse succeed");
+         end if;
+
+      else
+         if Trace_Parse > Outline then
+            Trace.Put_Line ("packrat parse fail @" & Image_Pos 
(Result.Max_Examined_Pos));
+         end if;
+         raise Syntax_Error with Tree.Error_Message
+           (Tree.To_Rooted_Ref (Tree.Shared_Stream, Result.Max_Examined_Pos), 
"packrat parse fail");
+      end if;
+   end Finish_Parse;
+
 end WisiToken.Parse.Packrat;
diff --git a/wisitoken-parse-packrat.ads b/wisitoken-parse-packrat.ads
index 0c59dc9746..59ec0fbaad 100644
--- a/wisitoken-parse-packrat.ads
+++ b/wisitoken-parse-packrat.ads
@@ -14,7 +14,7 @@
 --  [warth 2008]  Warth, A., Douglass, J.R. and Millstein, T.D., 2008. Packrat
 --                parsers can support left recursion. PEPM, 8, pp.103-110.
 --
---  Copyright (C) 2018, 2020 - 2021 Free Software Foundation, Inc.
+--  Copyright (C) 2018, 2020 - 2022 Free Software Foundation, Inc.
 --
 --  This library is free software;  you can redistribute it and/or modify it
 --  under terms of the  GNU General Public License  as published by the Free
@@ -47,19 +47,109 @@ pragma License (Modified_GPL);
 with WisiToken.Syntax_Trees;
 package WisiToken.Parse.Packrat is
 
-   type Parser is abstract new Base_Parser with null record;
+   type Memo_State is (No_Result, Failure, Success);
+   subtype Result_States is Memo_State range Failure .. Success;
 
-   overriding
-   procedure Execute_Actions
-     (Parser              : in out Packrat.Parser;
-      Action_Region_Bytes : in     WisiToken.Buffer_Region := 
WisiToken.Null_Buffer_Region);
+   type Memo_Entry (State : Memo_State := No_Result) is record
+      Max_Examined_Pos : Syntax_Trees.Stream_Index;
+      --  For error message.
 
-   function Image_Pos
-     (Tree    : in Syntax_Trees.Tree;
-      Stream  : in Syntax_Trees.Stream_ID;
-      Element : in Syntax_Trees.Stream_Index)
-     return String
-   with Pre => Tree.Contains (Stream, Element);
+      case State is
+      when No_Result =>
+         Recursive : Boolean := False;
+
+      when Failure =>
+         null;
+
+      when Success =>
+         Result   : Syntax_Trees.Node_Access;
+         Last_Pos : Syntax_Trees.Stream_Index; -- Last terminal in Result
+
+      end case;
+   end record;
+   subtype Success_Memo_Entry is Memo_Entry (Success);
+   subtype Result_Type is Memo_Entry with Dynamic_Predicate => 
Result_Type.State in Result_States;
+
+   No_Result_Memo : constant Memo_Entry := (No_Result, 
WisiToken.Syntax_Trees.Invalid_Stream_Index, False);
+
+   function Image_Pos (Element : in Syntax_Trees.Stream_Index) return String;
    --  "0" for Invalid_Stream_Index, Node_Index'Image otherwise.
 
+   function Image (Item : in Memo_Entry; Tree : in Syntax_Trees.Tree) return 
String;
+
+   function Image
+     (Item      : in Memo_Entry;
+      Nonterm   : in Token_ID;
+      Pos       : in Syntax_Trees.Node_Index;
+      Tree      : in Syntax_Trees.Tree)
+     return String;
+
+   function Image
+     (Item      : in Memo_Entry;
+      Nonterm   : in Token_ID;
+      RHS_Index : in Natural;
+      Pos       : in Syntax_Trees.Node_Index;
+      Tree      : in Syntax_Trees.Tree)
+     return String;
+
+   function Image
+     (Item      : in Memo_Entry;
+      Nonterm   : in Token_ID;
+      Pos       : in Syntax_Trees.Stream_Index;
+      Tree      : in Syntax_Trees.Tree)
+     return String;
+
+   function Image
+     (Item      : in Memo_Entry;
+      Nonterm   : in Token_ID;
+      RHS_Index : in Natural;
+      Pos       : in Syntax_Trees.Stream_Index;
+      Tree      : in Syntax_Trees.Tree)
+     return String;
+
+   subtype Positive_Node_Index is Syntax_Trees.Node_Index range 1 .. 
Syntax_Trees.Node_Index'Last;
+   package Memos is new SAL.Gen_Unbounded_Definite_Vectors
+     (Positive_Node_Index, Memo_Entry, Default_Element => (others => <>));
+   --  Memos is indexed by Node_Index of terminals in Shared_Stream
+   --  (incremental parse is not supported).
+
+   type Derivs is array (Token_ID range <>) of Memos.Vector;
+
+   procedure Clear (Derivs : in out Packrat.Derivs);
+   --  Free memory allocated by Derivs; set all to Empty_Vector.
+
+   function Get_Deriv
+     (Derivs  : in out Packrat.Derivs;
+      Nonterm : in     Token_ID;
+      Pos     : in     Positive_Node_Index)
+     return Memo_Entry;
+   --  Return Derivs (Nonterm)(Pos) if present; No_Result_Memo if not.
+
+   procedure Set_Deriv
+     (Derivs  : in out Packrat.Derivs;
+      Nonterm : in     Token_ID;
+      Pos     : in     Positive_Node_Index;
+      Memo    : in     Memo_Entry);
+   --  Add or replace Derivs (Nonterm)(Pos).
+
+   type Parser (First_Nonterminal, Last_Nonterminal : Token_ID) is abstract 
new WisiToken.Parse.Base_Parser with
+   record
+      Direct_Left_Recursive : Token_ID_Set (First_Nonterminal .. 
Last_Nonterminal);
+      Derivs                : Packrat.Derivs (First_Nonterminal .. 
Last_Nonterminal);
+   end record;
+
+   overriding procedure Finalize (Object : in out Parser);
+
+   procedure Finish_Parse
+     (Parser : in out Packrat.Parser'Class;
+      Result : in out Memo_Entry);
+   --  If a single parser succeeded, leaves Parser.Tree in
+   --  Fully_Parsed state.
+   --
+   --  If there were recovered errors, the error information is in
+   --  Parser.Tree.
+   --
+   --  If the parse did not succeed, raise Parse_Error with an error
+   --  message, and Parser.Parsers is left intact for error recover.
+
 end WisiToken.Parse.Packrat;
diff --git a/wisitoken-parse.adb b/wisitoken-parse.adb
index 9920d8577e..108df00749 100644
--- a/wisitoken-parse.adb
+++ b/wisitoken-parse.adb
@@ -17,6 +17,8 @@
 
 pragma License (Modified_GPL);
 
+with Ada.Exceptions;
+with GNAT.Traceback.Symbolic;
 with WisiToken.In_Parse_Actions;
 package body WisiToken.Parse is
 
@@ -85,12 +87,12 @@ package body WisiToken.Parse is
       when Insert =>
          String'Write (Stream, Item.Ins_ID'Image);
          --  Ignore Ins_Before.
-         String'Write (Stream, Syntax_Trees.Get_Node_Index 
(Item.Ins_Node)'Image);
+         String'Write (Stream, " " & Syntax_Trees.Get_Node_Index 
(Item.Ins_Node)'Image);
 
       when Delete =>
          String'Write (Stream, Item.Del_ID'Image);
          --  Ignore Del_Index.
-         String'Write (Stream, Syntax_Trees.Get_Node_Index 
(Item.Del_Node)'Image);
+         String'Write (Stream, " " & Syntax_Trees.Get_Node_Index 
(Item.Del_Node)'Image);
 
       end case;
       Character'Write (Stream, ')');
@@ -1177,4 +1179,102 @@ package body WisiToken.Parse is
       Put_Errors (Parser.Tree, Stream);
    end Put_Errors;
 
+   procedure Execute_Actions
+     (Tree                : in out Syntax_Trees.Tree;
+      Productions         : in     Syntax_Trees.Production_Info_Trees.Vector;
+      User_Data           : in     Syntax_Trees.User_Data_Access;
+      Action_Region_Bytes : in     WisiToken.Buffer_Region := 
WisiToken.Null_Buffer_Region)
+   is
+      use all type WisiToken.Syntax_Trees.Node_Access;
+      use all type Syntax_Trees.Post_Parse_Action;
+      use all type Syntax_Trees.User_Data_Access;
+
+      procedure Process_Node
+        (Tree : in out Syntax_Trees.Tree;
+         Node : in     Syntax_Trees.Valid_Node_Access)
+      is
+         use all type Syntax_Trees.Node_Label;
+         Node_Byte_Region : constant Buffer_Region := Tree.Byte_Region
+           (Node, Trailing_Non_Grammar => True);
+      begin
+         if Tree.Label (Node) /= Nonterm or else
+           not (Node_Byte_Region = Null_Buffer_Region or
+                  Action_Region_Bytes = Null_Buffer_Region or
+                  Overlaps (Node_Byte_Region, Action_Region_Bytes))
+         then
+            return;
+         end if;
+
+         for Child of Tree.Children (Node) loop
+            if Child /= Syntax_Trees.Invalid_Node_Access then
+               --  Child can be null in an edited tree
+               Process_Node (Tree, Child);
+            end if;
+         end loop;
+
+         User_Data.Reduce (Tree, Node);
+         declare
+            Post_Parse_Action : constant Syntax_Trees.Post_Parse_Action := 
Get_Post_Parse_Action
+              (Productions, Tree.Production_ID (Node));
+         begin
+            if Post_Parse_Action /= null then
+               begin
+                  Post_Parse_Action (User_Data.all, Tree, Node);
+               exception
+               when E : others =>
+                  if Trace_Tests > Outline then
+                     --  running a unit test; exception may be AUnit assert 
fail
+                     raise;
+
+                  elsif WisiToken.Debug_Mode then
+                     Tree.Lexer.Trace.Put_Line
+                       (Ada.Exceptions.Exception_Name (E) & ": " & 
Ada.Exceptions.Exception_Message (E));
+                     Tree.Lexer.Trace.Put_Line 
(GNAT.Traceback.Symbolic.Symbolic_Traceback (E));
+                     Tree.Lexer.Trace.New_Line;
+                  end if;
+
+                  raise WisiToken.Parse_Error with Tree.Error_Message
+                    (Node,
+                     "action raised exception " & 
Ada.Exceptions.Exception_Name (E) & ": " &
+                       Ada.Exceptions.Exception_Message (E));
+               end;
+            end if;
+         end;
+      end Process_Node;
+
+   begin
+      if User_Data = null then
+         return;
+      end if;
+
+      if Tree.Root = Syntax_Trees.Invalid_Node_Access then
+         --  No code in file, and error recovery failed to insert valid code.
+         --  Or ambiguous parse; Finish_Parse not called.
+         return;
+      end if;
+
+      User_Data.Initialize_Actions (Tree);
+
+      Process_Node (Tree, Tree.Root);
+   exception
+   when WisiToken.Parse_Error =>
+      raise;
+
+   when E : others =>
+      if Debug_Mode then
+         Tree.Lexer.Trace.Put_Line
+           (Ada.Exceptions.Exception_Name (E) & ": " & 
Ada.Exceptions.Exception_Message (E));
+         Tree.Lexer.Trace.Put_Line (GNAT.Traceback.Symbolic.Symbolic_Traceback 
(E));
+         Tree.Lexer.Trace.New_Line;
+      end if;
+      raise;
+   end Execute_Actions;
+
+   procedure Execute_Actions
+     (Parser              : in out WisiToken.Parse.Base_Parser'Class;
+      Action_Region_Bytes : in     WisiToken.Buffer_Region := 
WisiToken.Null_Buffer_Region)
+   is begin
+      Execute_Actions (Parser.Tree, Parser.Productions, Parser.User_Data, 
Action_Region_Bytes);
+   end Execute_Actions;
+
 end WisiToken.Parse;
diff --git a/wisitoken-parse.ads b/wisitoken-parse.ads
index fdf482f031..95094c6dfe 100644
--- a/wisitoken-parse.ads
+++ b/wisitoken-parse.ads
@@ -498,9 +498,16 @@ package WisiToken.Parse is
       Tree        : aliased Syntax_Trees.Tree;
       Productions : Syntax_Trees.Production_Info_Trees.Vector;
       User_Data   : Syntax_Trees.User_Data_Access;
+
+      Partial_Parse_Active    : access Boolean;
+      Partial_Parse_Byte_Goal : access WisiToken.Buffer_Pos;
+      --  Used by In_Parse_Actions to terminate Partial_Parse.
    end record;
    --  Common to all parsers. Finalize should free any allocated objects.
 
+   type Base_Parser_Access is access all Base_Parser'Class;
+   type Factory is access function return Base_Parser_Access;
+
    function Source_File_Name (Item : in Base_Parser'Class) return String
    is (Item.Tree.Lexer.File_Name);
 
@@ -616,9 +623,16 @@ package WisiToken.Parse is
    --  Output Parser.Tree.Stream errors to Tree.Lexer.Trace.
 
    procedure Execute_Actions
-     (Parser              : in out Base_Parser;
-      Action_Region_Bytes : in     WisiToken.Buffer_Region := 
WisiToken.Null_Buffer_Region)
-   is abstract;
+     (Tree                : in out Syntax_Trees.Tree;
+      Productions         : in     Syntax_Trees.Production_Info_Trees.Vector;
+      User_Data           : in     Syntax_Trees.User_Data_Access;
+      Action_Region_Bytes : in     WisiToken.Buffer_Region := 
WisiToken.Null_Buffer_Region);
+   --  Implements Execute_Actions, allows specifying different tree
+   --  (needed by wisitoken-bnf-generate).
+
+   procedure Execute_Actions
+     (Parser              : in out Base_Parser'Class;
+      Action_Region_Bytes : in     WisiToken.Buffer_Region := 
WisiToken.Null_Buffer_Region);
    --  Execute all actions in Parser.Tree nodes that overlap
    --  Action_Region_Bytes; all nodes if Action_Region_Bytes =
    --  Null_Buffer_Region. See wisitoken-syntax_trees.ads for other
diff --git a/wisitoken-parse_table-mode.el b/wisitoken-parse_table-mode.el
index 5a3c712ada..0891b39efa 100644
--- a/wisitoken-parse_table-mode.el
+++ b/wisitoken-parse_table-mode.el
@@ -25,6 +25,7 @@
 ;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 (require 'xref)
+(require 'wisi-prj)                     ;For `wisi-goto-source'.
 
 (defvar wisitoken-parse_table-last-buffer nil
   "Last buffer in which a wisitoken-parse_table operation was performed")
diff --git a/wisitoken-productions.ads b/wisitoken-productions.ads
index b134a50bab..f3412b209a 100644
--- a/wisitoken-productions.ads
+++ b/wisitoken-productions.ads
@@ -37,8 +37,8 @@ package WisiToken.Productions is
       --  Recursion for each token. There may be more than one recursion cycle 
for any token,
       --  but we don't track that.
 
-      Post_Parse_Action : Syntax_Trees.Post_Parse_Action;
-      In_Parse_Action   : Syntax_Trees.In_Parse_Actions.In_Parse_Action;
+      Post_Parse_Action : Syntax_Trees.Post_Parse_Action := null;
+      In_Parse_Action   : Syntax_Trees.In_Parse_Actions.In_Parse_Action := 
null;
    end record
    with Dynamic_Predicate =>
      (Tokens.Length = 0 or Tokens.First_Index = 1) and
diff --git a/wisitoken-syntax_trees.adb b/wisitoken-syntax_trees.adb
index cb90dff031..4a1e3760b1 100644
--- a/wisitoken-syntax_trees.adb
+++ b/wisitoken-syntax_trees.adb
@@ -109,7 +109,8 @@ package body WisiToken.Syntax_Trees is
    procedure Last_Source_Terminal
      (Tree                 : in     Syntax_Trees.Tree;
       Ref                  : in out Stream_Node_Parents;
-      Trailing_Non_Grammar : in     Boolean)
+      Trailing_Non_Grammar : in     Boolean;
+      Parse_Stream         : in     Stream_ID)
    with Pre => Rooted (Ref.Ref) and Ref.Parents.Depth = 0;
    --  Update Ref to last source terminal in Ref.Node, initialize Ref.Parents.
 
@@ -146,12 +147,6 @@ package body WisiToken.Syntax_Trees is
       Ref                  : in out Stream_Node_Parents;
       Trailing_Non_Grammar : in     Boolean);
 
-   function Prev_Source_Terminal
-     (Tree                 : in Syntax_Trees.Tree;
-      Node                 : in Node_Access;
-      Trailing_Non_Grammar : in Boolean)
-     return Node_Access;
-
    procedure Prev_Terminal
      (Tree    : in     Syntax_Trees.Tree;
       Node    : in out Node_Access;
@@ -1331,7 +1326,7 @@ package body WisiToken.Syntax_Trees is
          Prev_Source_Terminal := Ref;
          Tree.First_Source_Terminal (Prev_Source_Terminal, 
Trailing_Non_Grammar);
          Next_Source_Terminal := Ref;
-         Tree.Last_Source_Terminal (Next_Source_Terminal, 
Trailing_Non_Grammar);
+         Tree.Last_Source_Terminal (Next_Source_Terminal, 
Trailing_Non_Grammar, Parse_Stream);
 
          if Prev_Source_Terminal.Ref.Node = Invalid_Node_Access then
             Tree.Prev_Source_Terminal (Prev_Source_Terminal, Parse_Stream, 
Trailing_Non_Grammar);
@@ -1631,6 +1626,21 @@ package body WisiToken.Syntax_Trees is
       return Node.Children;
    end Children;
 
+   function Children_Recover_Tokens
+     (Tree : in Syntax_Trees.Tree;
+      Node : in Valid_Node_Access)
+     return Recover_Token_Array
+   is begin
+      --  WORKAROUND: GNAT Community 2020 doesn't support 'of' here, and it
+      --  hangs if there are any errors in the statement with 'in'.
+      --  return (for I in Node.Children'Range => Tree.Get_Recover_Token 
(Node.Children (I)));
+      return Result : Recover_Token_Array (1 .. Node.Child_Count) do
+         for I in Node.Children'Range loop
+            Result (I) := Tree.Get_Recover_Token (Node.Children (I));
+         end loop;
+      end return;
+   end Children_Recover_Tokens;
+
    function Children_Recover_Tokens
      (Tree    : in Syntax_Trees.Tree;
       Stream  : in Stream_ID;
@@ -1715,130 +1725,36 @@ package body WisiToken.Syntax_Trees is
       Node.Parent := Invalid_Node_Access;
    end Clear_Parent;
 
-   procedure Clear_Parse_Streams
-     (Tree       : in out Syntax_Trees.Tree;
-      Keep_Nodes : in     Valid_Node_Access_Lists.List := 
Valid_Node_Access_Lists.Empty_List)
-   is begin
-      if Tree.Root = Invalid_Node_Access then
-         Tree.Root := Syntax_Trees.Root (Tree);
-      end if;
-
-      --  Add SOI, EOI (from the parse stream, to include any
-      --  Following_Deleted and Error_Data) to Root children, so
-      --  Prev/Next_Non_Grammar can find them.
-      declare
-         Parse_Stream : Syntax_Trees.Parse_Stream renames Tree.Streams 
(Tree.Streams.Last);
-         SOI : constant Valid_Node_Access := Stream_Element_Lists.Element 
(Parse_Stream.Elements.First).Node;
-
-         Last_Node : constant Valid_Node_Access := 
Stream_Element_Lists.Element (Parse_Stream.Elements.Last).Node;
-
-         EOI : constant Valid_Node_Access :=
-           (if Tree.ID (Last_Node) = Tree.Lexer.Descriptor.EOI_ID
-            then Last_Node
-            else Tree.EOI);
-
-         New_Children : Node_Access_Array (1 .. Tree.Root.Child_Count + 2);
-      begin
-         if Tree.Streams.Last = Tree.Shared_Stream.Cur and 
Tree.Root.Child_Count = 3 then
-            --  This is a packrat parse; SOI, EOI already in tree
-            pragma Assert (Tree.Root.Children (1) = Tree.SOI and 
Tree.Root.Children (3) = EOI);
-         else
-            --  There is a parse stream, or this is an incremental parse where 
the
-            --  edit did not require a parse.
-            New_Children (1) := SOI;
-            New_Children (2 .. New_Children'Last - 1) := Tree.Root.Children;
-            New_Children (New_Children'Last) := EOI;
-
-            Tree.SOI := SOI;
-            Tree.EOI := EOI;
+   procedure Clear_Parse_Streams (Tree : in out Syntax_Trees.Tree)
+   is
+      use Parse_Stream_Lists;
+      Cur : Cursor := Tree.Streams.First;
+   begin
+      pragma Assert (Cur = Tree.Shared_Stream.Cur);
+      Next (Cur); --  first parse stream
 
-            Tree.Root.Children := (others => Invalid_Node_Access);
+      loop
+         exit when Cur = No_Element;
 
-            Tree.Root := new Node'
-              (Label       => Nonterm,
-               Copied_Node => Invalid_Node_Access,
-               Child_Count => Tree.Root.Child_Count + 2,
-               ID          => Tree.Root.ID,
-               Node_Index  => Tree.Root.Node_Index,
-               Parent      => null,
-               Augmented   => Tree.Root.Augmented,
-               Error_List  =>
-                 (if Tree.Root.Error_List = null
-                  then null
-                  else new Error_Data_Lists.List'(Tree.Root.Error_List.all)),
-               Virtual          => Tree.Root.Virtual,
-               Recover_Conflict => False,
-               RHS_Index        => Tree.Root.RHS_Index,
-               Name_Offset      => Tree.Root.Name_Offset,
-               Name_Length      => Tree.Root.Name_Length,
-               Children         => New_Children);
+         declare
+            Stream : Parse_Stream renames Tree.Streams (Cur);
+            To_Delete : Cursor := Cur;
+         begin
+            --  Clear saved element list cursors in parse streams before 
freeing
+            --  the element lists, so they don't try to decrement reference 
counts
+            --  in deallocated elements.
+            Stream.Stack_Top   := Stream_Element_Lists.No_Element;
+            Stream.Shared_Link := Stream_Element_Lists.No_Element;
 
-            for Child of New_Children loop
-               Child.Parent := Tree.Root;
-            end loop;
+            Stream.Elements.Finalize;
 
-            Tree.Nodes.Append (Tree.Root);
-         end if;
-      end;
+            Next (Cur);
+            Tree.Streams.Delete (To_Delete);
+         end;
 
-      --  Clear saved element list cursors in parse streams before freeing
-      --  the element lists, so they don't try to decrement reference counts
-      --  in deallocated elements. We can't rely on cursor Finalize for
-      --  this; that's done in arbitrary order.
-      for Stream of Tree.Streams loop
-         Stream.Stack_Top   := Stream_Element_Lists.No_Element;
-         Stream.Shared_Link := Stream_Element_Lists.No_Element;
       end loop;
 
-      Tree.Streams.Clear;
       Tree.Next_Stream_Label := Shared_Stream_Label + 1;
-
-      Tree.Shared_Stream.Cur := Parse_Stream_Lists.No_Element;
-
-      if not Tree.Parents_Set then
-         Set_Parents (Tree);
-      end if;
-
-      for Node of Tree.Nodes loop
-         --  Only nodes that have parents are part of the final parse result.
-         --  In an incremental parse, breakdown removes nodes from a parse
-         --  stream, and clears any parent pointers involved.
-         if Node.Parent = null and then
-           Node /= Tree.Root and then
-           Node /= Tree.SOI and then
-           Node /= Tree.EOI and then
-           not (for some N of Keep_Nodes => N = Node)
-         then
-            --  It is tempting to try to enforce that all deleted nonterms have
-            --  Children = (others => Invalid_Node_Access) here. However, that 
is
-            --  not true when Breakdown is called by the main parser;
-            --  Tree.Parents_Set is false, indicating there might be multiple
-            --  streams, so Breakdown does not clear children.
-            Free (Node);
-         end if;
-      end loop;
-
-      --  Compact Tree.Nodes
-      declare
-         Free : Node_Index := Tree.Nodes.First_Index - 1;
-      begin
-         for I in Tree.Nodes.First_Index .. Tree.Nodes.Last_Index loop
-            if Free < Tree.Nodes.First_Index then
-               if Tree.Nodes (I) = Invalid_Node_Access then
-                  Free := I;
-               end if;
-            else
-               if Tree.Nodes (I) /= Invalid_Node_Access then
-                  Tree.Nodes (Free) := Tree.Nodes (I);
-                  Free := @ + 1;
-               end if;
-            end if;
-         end loop;
-
-         if Free > Tree.Nodes.First_Index then
-            Tree.Nodes.Set_First_Last (First => Tree.Nodes.First_Index, Last 
=> Free - 1);
-         end if;
-      end;
    end Clear_Parse_Streams;
 
    function Column (Tree : in Syntax_Trees.Tree; Node : in Valid_Node_Access) 
return Ada.Text_IO.Count
@@ -3068,14 +2984,17 @@ package body WisiToken.Syntax_Trees is
       Non_Grammar : Node_Access := Invalid_Node_Access;
       Null_Non_Grammar : WisiToken.Lexer.Token_Arrays.Vector;
    begin
-      begin
-         --  Tolerate broken trees where Prev_Non_Grammar doesn't find SOI, or
-         --  raises an exception.
-         Non_Grammar := Tree.Prev_Non_Grammar (Node);
-      exception
-      when others =>
-         null;
-      end;
+      if Tree.Parents_Set then
+         begin
+            --  Tolerate broken trees where Prev_Non_Grammar doesn't find SOI, 
or
+            --  raises an exception.
+            Non_Grammar := Tree.Prev_Non_Grammar (Node);
+         exception
+         when others =>
+            null;
+         end;
+      end if;
+
       return Error_Message_1
         (Tree,
          (if Non_Grammar = Invalid_Node_Access then Null_Non_Grammar else 
Non_Grammar.Non_Grammar),
@@ -3853,6 +3772,65 @@ package body WisiToken.Syntax_Trees is
       end if;
    end Find_Sibling;
 
+   procedure Finish_Parse (Tree : in out Syntax_Trees.Tree)
+   is begin
+      --  Clear saved element list cursors in parse streams before freeing
+      --  the element lists, so they don't try to decrement reference counts
+      --  in deallocated elements. We can't rely on cursor Finalize for
+      --  this; that's done in arbitrary order.
+      for Stream of Tree.Streams loop
+         Stream.Stack_Top   := Stream_Element_Lists.No_Element;
+         Stream.Shared_Link := Stream_Element_Lists.No_Element;
+      end loop;
+
+      Tree.Shared_Stream.Cur := Parse_Stream_Lists.No_Element;
+
+      Tree.Streams.Clear;
+      Tree.Next_Stream_Label := Shared_Stream_Label + 1;
+
+      if not Tree.Parents_Set then
+         Set_Parents (Tree);
+      end if;
+
+      for Node of Tree.Nodes loop
+         --  Only nodes that have parents are part of the final parse result.
+         --  In an incremental parse, breakdown removes nodes from a parse
+         --  stream, and clears any parent pointers involved.
+         if Node.Parent = null and then
+           Node /= Tree.Root
+         then
+            --  It is tempting to try to enforce that all deleted nonterms have
+            --  Children = (others => Invalid_Node_Access) here. However, that 
is
+            --  not true when Breakdown is called by the main parser;
+            --  Tree.Parents_Set is false, indicating there might be multiple
+            --  streams, so Breakdown does not clear children.
+            Free (Node);
+         end if;
+      end loop;
+
+      --  Compact Tree.Nodes
+      declare
+         Free : Node_Index := Tree.Nodes.First_Index - 1;
+      begin
+         for I in Tree.Nodes.First_Index .. Tree.Nodes.Last_Index loop
+            if Free < Tree.Nodes.First_Index then
+               if Tree.Nodes (I) = Invalid_Node_Access then
+                  Free := I;
+               end if;
+            else
+               if Tree.Nodes (I) /= Invalid_Node_Access then
+                  Tree.Nodes (Free) := Tree.Nodes (I);
+                  Free := @ + 1;
+               end if;
+            end if;
+         end loop;
+
+         if Free > Tree.Nodes.First_Index then
+            Tree.Nodes.Set_First_Last (First => Tree.Nodes.First_Index, Last 
=> Free - 1);
+         end if;
+      end;
+   end Finish_Parse;
+
    overriding function First (Object : Error_Iterator) return Error_Ref
    is begin
       return First_Error (Object.Tree.all);
@@ -3959,16 +3937,17 @@ package body WisiToken.Syntax_Trees is
 
    function First_Error (Tree : in Syntax_Trees.Tree; Stream : in Stream_ID) 
return Stream_Error_Ref
    is begin
-      return Result : Stream_Error_Ref :=
-        (Ref     => Tree.To_Stream_Node_Parents
-           (Tree.To_Rooted_Ref (Stream, Tree.Stream_First (Stream, Skip_SOI => 
True))),
-         Deleted => Valid_Node_Access_Lists.No_Element,
-         Error   => Error_Data_Lists.No_Element)
+      return Result : Stream_Error_Ref := Invalid_Stream_Error_Ref
       do
-         if Result.Ref.Ref.Node.Label = Source_Terminal then
-            Result.Deleted := Result.Ref.Ref.Node.Following_Deleted.First;
+         if Tree.Streams (Stream.Cur).Elements.Length > 1 then
+            Result.Ref := Tree.To_Stream_Node_Parents
+              (Tree.To_Rooted_Ref (Stream, Tree.Stream_First (Stream, Skip_SOI 
=> True)));
+
+            if Result.Ref.Ref.Node.Label = Source_Terminal then
+               Result.Deleted := Result.Ref.Ref.Node.Following_Deleted.First;
+            end if;
+            First_Error (Tree, Result);
          end if;
-         First_Error (Tree, Result);
       end return;
    end First_Error;
 
@@ -4077,8 +4056,7 @@ package body WisiToken.Syntax_Trees is
    is begin
       Ref.Ref.Node := First_Terminal (Tree, Ref.Ref.Node, Ref.Parents);
       loop
-         exit when Ref.Ref.Node = Invalid_Node_Access;
-         exit when
+         exit when Ref.Ref.Node /= Invalid_Node_Access and then
            (if Trailing_Non_Grammar
             then (case Terminal_Label'(Ref.Ref.Node.Label) is
                   when Source_Terminal => True,
@@ -4086,7 +4064,7 @@ package body WisiToken.Syntax_Trees is
                   when Virtual_Identifier => Ref.Ref.Node.Non_Grammar.Length > 
0)
             else Ref.Ref.Node.Label = Source_Terminal);
 
-         Next_Terminal (Tree, Ref.Ref.Node, Ref.Parents);
+         Next_Terminal (Tree, Ref, Following => True);
       end loop;
    end First_Source_Terminal;
 
@@ -4340,7 +4318,7 @@ package body WisiToken.Syntax_Trees is
 
    function Fully_Parsed (Tree : in Syntax_Trees.Tree) return Boolean
    is begin
-      return Tree.Streams.Length = 2 and then Tree.Stream_Length ((Cur => 
Tree.Streams.Last)) in 2 .. 3;
+      return Tree.Root /= Invalid_Node_Access;
    end Fully_Parsed;
 
    procedure Get_IDs
@@ -4670,6 +4648,11 @@ package body WisiToken.Syntax_Trees is
                begin
                   case Terminal_Label'(Label) is
                   when Source_Terminal =>
+                     if Node_Index = 0 and ID /= Tree.Lexer.Descriptor.SOI_ID 
then
+                        raise WisiToken.User_Error with "source_terminal 
node_index 0 has id" & ID'Image &
+                          " /= SOI; probably wrong language.";
+                     end if;
+
                      pragma Assert
                        (Child_Count = 0 and
                           (Node_Index > 0 or else ID = 
Tree.Lexer.Descriptor.SOI_ID));
@@ -4964,41 +4947,18 @@ package body WisiToken.Syntax_Trees is
       return Child.Parent /= Invalid_Node_Access;
    end Has_Parent;
 
-   function ID
-     (Tree : in Syntax_Trees.Tree;
-      Node : in Valid_Node_Access)
-     return Token_ID
+   function ID (Tree : in Syntax_Trees.Tree; Node : in Valid_Node_Access) 
return Token_ID
    is
       pragma Unreferenced (Tree);
    begin
       return Node.ID;
    end ID;
 
-   function ID
-     (Tree    : in Syntax_Trees.Tree;
-      Stream  : in Stream_ID;
-      Element : in Stream_Index)
-     return Token_ID
-   is
-      pragma Unreferenced (Tree, Stream);
-   begin
-      return Stream_Element_Lists.Element (Element.Cur).Node.ID;
-   end ID;
-
-   function ID
-     (Tree : in Syntax_Trees.Tree;
-      Ref  : in Stream_Node_Ref)
-     return WisiToken.Token_ID
+   function ID (Tree : in Syntax_Trees.Tree; Element : in Stream_Index) return 
Token_ID
    is
       pragma Unreferenced (Tree);
    begin
-      if Ref.Node /= Invalid_Node_Access then
-         return Ref.Node.ID;
-      elsif Ref.Element /= Invalid_Stream_Index then
-         return Stream_Element_Lists.Element (Ref.Element.Cur).Node.ID;
-      else
-         return Invalid_Token_ID;
-      end if;
+      return Stream_Element_Lists.Element (Element.Cur).Node.ID;
    end ID;
 
    function Identifier (Tree : in Syntax_Trees.Tree; Node : in 
Valid_Node_Access) return Base_Identifier_Index
@@ -5775,12 +5735,12 @@ package body WisiToken.Syntax_Trees is
    procedure Last_Source_Terminal
      (Tree                 : in     Syntax_Trees.Tree;
       Ref                  : in out Stream_Node_Parents;
-      Trailing_Non_Grammar : in     Boolean)
+      Trailing_Non_Grammar : in     Boolean;
+      Parse_Stream         : in     Stream_ID)
    is begin
       Ref.Ref.Node := Last_Terminal (Tree, Ref.Ref.Node, Ref.Parents);
       loop
-         exit when Ref.Ref.Node = Invalid_Node_Access;
-         exit when
+         exit when Ref.Ref.Node /= Invalid_Node_Access and then
            (if Trailing_Non_Grammar
             then (case Terminal_Label'(Ref.Ref.Node.Label) is
                   when Source_Terminal => True,
@@ -5788,7 +5748,7 @@ package body WisiToken.Syntax_Trees is
                   when Virtual_Identifier => Ref.Ref.Node.Non_Grammar.Length > 
0)
             else Ref.Ref.Node.Label = Source_Terminal);
 
-         Prev_Terminal (Tree, Ref.Ref.Node, Ref.Parents);
+         Prev_Terminal (Tree, Ref, Parse_Stream, Preceding => True);
       end loop;
    end Last_Source_Terminal;
 
@@ -5966,7 +5926,13 @@ package body WisiToken.Syntax_Trees is
                   end if;
                end;
                Parse_Stream.Elements.Delete (To_Delete);
-               To_Delete := Cur;
+
+               if Element (Cur).Node.Label = Nonterm then
+                  To_Delete := Cur;
+               else
+                  --  ada_mode-interactive_04.adb
+                  To_Delete := No_Element;
+               end if;
             end if;
          end if;
 
@@ -5988,7 +5954,9 @@ package body WisiToken.Syntax_Trees is
          end;
 
          if Node.Label in Terminal_Label then
-            if To_Delete /= Cur and Next_I /= First_Child then
+            if To_Delete = No_Element or else
+              (To_Delete /= Cur and Next_I /= First_Child)
+            then
                Ref.Element.Cur := Cur;
 
             else
@@ -6003,16 +5971,18 @@ package body WisiToken.Syntax_Trees is
 
             Ref.Node := Node;
 
-            declare
-               Node : constant Valid_Node_Access := 
Stream_Element_Lists.Element (To_Delete).Node;
-            begin
-               if Node.Error_List /= null then
-                  for Err of Tree.Error_List (Node) loop
-                     New_Errors.Append (To_Message (Err, Tree, Node));
-                  end loop;
-               end if;
-            end;
-            Parse_Stream.Elements.Delete (To_Delete);
+            if To_Delete /= No_Element then
+               declare
+                  Node : constant Valid_Node_Access := 
Stream_Element_Lists.Element (To_Delete).Node;
+               begin
+                  if Node.Error_List /= null then
+                     for Err of Tree.Error_List (Node) loop
+                        New_Errors.Append (To_Message (Err, Tree, Node));
+                     end loop;
+                  end if;
+               end;
+               Parse_Stream.Elements.Delete (To_Delete);
+            end if;
             exit;
          end if;
       end loop;
@@ -6178,6 +6148,95 @@ package body WisiToken.Syntax_Trees is
       return Line_At_Byte_Pos (Tree.Root, Start_Line => Tree.SOI.Non_Grammar 
(1).Line_Region.First);
    end Line_At_Byte_Pos;
 
+   function Line_At_Node
+     (Tree   : in Syntax_Trees.Tree;
+      Stream : in Stream_ID;
+      Ref    : in Real_Recover_Token)
+     return Base_Line_Number_Type
+   is
+      function Find_Element return Stream_Index
+      is
+         use Stream_Element_Lists;
+         Parse_Stream : Syntax_Trees.Parse_Stream renames Tree.Streams 
(Stream.Cur);
+         Cur : Cursor := Parse_Stream.Stack_Top;
+      begin
+         loop
+            exit when not Has_Element (Cur);
+            if Stream_Element_Lists.Element (Cur).Node = Ref.Element_Node then
+               return (Cur => Cur);
+            end if;
+            Next (Cur);
+         end loop;
+
+         --  Not found in stream input; search stack.
+         Cur := Parse_Stream.Stack_Top;
+         loop
+            Previous (Cur);
+            exit when not Has_Element (Cur);
+            if Stream_Element_Lists.Element (Cur).Node = Ref.Element_Node then
+               return (Cur => Cur);
+            end if;
+         end loop;
+         return Invalid_Stream_Index;
+      end Find_Element;
+
+      Element : constant Stream_Index := Find_Element;
+   begin
+      if Element = Invalid_Stream_Index then
+         --  Ref.Node is a child of some stream Element; too hard to find.
+         --  test_incremental.adb Lexer_Errors_05.
+         return Invalid_Line_Number;
+      else
+         return Line_At_Node (Tree, Tree.To_Stream_Node_Parents 
(Tree.To_Rooted_Ref (Stream, Element)), Stream);
+      end if;
+   end Line_At_Node;
+
+   function Line_At_Node
+     (Tree : in Syntax_Trees.Tree;
+      Node : in Valid_Node_Access)
+     return Line_Number_Type
+   is
+      Temp           : Valid_Node_Access   := Node;
+      New_Line_Count : Base_Line_Number_Type := 0;
+   begin
+      loop
+         Temp := Tree.Prev_Terminal (Temp);
+         exit when Temp.Non_Grammar.Length > 0;
+         if Temp.Label = Source_Terminal then
+            New_Line_Count := @ + Temp.New_Line_Count;
+         end if;
+      end loop;
+      return Temp.Non_Grammar (Temp.Non_Grammar.Last_Index).Line_Region.Last + 
New_Line_Count;
+   end Line_At_Node;
+
+   function Line_At_Node
+     (Tree         : in Syntax_Trees.Tree;
+      Ref          : in Stream_Node_Parents;
+      Parse_Stream : in Stream_ID)
+     return Line_Number_Type
+   is
+      Temp           : Stream_Node_Parents   := Ref;
+      New_Line_Count : Base_Line_Number_Type := 0;
+   begin
+      loop
+         Tree.Prev_Terminal (Temp, Parse_Stream, Preceding => True);
+         exit when Temp.Ref.Node.Non_Grammar.Length > 0;
+         if Temp.Ref.Node.Label = Source_Terminal then
+            New_Line_Count := @ + Temp.Ref.Node.New_Line_Count;
+         end if;
+      end loop;
+      return Temp.Ref.Node.Non_Grammar 
(Temp.Ref.Node.Non_Grammar.Last_Index).Line_Region.Last + New_Line_Count;
+   end Line_At_Node;
+
+   function Line_At_Node
+     (Tree         : in Syntax_Trees.Tree;
+      Ref          : in Stream_Node_Ref;
+      Parse_Stream : in Stream_ID)
+     return Line_Number_Type
+   is begin
+      return Tree.Line_At_Node (Tree.To_Stream_Node_Parents (Ref), 
Parse_Stream);
+   end Line_At_Node;
+
    function Line_Begin_Char_Pos
      (Tree : in Syntax_Trees.Tree;
       Line : in Line_Number_Type)
@@ -6326,14 +6385,15 @@ package body WisiToken.Syntax_Trees is
       end if;
    end Line_Begin_Token;
 
-   procedure  Line_Region_Internal_1
-     (Tree                    : in     Syntax_Trees.Tree;
-      Node                    : in     Node_Access;
-      Prev_Non_Grammar        : in     Valid_Node_Access;
-      Next_Non_Grammar        : in     Valid_Node_Access;
-      Trailing_Non_Grammar    : in     Boolean;
-      First_Non_Grammar_Token :    out WisiToken.Lexer.Token;
-      Last_Non_Grammar_Token  :    out WisiToken.Lexer.Token)
+   procedure Line_Region_Internal_1
+     (Tree                                 : in     Syntax_Trees.Tree;
+      Node                                 : in     Node_Access;
+      Prev_Non_Grammar                     : in     Valid_Node_Access;
+      Next_Non_Grammar                     : in     Valid_Node_Access;
+      Trailing_Non_Grammar                 : in     Boolean;
+      First_Non_Grammar_Token              :    out WisiToken.Lexer.Token;
+      Last_Non_Grammar_Token               :    out WisiToken.Lexer.Token;
+      Last_Non_Grammar_Is_Node_Non_Grammar :    out Boolean)
    is
       --  Since all non_grammar have line_region, we don't have to look for
       --  a new_line, just any non_grammar.
@@ -6374,6 +6434,8 @@ package body WisiToken.Syntax_Trees is
             --  want to include the leading non_grammar in SOI.
             Prev_Non_Grammar.Non_Grammar 
(Prev_Non_Grammar.Non_Grammar.Last_Index));
 
+      Last_Non_Grammar_Is_Node_Non_Grammar := Actual_Last_Non_Grammar = 
Last_Terminal;
+
       Last_Non_Grammar_Token := Actual_Last_Non_Grammar.Non_Grammar
         (if Trailing_Non_Grammar and Actual_Last_Non_Grammar = Last_Non_Grammar
          then Actual_Last_Non_Grammar.Non_Grammar.Last_Index
@@ -6388,16 +6450,20 @@ package body WisiToken.Syntax_Trees is
       Trailing_Non_Grammar : in Boolean)
      return WisiToken.Line_Region
    is
-      First_Non_Grammar_Token : WisiToken.Lexer.Token;
-      Last_Non_Grammar_Token  : WisiToken.Lexer.Token;
+      First_Non_Grammar_Token              : WisiToken.Lexer.Token;
+      Last_Non_Grammar_Token               : WisiToken.Lexer.Token;
+      Last_Non_Grammar_Is_Node_Non_Grammar : Boolean;
    begin
       Line_Region_Internal_1
         (Tree, Node, Prev_Non_Grammar, Next_Non_Grammar, Trailing_Non_Grammar,
-         First_Non_Grammar_Token, Last_Non_Grammar_Token);
+         First_Non_Grammar_Token, Last_Non_Grammar_Token, 
Last_Non_Grammar_Is_Node_Non_Grammar);
 
       return
         (First => First_Non_Grammar_Token.Line_Region.Last,
-         Last => Last_Non_Grammar_Token.Line_Region.First);
+         Last =>
+           (if Trailing_Non_Grammar and Last_Non_Grammar_Is_Node_Non_Grammar
+            then Last_Non_Grammar_Token.Line_Region.Last
+            else Last_Non_Grammar_Token.Line_Region.First));
    end Line_Region_Internal;
 
    function Byte_Region_Of_Line_Region_Internal
@@ -6408,16 +6474,20 @@ package body WisiToken.Syntax_Trees is
       Trailing_Non_Grammar : in     Boolean)
      return WisiToken.Buffer_Region
    is
-      First_Non_Grammar_Token : WisiToken.Lexer.Token;
-      Last_Non_Grammar_Token  : WisiToken.Lexer.Token;
+      First_Non_Grammar_Token              : WisiToken.Lexer.Token;
+      Last_Non_Grammar_Token               : WisiToken.Lexer.Token;
+      Last_Non_Grammar_Is_Node_Non_Grammar : Boolean;
    begin
       Line_Region_Internal_1
         (Tree, Node, Prev_Non_Grammar, Next_Non_Grammar, Trailing_Non_Grammar,
-         First_Non_Grammar_Token, Last_Non_Grammar_Token);
+         First_Non_Grammar_Token, Last_Non_Grammar_Token, 
Last_Non_Grammar_Is_Node_Non_Grammar);
 
       return
         (First => First_Non_Grammar_Token.Byte_Region.Last,
-         Last => Last_Non_Grammar_Token.Byte_Region.First);
+         Last =>
+           (if Last_Non_Grammar_Is_Node_Non_Grammar
+            then Last_Non_Grammar_Token.Byte_Region.Last
+            else Last_Non_Grammar_Token.Byte_Region.First));
    end Byte_Region_Of_Line_Region_Internal;
 
    function Line_Region (Tree : in Syntax_Trees.Tree) return 
WisiToken.Line_Region
@@ -6454,20 +6524,7 @@ package body WisiToken.Syntax_Trees is
       Trailing_Non_Grammar : in Boolean)
      return WisiToken.Line_Region
    is begin
-      if Tree.Parents_Set then
-         declare
-            Prev_Non_Grammar : Stream_Node_Ref := Ref;
-            Next_Non_Grammar : Stream_Node_Ref := Ref;
-         begin
-            Tree.Prev_Non_Grammar (Prev_Non_Grammar);
-            Tree.Next_Non_Grammar (Next_Non_Grammar);
-            return Line_Region_Internal
-              (Tree, Ref.Node, Prev_Non_Grammar.Node, Next_Non_Grammar.Node, 
Trailing_Non_Grammar);
-         end;
-
-      else
-         return Line_Region (Tree, To_Stream_Node_Parents (Tree, Ref), 
Ref.Stream, Trailing_Non_Grammar);
-      end if;
+      return Line_Region (Tree, To_Stream_Node_Parents (Tree, Ref), 
Ref.Stream, Trailing_Non_Grammar);
    end Line_Region;
 
    function Byte_Region_Of_Line_Region
@@ -7843,7 +7900,7 @@ package body WisiToken.Syntax_Trees is
 
    function Prev_Source_Terminal
      (Tree                 : in Syntax_Trees.Tree;
-      Node                 : in Node_Access;
+      Node                 : in Valid_Node_Access;
       Trailing_Non_Grammar : in Boolean)
      return Node_Access
    is begin
@@ -8175,9 +8232,10 @@ package body WisiToken.Syntax_Trees is
          for I in 1 .. Level loop
             Tree.Lexer.Trace.Put ("| ", Prefix => False);
          end loop;
-         Tree.Lexer.Trace.Put (Image (Tree, Node, Children => False, RHS_Index 
=> True, Node_Numbers => True,
-                           Line_Numbers => Line_Numbers, Non_Grammar => 
Non_Grammar),
-                    Prefix => False);
+         Tree.Lexer.Trace.Put
+           (Image (Tree, Node, Children => False, RHS_Index => True, 
Node_Numbers => True,
+                   Line_Numbers => Line_Numbers, Non_Grammar => Non_Grammar),
+            Prefix => False);
 
          if Node.Augmented /= null then
             Tree.Lexer.Trace.Put (Image_Augmented (Node.Augmented.all), Prefix 
=> False);
@@ -8436,9 +8494,7 @@ package body WisiToken.Syntax_Trees is
 
          --  We don't output Node.Parent; redundant with node.Children.
 
-         if Node.Augmented /= null then
-            raise SAL.Not_Implemented with "put_tree augmented";
-         end if;
+         --  FIXME: implement augmented
 
          Put_Error_List (Node.Error_List);
 
@@ -8582,29 +8638,7 @@ package body WisiToken.Syntax_Trees is
 
    function Root (Tree : in Syntax_Trees.Tree) return Node_Access
    is begin
-      if Tree.Root = Invalid_Node_Access then
-         if Tree.Streams.Length = 0 then
-            return Invalid_Node_Access;
-         else
-            declare
-               use Stream_Element_Lists;
-               Stream : Parse_Stream renames Tree.Streams (Tree.Streams.Last);
-               --  parse stream from Parse or shared_stream from Edit_Tree 
with no changes
-
-               Cur : Cursor := Stream.Elements.First; -- SOI
-            begin
-               if Has_Element (Cur) then
-                  Cur := Next (Cur); -- wisitoken_accept
-                  if Has_Element (Cur) then
-                     return Element (Cur).Node;
-                  end if;
-               end if;
-               return Invalid_Node_Access;
-            end;
-         end if;
-      else
-         return Tree.Root;
-      end if;
+      return Tree.Root;
    end Root;
 
    function Rooted (Ref : in Stream_Node_Ref) return Boolean
@@ -8831,26 +8865,43 @@ package body WisiToken.Syntax_Trees is
          Tree.Root := New_Root;
       else
          declare
+            Parse_Stream : Syntax_Trees.Parse_Stream renames Tree.Streams 
(Tree.Streams.Last);
+            --  Parse_Stream is Shared_Stream if this is a packrat parse.
+
+            SOI : constant Valid_Node_Access := Stream_Element_Lists.Element 
(Parse_Stream.Elements.First).Node;
+
+            Last_Node : constant Valid_Node_Access := 
Stream_Element_Lists.Element (Parse_Stream.Elements.Last).Node;
+
+            EOI : constant Node_Access :=
+              (if Last_Node.ID = Tree.Lexer.Descriptor.EOI_ID
+               then Last_Node
+               elsif Last_Node.Children (Last_Node.Child_Count).ID = 
Tree.Lexer.Descriptor.EOI_ID
+               then Last_Node.Children (Last_Node.Child_Count)
+               else Tree.EOI);
+
             function Create_New_Children return Node_Access_Array
             is
                Last : Positive_Index_Type := New_Root.Children'Last;
                New_Children : Node_Access_Array (1 .. New_Root.Children'Last + 
2);
             begin
-               if New_Root.Children (1) /= Tree.SOI then
-                  New_Children (1) := Tree.SOI;
+               if New_Root.Children (1).ID /= Tree.Lexer.Descriptor.SOI_ID then
+                  New_Children (1) := SOI;
                   Last := 1 + New_Root.Children'Length;
                   New_Children (2 .. Last) := New_Root.Children;
                end if;
 
-               if New_Root.Children (New_Root.Children'Last) /= Tree.EOI then
+               if New_Root.Children (New_Root.Children'Last).ID /= 
Tree.Lexer.Descriptor.EOI_ID then
                   Last := @ + 1;
-                  New_Children (Last) := Tree.EOI;
+                  New_Children (Last) := EOI;
                end if;
                return New_Children (1 .. Last);
             end Create_New_Children;
 
             New_Children : constant Node_Access_Array := Create_New_Children;
          begin
+            Tree.SOI := SOI;
+            Tree.EOI := EOI;
+
             Tree.Root := new Node'
               (Label       => Nonterm,
                Copied_Node => Invalid_Node_Access,
@@ -9029,7 +9080,7 @@ package body WisiToken.Syntax_Trees is
 
       Tree.SOI.Parent := Invalid_Node_Access;
 
-      --  Delete SOI, EOI from root children (added in Clear_Parse_Streams)
+      --  Delete SOI, EOI from root children (added in Finish_Parse)
       declare
          New_Children : Node_Access_Array (1 .. Tree.Root.Child_Count - 2);
       begin
@@ -9081,6 +9132,8 @@ package body WisiToken.Syntax_Trees is
       Begin_Char_Pos : Buffer_Pos;
       Begin_Line     : Line_Number_Type;
    begin
+      Tree.Lexer.Errors.Clear;
+
       Tree.Lexer.Begin_Pos (Begin_Byte_Pos, Begin_Char_Pos, Begin_Line);
       declare
          Token : constant Lexer.Token :=
@@ -9156,9 +9209,9 @@ package body WisiToken.Syntax_Trees is
       return Stream_Element_Lists.Element (Tree.Streams 
(Stream.Cur).Stack_Top).State;
    end State;
 
-   function Stream_Count (Tree : in Syntax_Trees.Tree) return Natural
+   function Stream_Count (Tree : in Syntax_Trees.Tree) return 
SAL.Base_Peek_Type
    is begin
-      return Natural (Tree.Streams.Length);
+      return SAL.Base_Peek_Type (Tree.Streams.Length);
    end Stream_Count;
 
    procedure Stream_Delete
@@ -9693,6 +9746,14 @@ package body WisiToken.Syntax_Trees is
               Tree.Is_Descendant_Of (Root => Tree.Get_Node (Ref.Stream, 
Ref.Element), Descendant => Ref.Node)));
    end Valid_Stream_Node;
 
+   function Valid_Stream_Node_Parents
+     (Tree : in Syntax_Trees.Tree;
+      Ref  : in Stream_Node_Parents)
+     return Boolean
+   is begin
+      return Valid_Stream_Node (Tree, Ref.Ref) and Parents_Valid (Ref);
+   end Valid_Stream_Node_Parents;
+
    procedure Validate_Tree
      (Tree              : in out Syntax_Trees.Tree;
       User_Data         : in out User_Data_Type'Class;
@@ -9705,7 +9766,9 @@ package body WisiToken.Syntax_Trees is
 
       Real_Root : Node_Access;
 
-      Last_Source_Terminal_Pos : Base_Buffer_Pos := Buffer_Pos'First;
+      Last_Source_Terminal_Pos : Base_Buffer_Pos  := Buffer_Pos'First;
+      Last_Line                : Base_Line_Number_Type :=
+        Tree.SOI.Non_Grammar (1).Line_Region.First;
 
       procedure Process_Node
         (Tree : in out Syntax_Trees.Tree;
@@ -9773,15 +9836,25 @@ package body WisiToken.Syntax_Trees is
             end if;
             case Terminal_Label'(Node.Label) is
             when Source_Terminal =>
-               if Byte_Region_Order and then Node.Byte_Region.First < 
Last_Source_Terminal_Pos then
-                  Put_Error ("byte_region out of order");
-               end if;
-               if Node.Non_Grammar.Length > 0 then
-                  Last_Source_Terminal_Pos := Node.Non_Grammar 
(Node.Non_Grammar.Last_Index).Byte_Region.Last;
-               else
-                  Last_Source_Terminal_Pos := Node.Byte_Region.Last;
+               if Byte_Region_Order then
+                  if Node.Byte_Region.First < Last_Source_Terminal_Pos then
+                     Put_Error ("byte_region out of order");
+                  end if;
+                  Last_Line := @ + Node.New_Line_Count;
+                  if Node.Non_Grammar.Length > 0 then
+                     Last_Source_Terminal_Pos := Node.Non_Grammar 
(Node.Non_Grammar.Last_Index).Byte_Region.Last;
+                     if Tree.Lexer.Descriptor.New_Line_ID /= Invalid_Token_ID 
then
+                        for Token of Node.Non_Grammar loop
+                           if Token.Line_Region.First /= Last_Line then
+                              Put_Error ("line_number missing/out of order");
+                           end if;
+                           Last_Line := Token.Line_Region.Last;
+                        end loop;
+                     end if;
+                  else
+                     Last_Source_Terminal_Pos := Node.Byte_Region.Last;
+                  end if;
                end if;
-
                for Deleted of Node.Following_Deleted loop
                   if Deleted.Parent /= Node then
                      Put_Error ("deleted.parent wrong");
@@ -9811,7 +9884,18 @@ package body WisiToken.Syntax_Trees is
 
             when Virtual_Terminal | Virtual_Identifier =>
                if Node.Non_Grammar.Length > 0 then
-                  Last_Source_Terminal_Pos := Node.Non_Grammar 
(Node.Non_Grammar.Last_Index).Byte_Region.Last;
+                  if Byte_Region_Order then
+                     Last_Source_Terminal_Pos := Node.Non_Grammar 
(Node.Non_Grammar.Last_Index).Byte_Region.Last;
+
+                     if Tree.Lexer.Descriptor.New_Line_ID /= Invalid_Token_ID 
then
+                        for Token of Node.Non_Grammar loop
+                           if Token.Line_Region.First /= Last_Line then
+                              Put_Error ("line_number missing/out of order");
+                           end if;
+                           Last_Line := Token.Line_Region.Last;
+                        end loop;
+                     end if;
+                  end if;
                end if;
             end case;
 
diff --git a/wisitoken-syntax_trees.ads b/wisitoken-syntax_trees.ads
index 8e89007b24..796af1ad60 100644
--- a/wisitoken-syntax_trees.ads
+++ b/wisitoken-syntax_trees.ads
@@ -110,6 +110,7 @@ with SAL.Gen_Unbounded_Sparse_Ordered_Sets;
 with SAL.Generic_Decimal_Image;
 with WisiToken.Lexer;
 package WisiToken.Syntax_Trees is
+   use all type Ada.Containers.Count_Type;
    use all type SAL.Base_Peek_Type;
 
    type Node (<>) is private;
@@ -404,7 +405,8 @@ package WisiToken.Syntax_Trees is
      (Tree    : in Syntax_Trees.Tree;
       Stream  : in Stream_ID;
       Element : in Stream_Index)
-     return Rooted_Ref;
+     return Rooted_Ref
+   with Pre => Element /= Invalid_Stream_Index;
 
    type Stream_Node_Parents is record
       Ref     : Stream_Node_Ref;
@@ -422,6 +424,11 @@ package WisiToken.Syntax_Trees is
    function Parents_Valid (Ref : in Stream_Node_Parents) return Boolean;
    --  True if Parents gives the path from Element.Node to Node, or Element or 
Node is invalid.
 
+   function Valid_Stream_Node_Parents
+     (Tree : in Syntax_Trees.Tree;
+      Ref  : in Stream_Node_Parents)
+     return Boolean;
+
    function To_Stream_Node_Parents (Tree : in Syntax_Trees.Tree; Ref : in 
Stream_Node_Ref) return Stream_Node_Parents
    with Pre => Ref = Invalid_Stream_Node_Ref or else Tree.Parents_Set or else
                (Rooted (Ref) or Ref.Node = Tree.First_Terminal (Get_Node 
(Ref.Element))),
@@ -558,10 +565,6 @@ package WisiToken.Syntax_Trees is
    type User_Data_Access is access all User_Data_Type'Class;
    type User_Data_Access_Constant is access constant User_Data_Type'Class;
 
-   function New_User_Data (Template : in User_Data_Type) return 
User_Data_Access
-   is (null);
-   --  Return a new empty object with the same type as Template.
-
    procedure Reset (User_Data : in out User_Data_Type) is null;
    --  Reset to start a new parse.
 
@@ -733,8 +736,8 @@ package WisiToken.Syntax_Trees is
      Post => Tree.Is_Valid (New_Stream'Result);
    --  Create a new parse stream, initially copied from Old_Stream.
 
-   function Stream_Count (Tree : in Syntax_Trees.Tree) return Natural;
-   --  Number of active streams.
+   function Stream_Count (Tree : in Syntax_Trees.Tree) return 
SAL.Base_Peek_Type;
+   --  Number of parse streams plus the shared stream.
 
    function First_Parse_Stream (Tree : in Syntax_Trees.Tree) return Stream_ID
    with Pre => Tree.Stream_Count >= 2;
@@ -893,7 +896,7 @@ package WisiToken.Syntax_Trees is
       Productions    : in     Production_Info_Trees.Vector;
       User_Data      : in     Syntax_Trees.User_Data_Access_Constant;
       First_Terminal : in     Boolean)
-   with Pre => Valid_Stream_Node (Tree, Ref.Ref) and Parents_Valid (Ref) and
+   with Pre => Tree.Valid_Stream_Node_Parents (Ref) and
                Tree.Label (Ref.Ref.Element) = Nonterm and
                (if First_Terminal
                 then not Tree.Is_Empty_Nonterm (Ref.Ref.Node)
@@ -1045,6 +1048,7 @@ package WisiToken.Syntax_Trees is
    with Pre => Element = Invalid_Stream_Index or else
                (Tree.Contains (Stream, Element) or Tree.Contains 
(Tree.Shared_Stream, Element));
    --  If Element is Invalid_Stream_Index, result is Stream_First (= SOI).
+   --  Does not follow Stream.Shared_Link
 
    function Stream_Next
      (Tree : in Syntax_Trees.Tree;
@@ -1111,7 +1115,7 @@ package WisiToken.Syntax_Trees is
      (Tree   : in     Syntax_Trees.Tree;
       Ref    : in out Stream_Node_Parents;
       Rooted : in     Boolean)
-   with Pre => Valid_Stream_Node (Tree, Ref.Ref),
+   with Pre => Valid_Stream_Node_Parents (Tree, Ref),
      Post => Correct_Stream_Node (Tree, Ref.Ref) and
              (Ref.Ref = Invalid_Stream_Node_Ref or else
                 (if Rooted
@@ -1242,17 +1246,6 @@ package WisiToken.Syntax_Trees is
    --  Delete Element from Stream. If Element = Stream.Stack_Top,
    --  Stack_Top is set to Invalid_Stream_Index.
 
-   function ID
-     (Tree    : in Syntax_Trees.Tree;
-      Stream  : in Stream_ID;
-      Element : in Stream_Index)
-     return Token_ID
-   with Pre => Tree.Contains (Stream, Element) or Tree.Contains 
(Tree.Shared_Stream, Element);
-   --  The precondition allows either stream; Current_Token is
-   --  either a Source_Terminal from Shared_Stream or a Virtual_Terminal
-   --  in Stream input from error recovery; in incremental parse, it
-   --  could be a Source_Terminal in Stream input from push_back.
-
    function Label (Tree : in Syntax_Trees.Tree; Node : in Valid_Node_Access) 
return Node_Label;
    function Label (Tree : in Syntax_Trees.Tree; Element : in Stream_Index) 
return Node_Label
    with Pre => Element /= Invalid_Stream_Index;
@@ -1316,16 +1309,8 @@ package WisiToken.Syntax_Trees is
       Region : in Buffer_Region)
    with Pre => Tree.Is_Nonterm (Node);
 
-   function ID
-     (Tree : in Syntax_Trees.Tree;
-      Node : in Valid_Node_Access)
-     return WisiToken.Token_ID;
-
-   function ID
-     (Tree : in Syntax_Trees.Tree;
-      Ref  : in Stream_Node_Ref)
-     return WisiToken.Token_ID;
-   --  One of Ref.Node.ID, Ref.Element.Node.ID, Invalid_Token_ID
+   function ID (Tree : in Syntax_Trees.Tree; Node : in Valid_Node_Access) 
return WisiToken.Token_ID;
+   function ID (Tree : in Syntax_Trees.Tree; Element : in Stream_Index) return 
Token_ID;
 
    function Production_ID
      (Tree : in Syntax_Trees.Tree;
@@ -1372,7 +1357,7 @@ package WisiToken.Syntax_Trees is
       Parse_Stream         : in Stream_ID;
       Trailing_Non_Grammar : in Boolean := False)
      return WisiToken.Buffer_Region
-   with Pre => Valid_Stream_Node (Tree, Ref.Ref) and Parents_Valid (Ref);
+   with Pre => Tree.Valid_Stream_Node_Parents (Ref);
    --  Same as Byte_Region (Stream_Node_Ref), for use when parents are
    --  not set. See Prev_Terminal (tree, stream_node_parents) for meaning
    --  of Parse_Stream.
@@ -1414,11 +1399,11 @@ package WisiToken.Syntax_Trees is
    with Pre => Tree.Editable;
    --  Lines of tokens in Node. First is the line started by the first
    --  New_Line or SOI (start of input) before the first terminal in
-   --  Node. If Trailing_Non_Grammar, Last is the line ended by the last
-   --  New_Line in the first non_grammar array after the last terminal of
-   --  Node, or EOI (end of input); if not Trailing_Non_Grammar, Last is
-   --  the line ended by the first New_Line or EOI after the last
-   --  terminal of Node.
+   --  Node. If Trailing_Non_Grammar and the last terminal of Node has
+   --  Non_Grammar, Last is the line ended by the last New_Line of
+   --  Last_Terminal (Node).Non_Grammar; if not Trailing_Non_Grammar or
+   --  Node does not have Non_Grammar, Last is the line ended by the
+   --  first New_Line or EOI after the last terminal of Node.
    --
    --  Trailing_Non_Grammar => False is used to get the line_region of a
    --  multi-line token.
@@ -1450,7 +1435,7 @@ package WisiToken.Syntax_Trees is
       Parse_Stream         : in Stream_ID;
       Trailing_Non_Grammar : in Boolean := True)
      return WisiToken.Line_Region
-   with Pre => Tree.Valid_Stream_Node (Ref.Ref) and Parents_Valid (Ref);
+   with Pre => Tree.Valid_Stream_Node_Parents (Ref);
    --  Same as Line_Region (Stream_Node_Ref), for use when parents are
    --  not set. See Prev_Terminal (tree, stream_node_parents) for meaning
    --  of Parse_Stream.
@@ -1494,6 +1479,12 @@ package WisiToken.Syntax_Trees is
      return Recover_Token;
    --  Treat Node as a stream element.
 
+   function Children_Recover_Tokens
+     (Tree : in Syntax_Trees.Tree;
+      Node : in Valid_Node_Access)
+     return Recover_Token_Array
+   with Pre => Tree.Label (Node) = Nonterm;
+
    function Children_Recover_Tokens
      (Tree    : in Syntax_Trees.Tree;
       Stream  : in Stream_ID;
@@ -1564,15 +1555,15 @@ package WisiToken.Syntax_Trees is
       Node : in Valid_Node_Access;
       ID   : in Token_ID)
      return Node_Access;
-   --  Return the descendant of Node (may be Node) whose ID is ID, or
-   --  Invalid_Node_Access if none match.
+   --  Return the descendant of Node (may be Node; depth first search)
+   --  whose ID is ID, or Invalid_Node_Access if none match.
 
    function Find_Descendant
      (Tree      : in     Syntax_Trees.Tree;
       Node      : in     Valid_Node_Access;
       Predicate : access function (Tree : in Syntax_Trees.Tree; Node : in 
Valid_Node_Access) return Boolean)
      return Node_Access;
-   --  Return the first descendant of Node (may be Node; breadth first
+   --  Return the first descendant of Node (may be Node; depth first
    --  search) for which Predicate returns True, or Invalid_Node_Access
    --  if none do.
 
@@ -1620,7 +1611,7 @@ package WisiToken.Syntax_Trees is
      (Tree         : in     Syntax_Trees.Tree;
       Ref          : in out Stream_Node_Parents;
       Parse_Stream : in     Stream_ID)
-   with Pre => Tree.Valid_Stream_Node (Ref.Ref) and Parents_Valid (Ref),
+   with Pre => Tree.Valid_Stream_Node_Parents (Ref),
      Post => Tree.Correct_Stream_Node (Ref.Ref) and Parents_Valid (Ref);
 
    function First_Non_Grammar
@@ -1650,7 +1641,7 @@ package WisiToken.Syntax_Trees is
    procedure Next_Non_Grammar
      (Tree : in     Syntax_Trees.Tree;
       Ref  : in out Stream_Node_Parents)
-   with Pre => Valid_Stream_Node (Tree, Ref.Ref) and Parents_Valid (Ref),
+   with Pre => Tree.Valid_Stream_Node_Parents (Ref),
      Post => Tree.Correct_Stream_Node (Ref.Ref) and Parents_Valid (Ref);
 
    type New_Line_Ref is record
@@ -1670,7 +1661,7 @@ package WisiToken.Syntax_Trees is
       --  new_line is the last; it was found by Prev_New_Line;
 
       Pos : Base_Buffer_Pos := Invalid_Buffer_Pos;
-      --  The buffer position of the new_line.
+      --  The byte position of the new_line.
 
       Line : Base_Line_Number_Type := Invalid_Line_Number;
       --  The line number after the new_line.
@@ -1694,13 +1685,48 @@ package WisiToken.Syntax_Trees is
    --  giving a line number, computes Start_Line, and continues as
    --  above.
 
+   function Line_At_Node
+     (Tree   : in Syntax_Trees.Tree;
+      Stream : in Stream_ID;
+      Ref    : in Real_Recover_Token)
+     return Base_Line_Number_Type;
+   --  Return line at first byte of Ref.Node; Invalid_Line_Number if too hard 
to find.
+
+   function Line_At_Node
+     (Tree : in Syntax_Trees.Tree;
+      Node : in Valid_Node_Access)
+     return Line_Number_Type
+   with Pre => Tree.Parents_Set;
+   --  Return line at first byte of Node.
+
+   function Line_At_Node
+     (Tree         : in Syntax_Trees.Tree;
+      Ref          : in Stream_Node_Ref;
+      Parse_Stream : in Stream_ID)
+     return Line_Number_Type
+   with Pre => Valid_Stream_Node (Tree, Ref);
+   --  Return line at first byte of Ref.Node.
+
+   function Line_At_Node
+     (Tree         : in Syntax_Trees.Tree;
+      Ref          : in Stream_Node_Parents;
+      Parse_Stream : in Stream_ID)
+     return Line_Number_Type
+   with Pre => Valid_Stream_Node_Parents (Tree, Ref);
+   --  Return line at first byte of Ref.Node.
+
    function First_Source_Terminal
      (Tree                 : in Syntax_Trees.Tree;
       Node                 : in Valid_Node_Access;
       Trailing_Non_Grammar : in Boolean;
       Following            : in Boolean)
      return Node_Access
-   with Pre => (if Following then Tree.Parents_Set else True);
+   with Pre => (if Following then Tree.Parents_Set else True),
+    Post =>
+       (if Following
+        then First_Source_Terminal'Result /= Invalid_Node_Access and then
+         (Tree.Label (First_Source_Terminal'Result) = Source_Terminal or
+            Tree.Non_Grammar_Const (First_Source_Terminal'Result).Length > 0));
    --  Return a terminal node that can give byte or char pos.
    --
    --  If Trailing_Non_Grammar, return first terminal in Node that is a
@@ -1738,6 +1764,13 @@ package WisiToken.Syntax_Trees is
    --  non_grammar. If not Trailing_Non_Grammar, only return a
    --  Source_Terminal.
 
+   function Prev_Source_Terminal
+     (Tree                 : in Syntax_Trees.Tree;
+      Node                 : in Valid_Node_Access;
+      Trailing_Non_Grammar : in Boolean)
+     return Node_Access
+   with Pre => Tree.Parents_Set;
+
    function Prev_Source_Terminal
      (Tree                 : in Syntax_Trees.Tree;
       Ref                  : in Stream_Node_Ref;
@@ -1757,7 +1790,7 @@ package WisiToken.Syntax_Trees is
       Ref                  : in out Stream_Node_Parents;
       Parse_Stream         : in     Stream_ID;
       Trailing_Non_Grammar : in     Boolean)
-   with Pre => Valid_Stream_Node (Tree, Ref.Ref) and not Tree.Parents_Set,
+   with Pre => Valid_Stream_Node_Parents (Tree, Ref),
      Post   => Tree.Correct_Stream_Node (Ref.Ref);
 
    function Count_Terminals (Tree : in Syntax_Trees.Tree; Node : in 
Valid_Node_Access) return Natural;
@@ -1777,16 +1810,8 @@ package WisiToken.Syntax_Trees is
       Node    : in     Valid_Node_Access;
       Parents : in out Node_Stacks.Stack)
      return Node_Access;
-   --  Same as First_Terminal (Tree, Node), also initializes Parents to
-   --  store path from Node to the first terminal, for Next_Terminal in
-   --  nodes that have unset parent links, or to limit Next_Terminal to
-   --  descendants of Node.
-   --
-   --  We don't have "Pre => Parents.Is_Empty" or "Post => Parents_Valid
-   --  (Parents, First_Terminal'Result)", because we call this function
-   --  recursively to create Parents.
-   --
-   --  Visible for use with error recovery Configuration input stream.
+   --  Same as First_Terminal (Tree, Node), also updates Parents to
+   --  store path from Node to the first terminal.
 
    procedure First_Terminal
      (Tree : in     Syntax_Trees.Tree;
@@ -1821,7 +1846,7 @@ package WisiToken.Syntax_Trees is
      (Tree      : in     Syntax_Trees.Tree;
       Ref       : in out Stream_Node_Parents;
       Following : in     Boolean)
-   with Pre => Valid_Stream_Node (Tree, Ref.Ref) and Parents_Valid (Ref),
+   with Pre => Tree.Valid_Stream_Node_Parents (Ref),
      Post => Parents_Valid (Ref);
    --  Update Ref to first terminal in Ref.Ref.Node or, if Following, a
    --  following stream element - continues search in Shared_Stream.
@@ -1857,7 +1882,7 @@ package WisiToken.Syntax_Trees is
       Ref          : in out Stream_Node_Parents;
       Parse_Stream : in     Stream_ID;
       Preceding    : in     Boolean)
-   with Pre => Valid_Stream_Node (Tree, Ref.Ref),
+   with Pre => Valid_Stream_Node_Parents (Tree, Ref),
      Post => Parents_Valid (Ref);
    --  Update Ref to last terminal of Ref.Ref.Element.Node or, if
    --  Preceding, preceding element.
@@ -1992,8 +2017,8 @@ package WisiToken.Syntax_Trees is
      (Tree      : in     Syntax_Trees.Tree;
       Ref       : in out Syntax_Trees.Stream_Node_Parents;
       Following : in     Boolean)
-   with Pre => Valid_Stream_Node (Tree, Ref.Ref) and Parents_Valid (Ref),
-     Post => Correct_Stream_Node (Tree, Ref.Ref) and Parents_Valid (Ref);
+   with Pre => Tree.Valid_Stream_Node_Parents (Ref),
+     Post => Tree.Correct_Stream_Node (Ref.Ref) and Parents_Valid (Ref);
    --  Return first terminal with valid Sequential_Index in Ref.Node or,
    --  if Following, a following stream element; continues search in
    --  Tree.Shared_Stream. Invalid_Stream_Node_Parents if none found.
@@ -2035,7 +2060,7 @@ package WisiToken.Syntax_Trees is
       Ref          : in out Syntax_Trees.Stream_Node_Parents;
       Parse_Stream : in     Stream_ID;
       Preceding    : in     Boolean)
-   with Pre => Valid_Stream_Node (Tree, Ref.Ref) and Parents_Valid (Ref),
+   with Pre => Tree.Valid_Stream_Node_Parents (Ref),
      Post => Correct_Stream_Node (Tree, Ref.Ref) and Parents_Valid (Ref);
    --  Update Ref to last terminal with valid Sequential_Index in
    --  Ref.Node or, if Preceding, a preceding stream element; if
@@ -2060,7 +2085,7 @@ package WisiToken.Syntax_Trees is
      (Tree      : in     Syntax_Trees.Tree;
       Ref       : in out Syntax_Trees.Stream_Node_Parents;
       Following : in     Boolean)
-   with Pre => Valid_Stream_Node (Tree, Ref.Ref) and Parents_Valid (Ref),
+   with Pre => Tree.Valid_Stream_Node_Parents (Ref),
      Post => Correct_Stream_Node (Tree, Ref.Ref) and Parents_Valid (Ref);
    --  Update Node to the first terminal with valid Sequential_Index
    --  succeeding Node. Can step past EOI. If not Following, do not step
@@ -2079,7 +2104,7 @@ package WisiToken.Syntax_Trees is
       Ref          : in out Stream_Node_Parents;
       Parse_Stream : in     Stream_ID;
       Preceding    : in     Boolean)
-   with Pre => Valid_Stream_Node (Tree, Ref.Ref) and Parents_Valid (Ref),
+   with Pre => Tree.Valid_Stream_Node_Parents (Ref),
      Post => Correct_Stream_Node (Tree, Ref.Ref) and Parents_Valid (Ref);
 
    function Get_IDs
@@ -2094,7 +2119,7 @@ package WisiToken.Syntax_Trees is
    --  zero streams, so these subprograms have no stream argument.
    --
    --  Some of these are also used for Packrat parsing, and don't have a
-   --  precondition of Fully_Parsed.
+   --  precondition.
 
    function Cleared (Tree : in Syntax_Trees.Tree) return Boolean;
    --  True if there are no streams and no nodes.
@@ -2107,9 +2132,11 @@ package WisiToken.Syntax_Trees is
    --  Shared_Stream holds a lexed or edited stream.
 
    function Fully_Parsed (Tree : in Syntax_Trees.Tree) return Boolean;
-   --  True if there is only one parse stream, and it has only two
-   --  elements; SOI with the start state and the tree root (EOI is only
-   --  in the shared stream).
+   --  True if Tree.Root is valid; a parse succeeded.
+   --
+   --  LR parse leaves a parse stream containing SOI and root; Packrat
+   --  parse does not use a parse stream, it just creates nonterminal
+   --  nodes.
 
    function Editable (Tree : in Syntax_Trees.Tree) return Boolean;
    --  True if Clear_Parse_Streams and Set_Parents have been called; the
@@ -2161,22 +2188,15 @@ package WisiToken.Syntax_Trees is
       File_Name : in     String);
    --  Read the output of Put_Tree from File_Name, populate Tree.
 
-   procedure Clear_Parse_Streams
-     (Tree       : in out Syntax_Trees.Tree;
-      Keep_Nodes : in     Valid_Node_Access_Lists.List := 
Valid_Node_Access_Lists.Empty_List)
-   with Pre => Tree.Fully_Parsed or Tree.Stream_Count = 1,
+   procedure Clear_Parse_Streams (Tree : in out Syntax_Trees.Tree);
+   --  Delete the parse streams, but not the nodes they reference.
+
+   procedure Finish_Parse (Tree : in out Syntax_Trees.Tree)
+   with Pre => Tree.Root /= Invalid_Node_Access,
      Post => Tree.Editable;
-   --  If Tree.Root is not set, set it to the root of the single
-   --  remaining parse stream. Delete the parse stream and shared stream.
-   --  Delete all nodes not reachable from the root, and not Tree.SOI,
-   --  Tree.EOI, or in Keep_Nodes. Also call Set_Parents if not
+   --  Delete the parse streams and shared stream. Delete all nodes
+   --  not reachable from the root. Call Set_Parents if not
    --  Tree.Parents_Set.
-   --
-   --  Keep_Nodes should be set to nodes that occur in errors, or are
-   --  deleted by error recovery; they may be referenced by post-parse
-   --  actions.
-   --
-   --  No precondition for Packrat parser.
 
    function Parents_Set (Tree : in Syntax_Trees.Tree) return Boolean;
 
@@ -2194,12 +2214,13 @@ package WisiToken.Syntax_Trees is
 
    function Root (Tree : in Syntax_Trees.Tree) return Node_Access
    with Pre => Tree.Valid_Root;
-   --  Tree.Root, or the root in the last parse stream if Tree.Root is
-   --  not set. Can be Invalid_Node_Access if input syntax does not allow
-   --  parsing to succeed.
+   --  The node set by Set_Root; Invalid_Node_Access if that has not been 
called.
 
    procedure Set_Root (Tree : in out Syntax_Trees.Tree; New_Root : in 
Valid_Node_Access)
-   with Pre => Tree.Label (New_Root) = Nonterm and then Tree.Child_Count 
(New_Root) > 0;
+   with Pre =>
+     Tree.ID (New_Root) = Tree.Lexer.Descriptor.Accept_ID and then
+     Tree.Label (New_Root) = Nonterm and then
+     Tree.Child_Count (New_Root) > 0;
    --  Set Tree.Root to Root. If New_Root.Children does not start with
    --  Tree.SOI, prepend it. If New_Root.Children does not end with
    --  Tree.EOI, append it.
@@ -2388,8 +2409,7 @@ package WisiToken.Syntax_Trees is
       User_Data     : in     User_Data_Access_Constant)
    with Pre =>
      Tree.Label (Deleted_Node) in Terminal_Label and
-     Tree.Valid_Stream_Node (Prev_Terminal.Ref) and
-     Parents_Valid (Prev_Terminal) and
+     Tree.Valid_Stream_Node_Parents (Prev_Terminal) and
      Prev_Terminal.Ref.Stream /= Tree.Shared_Stream and
      Tree.Label (Prev_Terminal.Ref.Node) = Source_Terminal;
    --  Copy Prev_Terminal.Ref.Node, add Deleted_Node to
@@ -2550,7 +2570,7 @@ package WisiToken.Syntax_Trees is
       Error_Ref : in out Stream_Node_Parents;
       Errors    : in     Error_Data_Lists.List;
       User_Data : in     User_Data_Access_Constant)
-   with Pre => Parents_Valid (Error_Ref) and
+   with Pre => Tree.Valid_Stream_Node_Parents (Error_Ref) and
      (for all Err of Errors => not Tree.Contains_Error (Error_Ref.Ref.Node, 
Err));
    --  Copy Error_Ref.Node and parents, add Errors to its error list.
    --  Update Error_Ref to point to copied node.
@@ -2682,7 +2702,7 @@ package WisiToken.Syntax_Trees is
    function Error_Deleted (Error : in Stream_Error_Ref) return 
Valid_Node_Access_Lists.Cursor;
 
    function First_Error (Tree : in Syntax_Trees.Tree) return Error_Ref
-   with Pre => Tree.Editable;
+   with Pre => Tree.Parents_Set;
    --  Return first error node in Tree.
 
    function First_Error (Tree : in Syntax_Trees.Tree; Stream : in Stream_ID) 
return Stream_Error_Ref;
@@ -2958,8 +2978,6 @@ package WisiToken.Syntax_Trees is
    --  in debugger for a stable way to access Node.
 
 private
-   use all type Ada.Containers.Count_Type;
-
    type Error_List_Access is access all Error_Data_Lists.List;
    procedure Free is new Ada.Unchecked_Deallocation (Error_Data_Lists.List, 
Error_List_Access);
 
diff --git a/wisitoken-user_guide.texinfo b/wisitoken-user_guide.texinfo
index ba59be658d..f95ca41985 100644
--- a/wisitoken-user_guide.texinfo
+++ b/wisitoken-user_guide.texinfo
@@ -33,7 +33,7 @@ section entitled "GNU Free Documentation License".
 @contents
 
 @node Top
-@top WisiToken User Guide version 3.0
+@top WisiToken User Guide version 4.0
 
 @ifnottex
 @insertcopying
diff --git a/wisitoken.ads b/wisitoken.ads
index 3606c8387d..b8a4b0c8e4 100644
--- a/wisitoken.ads
+++ b/wisitoken.ads
@@ -78,6 +78,8 @@ package WisiToken is
 
    --  SAL.Programmer_Error : exception; -- a programming convention has been 
violated
 
+   Validate_Error : exception; -- A validation has failed.
+
    subtype Positive_Index_Type is SAL.Peek_Type;
    function Trimmed_Image is new SAL.Gen_Trimmed_Image (SAL.Base_Peek_Type);
 
@@ -532,4 +534,6 @@ package WisiToken is
    --  (ending delim is read from the stream but not included in result).
    --  Leading Delims are skipped.
 
+   type Recursion_Strategy is (None, Partial, Full);
+
 end WisiToken;
diff --git a/wisitoken_grammar_actions.ads b/wisitoken_grammar_actions.ads
index 4c044a5302..f8a7654b7b 100644
--- a/wisitoken_grammar_actions.ads
+++ b/wisitoken_grammar_actions.ads
@@ -283,4 +283,6 @@ package Wisitoken_Grammar_Actions is
      (User_Data : in out WisiToken.Syntax_Trees.User_Data_Type'Class;
       Tree      : in out WisiToken.Syntax_Trees.Tree;
       Nonterm   : in     WisiToken.Syntax_Trees.Valid_Node_Access);
+   Partial_Parse_Active    : aliased Boolean := False;
+   Partial_Parse_Byte_Goal : aliased WisiToken.Buffer_Pos := 
WisiToken.Buffer_Pos'Last;
 end Wisitoken_Grammar_Actions;
diff --git a/wisitoken_grammar_editing.adb b/wisitoken_grammar_editing.adb
index 81b16b1dcc..8d0ad09ed4 100644
--- a/wisitoken_grammar_editing.adb
+++ b/wisitoken_grammar_editing.adb
@@ -2937,7 +2937,7 @@ package body WisiToken_Grammar_Editing is
          if Data.Error_Reported.Count > 0 then
             Ada.Text_IO.New_Line;
             Ada.Text_IO.Put_Line ("initial invalid tree:");
-            Tree.Print_Tree;
+            Tree.Print_Tree (Line_Numbers => True, Non_Grammar => True);
          end if;
       end if;
 
diff --git a/wisitoken_grammar_main.adb b/wisitoken_grammar_main.adb
index d985bb4429..4816a20407 100644
--- a/wisitoken_grammar_main.adb
+++ b/wisitoken_grammar_main.adb
@@ -24,6 +24,7 @@
 with SAL;
 with WisiToken.Lexer.re2c;
 with wisitoken_grammar_re2c_c;
+with WisiToken.Parse.LR;
 with Wisitoken_Grammar_Actions; use Wisitoken_Grammar_Actions;
 package body Wisitoken_Grammar_Main is
 
@@ -960,11 +961,6 @@ package body Wisitoken_Grammar_Main is
       return Table;
    end Create_Parse_Table;
 
-   function Create_Lexer (Trace : in WisiToken.Trace_Access) return 
WisiToken.Lexer.Handle
-   is begin
-      return Lexer.New_Lexer (Trace, 
Wisitoken_Grammar_Actions.Descriptor'Access);
-   end Create_Lexer;
-
    function Create_Productions return 
WisiToken.Syntax_Trees.Production_Info_Trees.Vector
    is begin
       return Result : WisiToken.Syntax_Trees.Production_Info_Trees.Vector do
@@ -1032,4 +1028,16 @@ package body Wisitoken_Grammar_Main is
       end return;
    end Create_Productions;
 
+   function Create_Parser
+     (Trace      : in WisiToken.Trace_Access;
+      User_Data  : in WisiToken.Syntax_Trees.User_Data_Access)
+     return WisiToken.Parse.LR.Parser_No_Recover.Parser
+   is begin
+      return Parser : WisiToken.Parse.LR.Parser_No_Recover.Parser do
+         Parser.Tree.Lexer := Lexer.New_Lexer (Trace, 
Wisitoken_Grammar_Actions.Descriptor'Access);
+         Parser.Productions := Create_Productions;
+         Parser.User_Data := User_Data;
+         Parser.Table := Create_Parse_Table;
+      end return;
+   end Create_Parser;
 end Wisitoken_Grammar_Main;
diff --git a/wisitoken_grammar_main.ads b/wisitoken_grammar_main.ads
index 90354e3a79..1e7b6f937a 100644
--- a/wisitoken_grammar_main.ads
+++ b/wisitoken_grammar_main.ads
@@ -22,14 +22,12 @@
 --  along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 with WisiToken.Syntax_Trees;
-with WisiToken.Lexer;
-with WisiToken.Parse.LR;
+with WisiToken.Parse.LR.Parser_No_Recover;
 package Wisitoken_Grammar_Main is
 
-   function Create_Parse_Table
-     return WisiToken.Parse.LR.Parse_Table_Ptr;
+   function Create_Parser
+     (Trace      : in WisiToken.Trace_Access;
+      User_Data  : in WisiToken.Syntax_Trees.User_Data_Access)
+     return WisiToken.Parse.LR.Parser_No_Recover.Parser;
 
-   function Create_Productions return 
WisiToken.Syntax_Trees.Production_Info_Trees.Vector;
-
-   function Create_Lexer (Trace : in WisiToken.Trace_Access) return 
WisiToken.Lexer.Handle;
 end Wisitoken_Grammar_Main;
diff --git a/wisitoken_grammar_re2c.c b/wisitoken_grammar_re2c.c
index 7a76ad1ae7..712d5eb487 100644
--- a/wisitoken_grammar_re2c.c
+++ b/wisitoken_grammar_re2c.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 2.0.2 */
+/* Generated by re2c 3.0 */
 #line 1 "../wisitoken_grammar.re2c"
 //  generated parser support file. -*- buffer-read-only:t mode: C -*-
 //  command line: wisitoken-bnf-generate.exe  --generate LALR Ada re2c 
wisitoken_grammar.wy
@@ -207,5536 +207,5493 @@ int wisitoken_grammar_next_token
 {
        YYCTYPE yych;
        unsigned int yyaccept = 0;
-       YYDEBUG(0, *YYCURSOR);
+       YYDEBUG(0, YYPEEK());
        yych = YYPEEK();
        switch (yych) {
-       case 0x04:      goto yy4;
-       case '\t':
-       case ' ':       goto yy6;
-       case '\n':      goto yy8;
-       case '\r':      goto yy10;
-       case '"':       goto yy11;
-       case '%':       goto yy12;
-       case '\'':      goto yy14;
-       case '(':       goto yy15;
-       case ')':       goto yy17;
-       case '*':       goto yy19;
-       case '+':       goto yy21;
-       case '-':       goto yy23;
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':       goto yy25;
-       case ':':       goto yy28;
-       case ';':       goto yy30;
-       case '<':       goto yy32;
-       case '=':       goto yy34;
-       case '>':       goto yy36;
-       case '?':       goto yy38;
-       case 'A':
-       case 'a':       goto yy40;
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case 'b':
-       case 'd':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'j':
-       case 'l':
-       case 'm':
-       case 'p':
-       case 'q':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':       goto yy42;
-       case 'R':
-       case 'r':       goto yy44;
-       case 'S':
-       case 's':       goto yy45;
-       case '[':       goto yy46;
-       case ']':       goto yy48;
-       case 'c':       goto yy50;
-       case 'e':       goto yy51;
-       case 'i':       goto yy52;
-       case 'k':       goto yy53;
-       case 'n':       goto yy54;
-       case 'o':       goto yy55;
-       case 't':       goto yy56;
-       case '{':       goto yy57;
-       case '|':       goto yy59;
-       case '}':       goto yy61;
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:      goto yy63;
-       case 0xE0:      goto yy64;
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:      goto yy65;
-       case 0xF0:      goto yy66;
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:      goto yy67;
-       case 0xF4:      goto yy68;
-       default:        goto yy2;
+               case 0x04: goto yy3;
+               case '\t':
+               case ' ': goto yy4;
+               case '\n': goto yy5;
+               case '\r': goto yy6;
+               case '"': goto yy7;
+               case '%': goto yy8;
+               case '\'': goto yy10;
+               case '(': goto yy11;
+               case ')': goto yy12;
+               case '*': goto yy13;
+               case '+': goto yy14;
+               case '-': goto yy15;
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9': goto yy17;
+               case ':': goto yy19;
+               case ';': goto yy21;
+               case '<': goto yy23;
+               case '=': goto yy24;
+               case '>': goto yy25;
+               case '?': goto yy26;
+               case 'A':
+               case 'a': goto yy27;
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case 'b':
+               case 'd':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'j':
+               case 'l':
+               case 'm':
+               case 'p':
+               case 'q':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z': goto yy29;
+               case 'R':
+               case 'r': goto yy31;
+               case 'S':
+               case 's': goto yy32;
+               case '[': goto yy33;
+               case ']': goto yy34;
+               case 'c': goto yy35;
+               case 'e': goto yy36;
+               case 'i': goto yy37;
+               case 'k': goto yy38;
+               case 'n': goto yy39;
+               case 'o': goto yy40;
+               case 't': goto yy41;
+               case '{': goto yy42;
+               case '|': goto yy43;
+               case '}': goto yy44;
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF: goto yy45;
+               case 0xE0: goto yy46;
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF: goto yy47;
+               case 0xF0: goto yy48;
+               case 0xF1:
+               case 0xF2:
+               case 0xF3: goto yy49;
+               case 0xF4: goto yy50;
+               default: goto yy1;
        }
+yy1:
+       YYDEBUG(1, YYPEEK());
+       YYSKIP();
 yy2:
        YYDEBUG(2, YYPEEK());
-       YYSKIP();
-yy3:
-       YYDEBUG(3, YYPEEK());
 #line 296 "../wisitoken_grammar.re2c"
        {status = ERROR_unrecognized_character; continue;}
 #line 360 "../wisitoken_grammar_re2c.c"
-yy4:
-       YYDEBUG(4, YYPEEK());
+yy3:
+       YYDEBUG(3, YYPEEK());
        YYSKIP();
-       YYDEBUG(5, YYPEEK());
 #line 294 "../wisitoken_grammar.re2c"
        {*id = 42; continue;}
-#line 367 "../wisitoken_grammar_re2c.c"
-yy6:
-       YYDEBUG(6, YYPEEK());
+#line 366 "../wisitoken_grammar_re2c.c"
+yy4:
+       YYDEBUG(4, YYPEEK());
        YYSKIP();
-       YYDEBUG(7, YYPEEK());
 #line 249 "../wisitoken_grammar.re2c"
        { lexer->byte_token_start = lexer->cursor;
           lexer->char_token_start = lexer->char_pos;
           lexer->line_token_start = lexer->line;
           continue; }
-#line 377 "../wisitoken_grammar_re2c.c"
-yy8:
-       YYDEBUG(8, YYPEEK());
+#line 375 "../wisitoken_grammar_re2c.c"
+yy5:
+       YYDEBUG(5, YYPEEK());
        YYSKIP();
-       YYDEBUG(9, YYPEEK());
 #line 253 "../wisitoken_grammar.re2c"
        {*id = 1; lexer->line++; continue;}
-#line 384 "../wisitoken_grammar_re2c.c"
-yy10:
-       YYDEBUG(10, YYPEEK());
+#line 381 "../wisitoken_grammar_re2c.c"
+yy6:
+       YYDEBUG(6, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case '\n':      goto yy8;
-       default:        goto yy3;
+               case '\n': goto yy5;
+               default: goto yy2;
        }
-yy11:
-       YYDEBUG(11, YYPEEK());
+yy7:
+       YYDEBUG(7, YYPEEK());
        yyaccept = 0;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case ' ':
-       case '!':
-       case '"':
-       case '#':
-       case '$':
-       case '%':
-       case '&':
-       case '\'':
-       case '(':
-       case ')':
-       case '*':
-       case '+':
-       case ',':
-       case '-':
-       case '.':
-       case '/':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case ':':
-       case ';':
-       case '<':
-       case '=':
-       case '>':
-       case '?':
-       case '@':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '[':
-       case '\\':
-       case ']':
-       case '^':
-       case '_':
-       case '`':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case '{':
-       case '|':
-       case '}':
-       case '~':
-       case 0x7F:
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:
-       case 0xE0:
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:
-       case 0xF0:
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:
-       case 0xF4:      goto yy70;
-       default:        goto yy3;
+               case ' ':
+               case '!':
+               case '"':
+               case '#':
+               case '$':
+               case '%':
+               case '&':
+               case '\'':
+               case '(':
+               case ')':
+               case '*':
+               case '+':
+               case ',':
+               case '-':
+               case '.':
+               case '/':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case ':':
+               case ';':
+               case '<':
+               case '=':
+               case '>':
+               case '?':
+               case '@':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '[':
+               case '\\':
+               case ']':
+               case '^':
+               case '_':
+               case '`':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case '{':
+               case '|':
+               case '}':
+               case '~':
+               case 0x7F:
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF:
+               case 0xE0:
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF:
+               case 0xF0:
+               case 0xF1:
+               case 0xF2:
+               case 0xF3:
+               case 0xF4: goto yy52;
+               default: goto yy2;
        }
-yy12:
-       YYDEBUG(12, YYPEEK());
+yy8:
+       YYDEBUG(8, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case '(':       goto yy80;
-       case '[':       goto yy82;
-       case '{':       goto yy84;
-       default:        goto yy13;
+               case '(': goto yy62;
+               case '[': goto yy63;
+               case '{': goto yy64;
+               default: goto yy9;
        }
-yy13:
-       YYDEBUG(13, YYPEEK());
+yy9:
+       YYDEBUG(9, YYPEEK());
 #line 282 "../wisitoken_grammar.re2c"
        {*id = 30; continue;}
-#line 563 "../wisitoken_grammar_re2c.c"
-yy14:
-       YYDEBUG(14, YYPEEK());
+#line 560 "../wisitoken_grammar_re2c.c"
+yy10:
+       YYDEBUG(10, YYPEEK());
        yyaccept = 0;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case ' ':
-       case '!':
-       case '"':
-       case '#':
-       case '$':
-       case '%':
-       case '&':
-       case '\'':
-       case '(':
-       case ')':
-       case '*':
-       case '+':
-       case ',':
-       case '-':
-       case '.':
-       case '/':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case ':':
-       case ';':
-       case '<':
-       case '=':
-       case '>':
-       case '?':
-       case '@':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '[':
-       case '\\':
-       case ']':
-       case '^':
-       case '_':
-       case '`':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case '{':
-       case '|':
-       case '}':
-       case '~':
-       case 0x7F:
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:
-       case 0xE0:
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:
-       case 0xF0:
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:
-       case 0xF4:      goto yy87;
-       default:        goto yy3;
+               case ' ':
+               case '!':
+               case '"':
+               case '#':
+               case '$':
+               case '%':
+               case '&':
+               case '\'':
+               case '(':
+               case ')':
+               case '*':
+               case '+':
+               case ',':
+               case '-':
+               case '.':
+               case '/':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case ':':
+               case ';':
+               case '<':
+               case '=':
+               case '>':
+               case '?':
+               case '@':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '[':
+               case '\\':
+               case ']':
+               case '^':
+               case '_':
+               case '`':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case '{':
+               case '|':
+               case '}':
+               case '~':
+               case 0x7F:
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF:
+               case 0xE0:
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF:
+               case 0xF0:
+               case 0xF1:
+               case 0xF2:
+               case 0xF3:
+               case 0xF4: goto yy66;
+               default: goto yy2;
        }
-yy15:
-       YYDEBUG(15, YYPEEK());
+yy11:
+       YYDEBUG(11, YYPEEK());
        YYSKIP();
-       YYDEBUG(16, YYPEEK());
 #line 279 "../wisitoken_grammar.re2c"
        {*id = 27; continue;}
-#line 726 "../wisitoken_grammar_re2c.c"
-yy17:
-       YYDEBUG(17, YYPEEK());
+#line 722 "../wisitoken_grammar_re2c.c"
+yy12:
+       YYDEBUG(12, YYPEEK());
        YYSKIP();
-       YYDEBUG(18, YYPEEK());
 #line 287 "../wisitoken_grammar.re2c"
        {*id = 35; continue;}
-#line 733 "../wisitoken_grammar_re2c.c"
-yy19:
-       YYDEBUG(19, YYPEEK());
+#line 728 "../wisitoken_grammar_re2c.c"
+yy13:
+       YYDEBUG(13, YYPEEK());
        YYSKIP();
-       YYDEBUG(20, YYPEEK());
 #line 289 "../wisitoken_grammar.re2c"
        {*id = 37; continue;}
-#line 740 "../wisitoken_grammar_re2c.c"
-yy21:
-       YYDEBUG(21, YYPEEK());
+#line 734 "../wisitoken_grammar_re2c.c"
+yy14:
+       YYDEBUG(14, YYPEEK());
        YYSKIP();
-       YYDEBUG(22, YYPEEK());
 #line 283 "../wisitoken_grammar.re2c"
        {*id = 31; continue;}
-#line 747 "../wisitoken_grammar_re2c.c"
-yy23:
-       YYDEBUG(23, YYPEEK());
+#line 740 "../wisitoken_grammar_re2c.c"
+yy15:
+       YYDEBUG(15, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case '_':       goto yy25;
-       default:        goto yy24;
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case '_': goto yy17;
+               default: goto yy16;
        }
-yy24:
-       YYDEBUG(24, YYPEEK());
+yy16:
+       YYDEBUG(16, YYPEEK());
 #line 281 "../wisitoken_grammar.re2c"
        {*id = 29; continue;}
-#line 770 "../wisitoken_grammar_re2c.c"
-yy25:
-       YYDEBUG(25, YYPEEK());
+#line 763 "../wisitoken_grammar_re2c.c"
+yy17:
+       YYDEBUG(17, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
-       YYDEBUG(26, YYPEEK());
        switch (yych) {
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case '_':       goto yy25;
-       default:        goto yy27;
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case '_': goto yy17;
+               default: goto yy18;
        }
-yy27:
-       YYDEBUG(27, YYPEEK());
+yy18:
+       YYDEBUG(18, YYPEEK());
 #line 290 "../wisitoken_grammar.re2c"
        {*id = 38; continue;}
-#line 794 "../wisitoken_grammar_re2c.c"
-yy28:
-       YYDEBUG(28, YYPEEK());
+#line 786 "../wisitoken_grammar_re2c.c"
+yy19:
+       YYDEBUG(19, YYPEEK());
        yyaccept = 1;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case ':':       goto yy96;
-       default:        goto yy29;
+               case ':': goto yy75;
+               default: goto yy20;
        }
-yy29:
-       YYDEBUG(29, YYPEEK());
+yy20:
+       YYDEBUG(20, YYPEEK());
 #line 273 "../wisitoken_grammar.re2c"
        {*id = 21; continue;}
-#line 809 "../wisitoken_grammar_re2c.c"
-yy30:
-       YYDEBUG(30, YYPEEK());
+#line 801 "../wisitoken_grammar_re2c.c"
+yy21:
+       YYDEBUG(21, YYPEEK());
        yyaccept = 2;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case ';':       goto yy97;
-       default:        goto yy31;
+               case ';': goto yy76;
+               default: goto yy22;
        }
-yy31:
-       YYDEBUG(31, YYPEEK());
+yy22:
+       YYDEBUG(22, YYPEEK());
 #line 288 "../wisitoken_grammar.re2c"
        {*id = 36; continue;}
-#line 824 "../wisitoken_grammar_re2c.c"
-yy32:
-       YYDEBUG(32, YYPEEK());
+#line 816 "../wisitoken_grammar_re2c.c"
+yy23:
+       YYDEBUG(23, YYPEEK());
        YYSKIP();
-       YYDEBUG(33, YYPEEK());
 #line 280 "../wisitoken_grammar.re2c"
        {*id = 28; continue;}
-#line 831 "../wisitoken_grammar_re2c.c"
-yy34:
-       YYDEBUG(34, YYPEEK());
+#line 822 "../wisitoken_grammar_re2c.c"
+yy24:
+       YYDEBUG(24, YYPEEK());
        YYSKIP();
-       YYDEBUG(35, YYPEEK());
 #line 275 "../wisitoken_grammar.re2c"
        {*id = 23; continue;}
-#line 838 "../wisitoken_grammar_re2c.c"
-yy36:
-       YYDEBUG(36, YYPEEK());
+#line 828 "../wisitoken_grammar_re2c.c"
+yy25:
+       YYDEBUG(25, YYPEEK());
        YYSKIP();
-       YYDEBUG(37, YYPEEK());
 #line 276 "../wisitoken_grammar.re2c"
        {*id = 24; continue;}
-#line 845 "../wisitoken_grammar_re2c.c"
-yy38:
-       YYDEBUG(38, YYPEEK());
+#line 834 "../wisitoken_grammar_re2c.c"
+yy26:
+       YYDEBUG(26, YYPEEK());
        YYSKIP();
-       YYDEBUG(39, YYPEEK());
 #line 284 "../wisitoken_grammar.re2c"
        {*id = 32; continue;}
-#line 852 "../wisitoken_grammar_re2c.c"
-yy40:
-       YYDEBUG(40, YYPEEK());
+#line 840 "../wisitoken_grammar_re2c.c"
+yy27:
+       YYDEBUG(27, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'C':
-       case 'c':       goto yy99;
-       default:        goto yy43;
+               case 'C':
+               case 'c': goto yy77;
+               default: goto yy30;
        }
-yy41:
-       YYDEBUG(41, YYPEEK());
+yy28:
+       YYDEBUG(28, YYPEEK());
 #line 291 "../wisitoken_grammar.re2c"
        {*id = 39; continue;}
-#line 868 "../wisitoken_grammar_re2c.c"
-yy42:
-       YYDEBUG(42, YYPEEK());
+#line 856 "../wisitoken_grammar_re2c.c"
+yy29:
+       YYDEBUG(29, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
-yy43:
-       YYDEBUG(43, YYPEEK());
+yy30:
+       YYDEBUG(30, YYPEEK());
        switch (yych) {
-       case '-':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '_':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':       goto yy42;
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:      goto yy100;
-       case 0xE0:      goto yy101;
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:      goto yy102;
-       case 0xF0:      goto yy103;
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:      goto yy104;
-       case 0xF4:      goto yy105;
-       default:        goto yy41;
+               case '-':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '_':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z': goto yy29;
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF: goto yy78;
+               case 0xE0: goto yy79;
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF: goto yy80;
+               case 0xF0: goto yy81;
+               case 0xF1:
+               case 0xF2:
+               case 0xF3: goto yy82;
+               case 0xF4: goto yy83;
+               default: goto yy28;
        }
-yy44:
-       YYDEBUG(44, YYPEEK());
+yy31:
+       YYDEBUG(31, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'E':
-       case 'e':       goto yy106;
-       default:        goto yy43;
+               case 'E':
+               case 'e': goto yy84;
+               default: goto yy30;
        }
-yy45:
-       YYDEBUG(45, YYPEEK());
+yy32:
+       YYDEBUG(32, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'H':
-       case 'h':       goto yy107;
-       default:        goto yy43;
+               case 'H':
+               case 'h': goto yy85;
+               default: goto yy30;
        }
-yy46:
-       YYDEBUG(46, YYPEEK());
+yy33:
+       YYDEBUG(33, YYPEEK());
        YYSKIP();
-       YYDEBUG(47, YYPEEK());
 #line 278 "../wisitoken_grammar.re2c"
        {*id = 26; continue;}
-#line 1023 "../wisitoken_grammar_re2c.c"
-yy48:
-       YYDEBUG(48, YYPEEK());
+#line 1010 "../wisitoken_grammar_re2c.c"
+yy34:
+       YYDEBUG(34, YYPEEK());
        YYSKIP();
-       YYDEBUG(49, YYPEEK());
 #line 286 "../wisitoken_grammar.re2c"
        {*id = 34; continue;}
-#line 1030 "../wisitoken_grammar_re2c.c"
-yy50:
-       YYDEBUG(50, YYPEEK());
+#line 1016 "../wisitoken_grammar_re2c.c"
+yy35:
+       YYDEBUG(35, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'o':       goto yy108;
-       default:        goto yy43;
+               case 'o': goto yy86;
+               default: goto yy30;
        }
-yy51:
-       YYDEBUG(51, YYPEEK());
+yy36:
+       YYDEBUG(36, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'l':       goto yy109;
-       case 'n':       goto yy110;
-       default:        goto yy43;
+               case 'l': goto yy87;
+               case 'n': goto yy88;
+               default: goto yy30;
        }
-yy52:
-       YYDEBUG(52, YYPEEK());
+yy37:
+       YYDEBUG(37, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'f':       goto yy111;
-       case 'n':       goto yy113;
-       default:        goto yy43;
+               case 'f': goto yy89;
+               case 'n': goto yy91;
+               default: goto yy30;
        }
-yy53:
-       YYDEBUG(53, YYPEEK());
+yy38:
+       YYDEBUG(38, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'e':       goto yy115;
-       default:        goto yy43;
+               case 'e': goto yy93;
+               default: goto yy30;
        }
-yy54:
-       YYDEBUG(54, YYPEEK());
+yy39:
+       YYDEBUG(39, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'o':       goto yy116;
-       default:        goto yy43;
+               case 'o': goto yy94;
+               default: goto yy30;
        }
-yy55:
-       YYDEBUG(55, YYPEEK());
+yy40:
+       YYDEBUG(40, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'n':       goto yy117;
-       default:        goto yy43;
+               case 'n': goto yy95;
+               default: goto yy30;
        }
-yy56:
-       YYDEBUG(56, YYPEEK());
+yy41:
+       YYDEBUG(41, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'o':       goto yy119;
-       default:        goto yy43;
+               case 'o': goto yy97;
+               default: goto yy30;
        }
-yy57:
-       YYDEBUG(57, YYPEEK());
+yy42:
+       YYDEBUG(42, YYPEEK());
        YYSKIP();
-       YYDEBUG(58, YYPEEK());
 #line 277 "../wisitoken_grammar.re2c"
        {*id = 25; continue;}
-#line 1109 "../wisitoken_grammar_re2c.c"
-yy59:
-       YYDEBUG(59, YYPEEK());
+#line 1094 "../wisitoken_grammar_re2c.c"
+yy43:
+       YYDEBUG(43, YYPEEK());
        YYSKIP();
-       YYDEBUG(60, YYPEEK());
 #line 272 "../wisitoken_grammar.re2c"
        {*id = 20; continue;}
-#line 1116 "../wisitoken_grammar_re2c.c"
-yy61:
-       YYDEBUG(61, YYPEEK());
+#line 1100 "../wisitoken_grammar_re2c.c"
+yy44:
+       YYDEBUG(44, YYPEEK());
        YYSKIP();
-       YYDEBUG(62, YYPEEK());
 #line 285 "../wisitoken_grammar.re2c"
        {*id = 33; continue;}
-#line 1123 "../wisitoken_grammar_re2c.c"
-yy63:
-       YYDEBUG(63, YYPEEK());
+#line 1106 "../wisitoken_grammar_re2c.c"
+yy45:
+       YYDEBUG(45, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy42;
-       default:        goto yy3;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F:
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy29;
+               default: goto yy2;
        }
-yy64:
-       YYDEBUG(64, YYPEEK());
+yy46:
+       YYDEBUG(46, YYPEEK());
        yyaccept = 0;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy100;
-       default:        goto yy3;
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy78;
+               default: goto yy2;
        }
-yy65:
-       YYDEBUG(65, YYPEEK());
+yy47:
+       YYDEBUG(47, YYPEEK());
        yyaccept = 0;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy100;
-       default:        goto yy3;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F:
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy78;
+               default: goto yy2;
        }
-yy66:
-       YYDEBUG(66, YYPEEK());
+yy48:
+       YYDEBUG(48, YYPEEK());
        yyaccept = 0;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy102;
-       default:        goto yy3;
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy80;
+               default: goto yy2;
        }
-yy67:
-       YYDEBUG(67, YYPEEK());
+yy49:
+       YYDEBUG(49, YYPEEK());
        yyaccept = 0;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy102;
-       default:        goto yy3;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F:
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy80;
+               default: goto yy2;
        }
-yy68:
-       YYDEBUG(68, YYPEEK());
+yy50:
+       YYDEBUG(50, YYPEEK());
        yyaccept = 0;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:      goto yy102;
-       default:        goto yy3;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F: goto yy80;
+               default: goto yy2;
        }
-yy69:
-       YYDEBUG(69, YYPEEK());
+yy51:
+       YYDEBUG(51, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
-yy70:
-       YYDEBUG(70, YYPEEK());
+yy52:
+       YYDEBUG(52, YYPEEK());
        switch (yych) {
-       case ' ':
-       case '!':
-       case '#':
-       case '$':
-       case '%':
-       case '&':
-       case '\'':
-       case '(':
-       case ')':
-       case '*':
-       case '+':
-       case ',':
-       case '-':
-       case '.':
-       case '/':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case ':':
-       case ';':
-       case '<':
-       case '=':
-       case '>':
-       case '?':
-       case '@':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '[':
-       case '\\':
-       case ']':
-       case '^':
-       case '_':
-       case '`':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case '{':
-       case '|':
-       case '}':
-       case '~':
-       case 0x7F:      goto yy69;
-       case '"':       goto yy72;
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:      goto yy74;
-       case 0xE0:      goto yy75;
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:      goto yy76;
-       case 0xF0:      goto yy77;
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:      goto yy78;
-       case 0xF4:      goto yy79;
-       default:        goto yy71;
+               case ' ':
+               case '!':
+               case '#':
+               case '$':
+               case '%':
+               case '&':
+               case '\'':
+               case '(':
+               case ')':
+               case '*':
+               case '+':
+               case ',':
+               case '-':
+               case '.':
+               case '/':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case ':':
+               case ';':
+               case '<':
+               case '=':
+               case '>':
+               case '?':
+               case '@':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '[':
+               case '\\':
+               case ']':
+               case '^':
+               case '_':
+               case '`':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case '{':
+               case '|':
+               case '}':
+               case '~':
+               case 0x7F: goto yy51;
+               case '"': goto yy54;
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF: goto yy56;
+               case 0xE0: goto yy57;
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF: goto yy58;
+               case 0xF0: goto yy59;
+               case 0xF1:
+               case 0xF2:
+               case 0xF3: goto yy60;
+               case 0xF4: goto yy61;
+               default: goto yy53;
        }
-yy71:
-       YYDEBUG(71, YYPEEK());
+yy53:
+       YYDEBUG(53, YYPEEK());
        YYRESTORE();
        switch (yyaccept) {
-       case 0:
-               goto yy3;
-       case 1:
-               goto yy29;
-       case 2:
-               goto yy31;
-       case 3:
-               goto yy41;
-       case 4:
-               goto yy73;
-       case 5:
-               goto yy89;
-       case 6:
-               goto yy112;
-       case 7:
-               goto yy114;
-       case 8:
-               goto yy118;
-       case 9:
-               goto yy137;
-       case 10:
-               goto yy145;
-       case 11:
-               goto yy154;
-       case 12:
-               goto yy157;
-       case 13:
-               goto yy161;
-       case 14:
-               goto yy164;
-       case 15:
-               goto yy171;
-       case 16:
-               goto yy175;
-       case 17:
-               goto yy178;
-       case 18:
-               goto yy185;
-       default:
-               goto yy194;
+               case 0: goto yy2;
+               case 1: goto yy20;
+               case 2: goto yy22;
+               case 3: goto yy28;
+               case 4: goto yy55;
+               case 5: goto yy68;
+               case 6: goto yy90;
+               case 7: goto yy92;
+               case 8: goto yy96;
+               case 9: goto yy113;
+               case 10: goto yy121;
+               case 11: goto yy130;
+               case 12: goto yy133;
+               case 13: goto yy137;
+               case 14: goto yy140;
+               case 15: goto yy147;
+               case 16: goto yy151;
+               case 17: goto yy154;
+               case 18: goto yy161;
+               default: goto yy170;
        }
-yy72:
-       YYDEBUG(72, YYPEEK());
+yy54:
+       YYDEBUG(54, YYPEEK());
        yyaccept = 4;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '"':       goto yy69;
-       default:        goto yy73;
+               case '"': goto yy51;
+               default: goto yy55;
        }
-yy73:
-       YYDEBUG(73, YYPEEK());
+yy55:
+       YYDEBUG(55, YYPEEK());
 #line 292 "../wisitoken_grammar.re2c"
        {*id = 40; continue;}
-#line 1679 "../wisitoken_grammar_re2c.c"
-yy74:
-       YYDEBUG(74, YYPEEK());
+#line 1642 "../wisitoken_grammar_re2c.c"
+yy56:
+       YYDEBUG(56, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy69;
-       default:        goto yy71;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F:
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy51;
+               default: goto yy53;
        }
-yy75:
-       YYDEBUG(75, YYPEEK());
+yy57:
+       YYDEBUG(57, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy74;
-       default:        goto yy71;
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy56;
+               default: goto yy53;
        }
-yy76:
-       YYDEBUG(76, YYPEEK());
+yy58:
+       YYDEBUG(58, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy74;
-       default:        goto yy71;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F:
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy56;
+               default: goto yy53;
        }
-yy77:
-       YYDEBUG(77, YYPEEK());
+yy59:
+       YYDEBUG(59, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy76;
-       default:        goto yy71;
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy58;
+               default: goto yy53;
        }
-yy78:
-       YYDEBUG(78, YYPEEK());
+yy60:
+       YYDEBUG(60, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy76;
-       default:        goto yy71;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F:
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy58;
+               default: goto yy53;
        }
-yy79:
-       YYDEBUG(79, YYPEEK());
+yy61:
+       YYDEBUG(61, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:      goto yy76;
-       default:        goto yy71;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F: goto yy58;
+               default: goto yy53;
        }
-yy80:
-       YYDEBUG(80, YYPEEK());
+yy62:
+       YYDEBUG(62, YYPEEK());
        YYSKIP();
-       YYDEBUG(81, YYPEEK());
 #line 271 "../wisitoken_grammar.re2c"
        {*id = 19; skip_to(lexer, ")%"); continue;}
-#line 2016 "../wisitoken_grammar_re2c.c"
-yy82:
-       YYDEBUG(82, YYPEEK());
+#line 1978 "../wisitoken_grammar_re2c.c"
+yy63:
+       YYDEBUG(63, YYPEEK());
        YYSKIP();
-       YYDEBUG(83, YYPEEK());
 #line 270 "../wisitoken_grammar.re2c"
        {*id = 18; skip_to(lexer, "]%"); continue;}
-#line 2023 "../wisitoken_grammar_re2c.c"
-yy84:
-       YYDEBUG(84, YYPEEK());
+#line 1984 "../wisitoken_grammar_re2c.c"
+yy64:
+       YYDEBUG(64, YYPEEK());
        YYSKIP();
-       YYDEBUG(85, YYPEEK());
 #line 269 "../wisitoken_grammar.re2c"
        {*id = 17; skip_to(lexer, "}%"); continue;}
-#line 2030 "../wisitoken_grammar_re2c.c"
-yy86:
-       YYDEBUG(86, YYPEEK());
+#line 1990 "../wisitoken_grammar_re2c.c"
+yy65:
+       YYDEBUG(65, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
-yy87:
-       YYDEBUG(87, YYPEEK());
+yy66:
+       YYDEBUG(66, YYPEEK());
        switch (yych) {
-       case ' ':
-       case '!':
-       case '"':
-       case '#':
-       case '$':
-       case '%':
-       case '&':
-       case '(':
-       case ')':
-       case '*':
-       case '+':
-       case ',':
-       case '-':
-       case '.':
-       case '/':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case ':':
-       case ';':
-       case '<':
-       case '=':
-       case '>':
-       case '?':
-       case '@':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '[':
-       case '\\':
-       case ']':
-       case '^':
-       case '_':
-       case '`':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case '{':
-       case '|':
-       case '}':
-       case '~':
-       case 0x7F:      goto yy86;
-       case '\'':      goto yy88;
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:      goto yy90;
-       case 0xE0:      goto yy91;
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:      goto yy92;
-       case 0xF0:      goto yy93;
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:      goto yy94;
-       case 0xF4:      goto yy95;
-       default:        goto yy71;
+               case ' ':
+               case '!':
+               case '"':
+               case '#':
+               case '$':
+               case '%':
+               case '&':
+               case '(':
+               case ')':
+               case '*':
+               case '+':
+               case ',':
+               case '-':
+               case '.':
+               case '/':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case ':':
+               case ';':
+               case '<':
+               case '=':
+               case '>':
+               case '?':
+               case '@':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '[':
+               case '\\':
+               case ']':
+               case '^':
+               case '_':
+               case '`':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case '{':
+               case '|':
+               case '}':
+               case '~':
+               case 0x7F: goto yy65;
+               case '\'': goto yy67;
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF: goto yy69;
+               case 0xE0: goto yy70;
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF: goto yy71;
+               case 0xF0: goto yy72;
+               case 0xF1:
+               case 0xF2:
+               case 0xF3: goto yy73;
+               case 0xF4: goto yy74;
+               default: goto yy53;
        }
-yy88:
-       YYDEBUG(88, YYPEEK());
+yy67:
+       YYDEBUG(67, YYPEEK());
        yyaccept = 5;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '\'':      goto yy86;
-       default:        goto yy89;
+               case '\'': goto yy65;
+               default: goto yy68;
        }
-yy89:
-       YYDEBUG(89, YYPEEK());
+yy68:
+       YYDEBUG(68, YYPEEK());
 #line 293 "../wisitoken_grammar.re2c"
        {*id = 41; continue;}
-#line 2201 "../wisitoken_grammar_re2c.c"
-yy90:
-       YYDEBUG(90, YYPEEK());
+#line 2161 "../wisitoken_grammar_re2c.c"
+yy69:
+       YYDEBUG(69, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy86;
-       default:        goto yy71;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F:
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy65;
+               default: goto yy53;
        }
-yy91:
-       YYDEBUG(91, YYPEEK());
+yy70:
+       YYDEBUG(70, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy90;
-       default:        goto yy71;
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy69;
+               default: goto yy53;
        }
-yy92:
-       YYDEBUG(92, YYPEEK());
+yy71:
+       YYDEBUG(71, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy90;
-       default:        goto yy71;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F:
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy69;
+               default: goto yy53;
        }
-yy93:
-       YYDEBUG(93, YYPEEK());
+yy72:
+       YYDEBUG(72, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy92;
-       default:        goto yy71;
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy71;
+               default: goto yy53;
        }
-yy94:
-       YYDEBUG(94, YYPEEK());
+yy73:
+       YYDEBUG(73, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy92;
-       default:        goto yy71;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F:
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy71;
+               default: goto yy53;
        }
-yy95:
-       YYDEBUG(95, YYPEEK());
+yy74:
+       YYDEBUG(74, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:      goto yy92;
-       default:        goto yy71;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F: goto yy71;
+               default: goto yy53;
        }
-yy96:
-       YYDEBUG(96, YYPEEK());
+yy75:
+       YYDEBUG(75, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case '=':       goto yy120;
-       default:        goto yy71;
+               case '=': goto yy98;
+               default: goto yy53;
        }
-yy97:
-       YYDEBUG(97, YYPEEK());
+yy76:
+       YYDEBUG(76, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
-       YYDEBUG(98, YYPEEK());
        switch (yych) {
-       case 0x00:
-       case 0x01:
-       case 0x02:
-       case 0x03:
-       case 0x05:
-       case 0x06:
-       case 0x07:
-       case 0x08:
-       case '\t':
-       case '\v':
-       case '\f':
-       case '\r':
-       case 0x0E:
-       case 0x0F:
-       case 0x10:
-       case 0x11:
-       case 0x12:
-       case 0x13:
-       case 0x14:
-       case 0x15:
-       case 0x16:
-       case 0x17:
-       case 0x18:
-       case 0x19:
-       case 0x1A:
-       case 0x1B:
-       case 0x1C:
-       case 0x1D:
-       case 0x1E:
-       case 0x1F:
-       case ' ':
-       case '!':
-       case '"':
-       case '#':
-       case '$':
-       case '%':
-       case '&':
-       case '\'':
-       case '(':
-       case ')':
-       case '*':
-       case '+':
-       case ',':
-       case '-':
-       case '.':
-       case '/':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case ':':
-       case ';':
-       case '<':
-       case '=':
-       case '>':
-       case '?':
-       case '@':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '[':
-       case '\\':
-       case ']':
-       case '^':
-       case '_':
-       case '`':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case '{':
-       case '|':
-       case '}':
-       case '~':
-       case 0x7F:      goto yy97;
-       case 0x04:
-       case '\n':      goto yy122;
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:      goto yy124;
-       case 0xE0:      goto yy125;
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:      goto yy126;
-       case 0xF0:      goto yy127;
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:      goto yy128;
-       case 0xF4:      goto yy129;
-       default:        goto yy71;
+               case 0x00:
+               case 0x01:
+               case 0x02:
+               case 0x03:
+               case 0x05:
+               case 0x06:
+               case 0x07:
+               case 0x08:
+               case '\t':
+               case '\v':
+               case '\f':
+               case '\r':
+               case 0x0E:
+               case 0x0F:
+               case 0x10:
+               case 0x11:
+               case 0x12:
+               case 0x13:
+               case 0x14:
+               case 0x15:
+               case 0x16:
+               case 0x17:
+               case 0x18:
+               case 0x19:
+               case 0x1A:
+               case 0x1B:
+               case 0x1C:
+               case 0x1D:
+               case 0x1E:
+               case 0x1F:
+               case ' ':
+               case '!':
+               case '"':
+               case '#':
+               case '$':
+               case '%':
+               case '&':
+               case '\'':
+               case '(':
+               case ')':
+               case '*':
+               case '+':
+               case ',':
+               case '-':
+               case '.':
+               case '/':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case ':':
+               case ';':
+               case '<':
+               case '=':
+               case '>':
+               case '?':
+               case '@':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '[':
+               case '\\':
+               case ']':
+               case '^':
+               case '_':
+               case '`':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case '{':
+               case '|':
+               case '}':
+               case '~':
+               case 0x7F: goto yy76;
+               case 0x04:
+               case '\n': goto yy99;
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF: goto yy100;
+               case 0xE0: goto yy101;
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF: goto yy102;
+               case 0xF0: goto yy103;
+               case 0xF1:
+               case 0xF2:
+               case 0xF3: goto yy104;
+               case 0xF4: goto yy105;
+               default: goto yy53;
        }
-yy99:
-       YYDEBUG(99, YYPEEK());
+yy77:
+       YYDEBUG(77, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'C':
-       case 'c':       goto yy130;
-       default:        goto yy43;
+               case 'C':
+               case 'c': goto yy106;
+               default: goto yy30;
        }
-yy100:
-       YYDEBUG(100, YYPEEK());
+yy78:
+       YYDEBUG(78, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy42;
-       default:        goto yy71;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F:
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy29;
+               default: goto yy53;
        }
-yy101:
-       YYDEBUG(101, YYPEEK());
+yy79:
+       YYDEBUG(79, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy100;
-       default:        goto yy71;
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy78;
+               default: goto yy53;
        }
-yy102:
-       YYDEBUG(102, YYPEEK());
+yy80:
+       YYDEBUG(80, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy100;
-       default:        goto yy71;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F:
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy78;
+               default: goto yy53;
        }
-yy103:
-       YYDEBUG(103, YYPEEK());
+yy81:
+       YYDEBUG(81, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy102;
-       default:        goto yy71;
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy80;
+               default: goto yy53;
        }
-yy104:
-       YYDEBUG(104, YYPEEK());
+yy82:
+       YYDEBUG(82, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy102;
-       default:        goto yy71;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F:
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy80;
+               default: goto yy53;
        }
-yy105:
-       YYDEBUG(105, YYPEEK());
+yy83:
+       YYDEBUG(83, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:      goto yy102;
-       default:        goto yy71;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F: goto yy80;
+               default: goto yy53;
        }
-yy106:
-       YYDEBUG(106, YYPEEK());
+yy84:
+       YYDEBUG(84, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'D':
-       case 'd':       goto yy131;
-       default:        goto yy43;
+               case 'D':
+               case 'd': goto yy107;
+               default: goto yy30;
        }
-yy107:
-       YYDEBUG(107, YYPEEK());
+yy85:
+       YYDEBUG(85, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'I':
-       case 'i':       goto yy132;
-       default:        goto yy43;
+               case 'I':
+               case 'i': goto yy108;
+               default: goto yy30;
        }
-yy108:
-       YYDEBUG(108, YYPEEK());
+yy86:
+       YYDEBUG(86, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'd':       goto yy133;
-       case 'n':       goto yy134;
-       default:        goto yy43;
+               case 'd': goto yy109;
+               case 'n': goto yy110;
+               default: goto yy30;
        }
-yy109:
-       YYDEBUG(109, YYPEEK());
+yy87:
+       YYDEBUG(87, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 's':       goto yy135;
-       default:        goto yy43;
+               case 's': goto yy111;
+               default: goto yy30;
        }
-yy110:
-       YYDEBUG(110, YYPEEK());
+yy88:
+       YYDEBUG(88, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'd':       goto yy136;
-       default:        goto yy43;
+               case 'd': goto yy112;
+               default: goto yy30;
        }
-yy111:
-       YYDEBUG(111, YYPEEK());
+yy89:
+       YYDEBUG(89, YYPEEK());
        yyaccept = 6;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '-':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '_':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:
-       case 0xE0:
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:
-       case 0xF0:
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:
-       case 0xF4:      goto yy43;
-       default:        goto yy112;
+               case '-':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '_':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF:
+               case 0xE0:
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF:
+               case 0xF0:
+               case 0xF1:
+               case 0xF2:
+               case 0xF3:
+               case 0xF4: goto yy30;
+               default: goto yy90;
        }
-yy112:
-       YYDEBUG(112, YYPEEK());
+yy90:
+       YYDEBUG(90, YYPEEK());
 #line 261 "../wisitoken_grammar.re2c"
        {*id = 9; continue;}
-#line 3249 "../wisitoken_grammar_re2c.c"
-yy113:
-       YYDEBUG(113, YYPEEK());
+#line 3208 "../wisitoken_grammar_re2c.c"
+yy91:
+       YYDEBUG(91, YYPEEK());
        yyaccept = 7;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '-':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '_':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:
-       case 0xE0:
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:
-       case 0xF0:
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:
-       case 0xF4:      goto yy43;
-       default:        goto yy114;
+               case '-':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '_':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF:
+               case 0xE0:
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF:
+               case 0xF0:
+               case 0xF1:
+               case 0xF2:
+               case 0xF3:
+               case 0xF4: goto yy30;
+               default: goto yy92;
        }
-yy114:
-       YYDEBUG(114, YYPEEK());
+yy92:
+       YYDEBUG(92, YYPEEK());
 #line 262 "../wisitoken_grammar.re2c"
        {*id = 10; continue;}
-#line 3378 "../wisitoken_grammar_re2c.c"
-yy115:
-       YYDEBUG(115, YYPEEK());
+#line 3337 "../wisitoken_grammar_re2c.c"
+yy93:
+       YYDEBUG(93, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'y':       goto yy138;
-       default:        goto yy43;
+               case 'y': goto yy114;
+               default: goto yy30;
        }
-yy116:
-       YYDEBUG(116, YYPEEK());
+yy94:
+       YYDEBUG(94, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'n':       goto yy139;
-       default:        goto yy43;
+               case 'n': goto yy115;
+               default: goto yy30;
        }
-yy117:
-       YYDEBUG(117, YYPEEK());
+yy95:
+       YYDEBUG(95, YYPEEK());
        yyaccept = 8;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '-':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '_':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:
-       case 0xE0:
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:
-       case 0xF0:
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:
-       case 0xF4:      goto yy43;
-       default:        goto yy118;
+               case '-':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '_':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF:
+               case 0xE0:
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF:
+               case 0xF0:
+               case 0xF1:
+               case 0xF2:
+               case 0xF3:
+               case 0xF4: goto yy30;
+               default: goto yy96;
        }
-yy118:
-       YYDEBUG(118, YYPEEK());
+yy96:
+       YYDEBUG(96, YYPEEK());
 #line 265 "../wisitoken_grammar.re2c"
        {*id = 13; continue;}
-#line 3527 "../wisitoken_grammar_re2c.c"
-yy119:
-       YYDEBUG(119, YYPEEK());
+#line 3486 "../wisitoken_grammar_re2c.c"
+yy97:
+       YYDEBUG(97, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'k':       goto yy140;
-       default:        goto yy43;
+               case 'k': goto yy116;
+               default: goto yy30;
        }
-yy120:
-       YYDEBUG(120, YYPEEK());
+yy98:
+       YYDEBUG(98, YYPEEK());
        YYSKIP();
-       YYDEBUG(121, YYPEEK());
 #line 274 "../wisitoken_grammar.re2c"
        {*id = 22; continue;}
-#line 3544 "../wisitoken_grammar_re2c.c"
-yy122:
-       YYDEBUG(122, YYPEEK());
+#line 3502 "../wisitoken_grammar_re2c.c"
+yy99:
+       YYDEBUG(99, YYPEEK());
        YYSKIP();
-       YYDEBUG(123, YYPEEK());
 #line 254 "../wisitoken_grammar.re2c"
        {*id = 2; if (lexer->cursor[-1] == 0x0a || (lexer->cursor[-1] == 0x0d 
&& lexer->cursor[-2] == 0x0a)) lexer->line++; continue;}
-#line 3551 "../wisitoken_grammar_re2c.c"
-yy124:
-       YYDEBUG(124, YYPEEK());
+#line 3508 "../wisitoken_grammar_re2c.c"
+yy100:
+       YYDEBUG(100, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy97;
-       default:        goto yy71;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F:
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy76;
+               default: goto yy53;
        }
-yy125:
-       YYDEBUG(125, YYPEEK());
+yy101:
+       YYDEBUG(101, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy124;
-       default:        goto yy71;
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy100;
+               default: goto yy53;
        }
-yy126:
-       YYDEBUG(126, YYPEEK());
+yy102:
+       YYDEBUG(102, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy124;
-       default:        goto yy71;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F:
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy100;
+               default: goto yy53;
        }
-yy127:
-       YYDEBUG(127, YYPEEK());
+yy103:
+       YYDEBUG(103, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy126;
-       default:        goto yy71;
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy102;
+               default: goto yy53;
        }
-yy128:
-       YYDEBUG(128, YYPEEK());
+yy104:
+       YYDEBUG(104, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:
-       case 0x90:
-       case 0x91:
-       case 0x92:
-       case 0x93:
-       case 0x94:
-       case 0x95:
-       case 0x96:
-       case 0x97:
-       case 0x98:
-       case 0x99:
-       case 0x9A:
-       case 0x9B:
-       case 0x9C:
-       case 0x9D:
-       case 0x9E:
-       case 0x9F:
-       case 0xA0:
-       case 0xA1:
-       case 0xA2:
-       case 0xA3:
-       case 0xA4:
-       case 0xA5:
-       case 0xA6:
-       case 0xA7:
-       case 0xA8:
-       case 0xA9:
-       case 0xAA:
-       case 0xAB:
-       case 0xAC:
-       case 0xAD:
-       case 0xAE:
-       case 0xAF:
-       case 0xB0:
-       case 0xB1:
-       case 0xB2:
-       case 0xB3:
-       case 0xB4:
-       case 0xB5:
-       case 0xB6:
-       case 0xB7:
-       case 0xB8:
-       case 0xB9:
-       case 0xBA:
-       case 0xBB:
-       case 0xBC:
-       case 0xBD:
-       case 0xBE:
-       case 0xBF:      goto yy126;
-       default:        goto yy71;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F:
+               case 0x90:
+               case 0x91:
+               case 0x92:
+               case 0x93:
+               case 0x94:
+               case 0x95:
+               case 0x96:
+               case 0x97:
+               case 0x98:
+               case 0x99:
+               case 0x9A:
+               case 0x9B:
+               case 0x9C:
+               case 0x9D:
+               case 0x9E:
+               case 0x9F:
+               case 0xA0:
+               case 0xA1:
+               case 0xA2:
+               case 0xA3:
+               case 0xA4:
+               case 0xA5:
+               case 0xA6:
+               case 0xA7:
+               case 0xA8:
+               case 0xA9:
+               case 0xAA:
+               case 0xAB:
+               case 0xAC:
+               case 0xAD:
+               case 0xAE:
+               case 0xAF:
+               case 0xB0:
+               case 0xB1:
+               case 0xB2:
+               case 0xB3:
+               case 0xB4:
+               case 0xB5:
+               case 0xB6:
+               case 0xB7:
+               case 0xB8:
+               case 0xB9:
+               case 0xBA:
+               case 0xBB:
+               case 0xBC:
+               case 0xBD:
+               case 0xBE:
+               case 0xBF: goto yy102;
+               default: goto yy53;
        }
-yy129:
-       YYDEBUG(129, YYPEEK());
+yy105:
+       YYDEBUG(105, YYPEEK());
        YYSKIP();
        yych = YYPEEK();
        switch (yych) {
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-       case 0x84:
-       case 0x85:
-       case 0x86:
-       case 0x87:
-       case 0x88:
-       case 0x89:
-       case 0x8A:
-       case 0x8B:
-       case 0x8C:
-       case 0x8D:
-       case 0x8E:
-       case 0x8F:      goto yy126;
-       default:        goto yy71;
+               case 0x80:
+               case 0x81:
+               case 0x82:
+               case 0x83:
+               case 0x84:
+               case 0x85:
+               case 0x86:
+               case 0x87:
+               case 0x88:
+               case 0x89:
+               case 0x8A:
+               case 0x8B:
+               case 0x8C:
+               case 0x8D:
+               case 0x8E:
+               case 0x8F: goto yy102;
+               default: goto yy53;
        }
-yy130:
-       YYDEBUG(130, YYPEEK());
+yy106:
+       YYDEBUG(106, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'E':
-       case 'e':       goto yy141;
-       default:        goto yy43;
+               case 'E':
+               case 'e': goto yy117;
+               default: goto yy30;
        }
-yy131:
-       YYDEBUG(131, YYPEEK());
+yy107:
+       YYDEBUG(107, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'U':
-       case 'u':       goto yy142;
-       default:        goto yy43;
+               case 'U':
+               case 'u': goto yy118;
+               default: goto yy30;
        }
-yy132:
-       YYDEBUG(132, YYPEEK());
+yy108:
+       YYDEBUG(108, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'F':
-       case 'f':       goto yy143;
-       default:        goto yy43;
+               case 'F':
+               case 'f': goto yy119;
+               default: goto yy30;
        }
-yy133:
-       YYDEBUG(133, YYPEEK());
+yy109:
+       YYDEBUG(109, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'e':       goto yy144;
-       default:        goto yy43;
+               case 'e': goto yy120;
+               default: goto yy30;
        }
-yy134:
-       YYDEBUG(134, YYPEEK());
+yy110:
+       YYDEBUG(110, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'f':       goto yy146;
-       default:        goto yy43;
+               case 'f': goto yy122;
+               default: goto yy30;
        }
-yy135:
-       YYDEBUG(135, YYPEEK());
+yy111:
+       YYDEBUG(111, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'i':       goto yy147;
-       default:        goto yy43;
+               case 'i': goto yy123;
+               default: goto yy30;
        }
-yy136:
-       YYDEBUG(136, YYPEEK());
+yy112:
+       YYDEBUG(112, YYPEEK());
        yyaccept = 9;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '-':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '_':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:
-       case 0xE0:
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:
-       case 0xF0:
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:
-       case 0xF4:      goto yy43;
-       default:        goto yy137;
+               case '-':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '_':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF:
+               case 0xE0:
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF:
+               case 0xF0:
+               case 0xF1:
+               case 0xF2:
+               case 0xF3:
+               case 0xF4: goto yy30;
+               default: goto yy113;
        }
-yy137:
-       YYDEBUG(137, YYPEEK());
+yy113:
+       YYDEBUG(113, YYPEEK());
 #line 259 "../wisitoken_grammar.re2c"
        {*id = 7; continue;}
-#line 4073 "../wisitoken_grammar_re2c.c"
-yy138:
-       YYDEBUG(138, YYPEEK());
+#line 4030 "../wisitoken_grammar_re2c.c"
+yy114:
+       YYDEBUG(114, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'w':       goto yy148;
-       default:        goto yy43;
+               case 'w': goto yy124;
+               default: goto yy30;
        }
-yy139:
-       YYDEBUG(139, YYPEEK());
+yy115:
+       YYDEBUG(115, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '_':       goto yy149;
-       default:        goto yy43;
+               case '_': goto yy125;
+               default: goto yy30;
        }
-yy140:
-       YYDEBUG(140, YYPEEK());
+yy116:
+       YYDEBUG(116, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'e':       goto yy150;
-       default:        goto yy43;
+               case 'e': goto yy126;
+               default: goto yy30;
        }
-yy141:
-       YYDEBUG(141, YYPEEK());
+yy117:
+       YYDEBUG(117, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'P':
-       case 'p':       goto yy151;
-       default:        goto yy43;
+               case 'P':
+               case 'p': goto yy127;
+               default: goto yy30;
        }
-yy142:
-       YYDEBUG(142, YYPEEK());
+yy118:
+       YYDEBUG(118, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'C':
-       case 'c':       goto yy152;
-       default:        goto yy43;
+               case 'C':
+               case 'c': goto yy128;
+               default: goto yy30;
        }
-yy143:
-       YYDEBUG(143, YYPEEK());
+yy119:
+       YYDEBUG(119, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'T':
-       case 't':       goto yy153;
-       default:        goto yy43;
+               case 'T':
+               case 't': goto yy129;
+               default: goto yy30;
        }
-yy144:
-       YYDEBUG(144, YYPEEK());
+yy120:
+       YYDEBUG(120, YYPEEK());
        yyaccept = 10;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '-':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '_':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:
-       case 0xE0:
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:
-       case 0xF0:
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:
-       case 0xF4:      goto yy43;
-       default:        goto yy145;
+               case '-':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '_':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF:
+               case 0xE0:
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF:
+               case 0xF0:
+               case 0xF1:
+               case 0xF2:
+               case 0xF3:
+               case 0xF4: goto yy30;
+               default: goto yy121;
        }
-yy145:
-       YYDEBUG(145, YYPEEK());
+yy121:
+       YYDEBUG(121, YYPEEK());
 #line 256 "../wisitoken_grammar.re2c"
        {*id = 4; continue;}
-#line 4265 "../wisitoken_grammar_re2c.c"
-yy146:
-       YYDEBUG(146, YYPEEK());
+#line 4222 "../wisitoken_grammar_re2c.c"
+yy122:
+       YYDEBUG(122, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'l':       goto yy155;
-       default:        goto yy43;
+               case 'l': goto yy131;
+               default: goto yy30;
        }
-yy147:
-       YYDEBUG(147, YYPEEK());
+yy123:
+       YYDEBUG(123, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'f':       goto yy156;
-       default:        goto yy43;
+               case 'f': goto yy132;
+               default: goto yy30;
        }
-yy148:
-       YYDEBUG(148, YYPEEK());
+yy124:
+       YYDEBUG(124, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'o':       goto yy158;
-       default:        goto yy43;
+               case 'o': goto yy134;
+               default: goto yy30;
        }
-yy149:
-       YYDEBUG(149, YYPEEK());
+yy125:
+       YYDEBUG(125, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'g':       goto yy159;
-       default:        goto yy43;
+               case 'g': goto yy135;
+               default: goto yy30;
        }
-yy150:
-       YYDEBUG(150, YYPEEK());
+yy126:
+       YYDEBUG(126, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'n':       goto yy160;
-       default:        goto yy43;
+               case 'n': goto yy136;
+               default: goto yy30;
        }
-yy151:
-       YYDEBUG(151, YYPEEK());
+yy127:
+       YYDEBUG(127, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'T':
-       case 't':       goto yy162;
-       default:        goto yy43;
+               case 'T':
+               case 't': goto yy138;
+               default: goto yy30;
        }
-yy152:
-       YYDEBUG(152, YYPEEK());
+yy128:
+       YYDEBUG(128, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'E':
-       case 'e':       goto yy163;
-       default:        goto yy43;
+               case 'E':
+               case 'e': goto yy139;
+               default: goto yy30;
        }
-yy153:
-       YYDEBUG(153, YYPEEK());
+yy129:
+       YYDEBUG(129, YYPEEK());
        yyaccept = 11;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '-':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '_':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:
-       case 0xE0:
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:
-       case 0xF0:
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:
-       case 0xF4:      goto yy43;
-       default:        goto yy154;
+               case '-':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '_':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF:
+               case 0xE0:
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF:
+               case 0xF0:
+               case 0xF1:
+               case 0xF2:
+               case 0xF3:
+               case 0xF4: goto yy30;
+               default: goto yy130;
        }
-yy154:
-       YYDEBUG(154, YYPEEK());
+yy130:
+       YYDEBUG(130, YYPEEK());
 #line 267 "../wisitoken_grammar.re2c"
        {*id = 15; continue;}
-#line 4466 "../wisitoken_grammar_re2c.c"
-yy155:
-       YYDEBUG(155, YYPEEK());
+#line 4423 "../wisitoken_grammar_re2c.c"
+yy131:
+       YYDEBUG(131, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'i':       goto yy165;
-       default:        goto yy43;
+               case 'i': goto yy141;
+               default: goto yy30;
        }
-yy156:
-       YYDEBUG(156, YYPEEK());
+yy132:
+       YYDEBUG(132, YYPEEK());
        yyaccept = 12;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '-':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '_':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:
-       case 0xE0:
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:
-       case 0xF0:
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:
-       case 0xF4:      goto yy43;
-       default:        goto yy157;
+               case '-':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '_':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF:
+               case 0xE0:
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF:
+               case 0xF0:
+               case 0xF1:
+               case 0xF2:
+               case 0xF3:
+               case 0xF4: goto yy30;
+               default: goto yy133;
        }
-yy157:
-       YYDEBUG(157, YYPEEK());
+yy133:
+       YYDEBUG(133, YYPEEK());
 #line 260 "../wisitoken_grammar.re2c"
        {*id = 8; continue;}
-#line 4605 "../wisitoken_grammar_re2c.c"
-yy158:
-       YYDEBUG(158, YYPEEK());
+#line 4562 "../wisitoken_grammar_re2c.c"
+yy134:
+       YYDEBUG(134, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'r':       goto yy166;
-       default:        goto yy43;
+               case 'r': goto yy142;
+               default: goto yy30;
        }
-yy159:
-       YYDEBUG(159, YYPEEK());
+yy135:
+       YYDEBUG(135, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'r':       goto yy167;
-       default:        goto yy43;
+               case 'r': goto yy143;
+               default: goto yy30;
        }
-yy160:
-       YYDEBUG(160, YYPEEK());
+yy136:
+       YYDEBUG(136, YYPEEK());
        yyaccept = 13;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '-':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '_':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:
-       case 0xE0:
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:
-       case 0xF0:
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:
-       case 0xF4:      goto yy43;
-       default:        goto yy161;
+               case '-':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '_':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF:
+               case 0xE0:
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF:
+               case 0xF0:
+               case 0xF1:
+               case 0xF2:
+               case 0xF3:
+               case 0xF4: goto yy30;
+               default: goto yy137;
        }
-yy161:
-       YYDEBUG(161, YYPEEK());
+yy137:
+       YYDEBUG(137, YYPEEK());
 #line 268 "../wisitoken_grammar.re2c"
        {*id = 16; continue;}
-#line 4754 "../wisitoken_grammar_re2c.c"
-yy162:
-       YYDEBUG(162, YYPEEK());
+#line 4711 "../wisitoken_grammar_re2c.c"
+yy138:
+       YYDEBUG(138, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '_':       goto yy168;
-       default:        goto yy43;
+               case '_': goto yy144;
+               default: goto yy30;
        }
-yy163:
-       YYDEBUG(163, YYPEEK());
+yy139:
+       YYDEBUG(139, YYPEEK());
        yyaccept = 14;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '-':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '_':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:
-       case 0xE0:
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:
-       case 0xF0:
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:
-       case 0xF4:      goto yy43;
-       default:        goto yy164;
+               case '-':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '_':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF:
+               case 0xE0:
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF:
+               case 0xF0:
+               case 0xF1:
+               case 0xF2:
+               case 0xF3:
+               case 0xF4: goto yy30;
+               default: goto yy140;
        }
-yy164:
-       YYDEBUG(164, YYPEEK());
+yy140:
+       YYDEBUG(140, YYPEEK());
 #line 266 "../wisitoken_grammar.re2c"
        {*id = 14; continue;}
-#line 4893 "../wisitoken_grammar_re2c.c"
-yy165:
-       YYDEBUG(165, YYPEEK());
+#line 4850 "../wisitoken_grammar_re2c.c"
+yy141:
+       YYDEBUG(141, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'c':       goto yy169;
-       default:        goto yy43;
+               case 'c': goto yy145;
+               default: goto yy30;
        }
-yy166:
-       YYDEBUG(166, YYPEEK());
+yy142:
+       YYDEBUG(142, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'd':       goto yy170;
-       default:        goto yy43;
+               case 'd': goto yy146;
+               default: goto yy30;
        }
-yy167:
-       YYDEBUG(167, YYPEEK());
+yy143:
+       YYDEBUG(143, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'a':       goto yy172;
-       default:        goto yy43;
+               case 'a': goto yy148;
+               default: goto yy30;
        }
-yy168:
-       YYDEBUG(168, YYPEEK());
+yy144:
+       YYDEBUG(144, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'I':
-       case 'i':       goto yy173;
-       default:        goto yy43;
+               case 'I':
+               case 'i': goto yy149;
+               default: goto yy30;
        }
-yy169:
-       YYDEBUG(169, YYPEEK());
+yy145:
+       YYDEBUG(145, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 't':       goto yy174;
-       default:        goto yy43;
+               case 't': goto yy150;
+               default: goto yy30;
        }
-yy170:
-       YYDEBUG(170, YYPEEK());
+yy146:
+       YYDEBUG(146, YYPEEK());
        yyaccept = 15;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '-':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '_':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:
-       case 0xE0:
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:
-       case 0xF0:
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:
-       case 0xF4:      goto yy43;
-       default:        goto yy171;
+               case '-':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '_':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF:
+               case 0xE0:
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF:
+               case 0xF0:
+               case 0xF1:
+               case 0xF2:
+               case 0xF3:
+               case 0xF4: goto yy30;
+               default: goto yy147;
        }
-yy171:
-       YYDEBUG(171, YYPEEK());
+yy147:
+       YYDEBUG(147, YYPEEK());
 #line 263 "../wisitoken_grammar.re2c"
        {*id = 11; continue;}
-#line 5073 "../wisitoken_grammar_re2c.c"
-yy172:
-       YYDEBUG(172, YYPEEK());
+#line 5030 "../wisitoken_grammar_re2c.c"
+yy148:
+       YYDEBUG(148, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'm':       goto yy176;
-       default:        goto yy43;
+               case 'm': goto yy152;
+               default: goto yy30;
        }
-yy173:
-       YYDEBUG(173, YYPEEK());
+yy149:
+       YYDEBUG(149, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'T':
-       case 't':       goto yy177;
-       default:        goto yy43;
+               case 'T':
+               case 't': goto yy153;
+               default: goto yy30;
        }
-yy174:
-       YYDEBUG(174, YYPEEK());
+yy150:
+       YYDEBUG(150, YYPEEK());
        yyaccept = 16;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '-':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:
-       case 0xE0:
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:
-       case 0xF0:
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:
-       case 0xF4:      goto yy43;
-       case '_':       goto yy179;
-       default:        goto yy175;
+               case '-':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF:
+               case 0xE0:
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF:
+               case 0xF0:
+               case 0xF1:
+               case 0xF2:
+               case 0xF3:
+               case 0xF4: goto yy30;
+               case '_': goto yy155;
+               default: goto yy151;
        }
-yy175:
-       YYDEBUG(175, YYPEEK());
+yy151:
+       YYDEBUG(151, YYPEEK());
 #line 257 "../wisitoken_grammar.re2c"
        {*id = 5; continue;}
-#line 5223 "../wisitoken_grammar_re2c.c"
-yy176:
-       YYDEBUG(176, YYPEEK());
+#line 5180 "../wisitoken_grammar_re2c.c"
+yy152:
+       YYDEBUG(152, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'm':       goto yy180;
-       default:        goto yy43;
+               case 'm': goto yy156;
+               default: goto yy30;
        }
-yy177:
-       YYDEBUG(177, YYPEEK());
+yy153:
+       YYDEBUG(153, YYPEEK());
        yyaccept = 17;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '-':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '_':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:
-       case 0xE0:
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:
-       case 0xF0:
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:
-       case 0xF4:      goto yy43;
-       default:        goto yy178;
+               case '-':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '_':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF:
+               case 0xE0:
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF:
+               case 0xF0:
+               case 0xF1:
+               case 0xF2:
+               case 0xF3:
+               case 0xF4: goto yy30;
+               default: goto yy154;
        }
-yy178:
-       YYDEBUG(178, YYPEEK());
+yy154:
+       YYDEBUG(154, YYPEEK());
 #line 255 "../wisitoken_grammar.re2c"
        {*id = 3; continue;}
-#line 5362 "../wisitoken_grammar_re2c.c"
-yy179:
-       YYDEBUG(179, YYPEEK());
+#line 5319 "../wisitoken_grammar_re2c.c"
+yy155:
+       YYDEBUG(155, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'r':       goto yy181;
-       default:        goto yy43;
+               case 'r': goto yy157;
+               default: goto yy30;
        }
-yy180:
-       YYDEBUG(180, YYPEEK());
+yy156:
+       YYDEBUG(156, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'a':       goto yy182;
-       default:        goto yy43;
+               case 'a': goto yy158;
+               default: goto yy30;
        }
-yy181:
-       YYDEBUG(181, YYPEEK());
+yy157:
+       YYDEBUG(157, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'e':       goto yy183;
-       default:        goto yy43;
+               case 'e': goto yy159;
+               default: goto yy30;
        }
-yy182:
-       YYDEBUG(182, YYPEEK());
+yy158:
+       YYDEBUG(158, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'r':       goto yy184;
-       default:        goto yy43;
+               case 'r': goto yy160;
+               default: goto yy30;
        }
-yy183:
-       YYDEBUG(183, YYPEEK());
+yy159:
+       YYDEBUG(159, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 's':       goto yy186;
-       default:        goto yy43;
+               case 's': goto yy162;
+               default: goto yy30;
        }
-yy184:
-       YYDEBUG(184, YYPEEK());
+yy160:
+       YYDEBUG(160, YYPEEK());
        yyaccept = 18;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '-':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '_':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:
-       case 0xE0:
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:
-       case 0xF0:
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:
-       case 0xF4:      goto yy43;
-       default:        goto yy185;
+               case '-':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '_':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF:
+               case 0xE0:
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF:
+               case 0xF0:
+               case 0xF1:
+               case 0xF2:
+               case 0xF3:
+               case 0xF4: goto yy30;
+               default: goto yy161;
        }
-yy185:
-       YYDEBUG(185, YYPEEK());
+yy161:
+       YYDEBUG(161, YYPEEK());
 #line 264 "../wisitoken_grammar.re2c"
        {*id = 12; continue;}
-#line 5541 "../wisitoken_grammar_re2c.c"
-yy186:
-       YYDEBUG(186, YYPEEK());
+#line 5498 "../wisitoken_grammar_re2c.c"
+yy162:
+       YYDEBUG(162, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'o':       goto yy187;
-       default:        goto yy43;
+               case 'o': goto yy163;
+               default: goto yy30;
        }
-yy187:
-       YYDEBUG(187, YYPEEK());
+yy163:
+       YYDEBUG(163, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'l':       goto yy188;
-       default:        goto yy43;
+               case 'l': goto yy164;
+               default: goto yy30;
        }
-yy188:
-       YYDEBUG(188, YYPEEK());
+yy164:
+       YYDEBUG(164, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'u':       goto yy189;
-       default:        goto yy43;
+               case 'u': goto yy165;
+               default: goto yy30;
        }
-yy189:
-       YYDEBUG(189, YYPEEK());
+yy165:
+       YYDEBUG(165, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 't':       goto yy190;
-       default:        goto yy43;
+               case 't': goto yy166;
+               default: goto yy30;
        }
-yy190:
-       YYDEBUG(190, YYPEEK());
+yy166:
+       YYDEBUG(166, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'i':       goto yy191;
-       default:        goto yy43;
+               case 'i': goto yy167;
+               default: goto yy30;
        }
-yy191:
-       YYDEBUG(191, YYPEEK());
+yy167:
+       YYDEBUG(167, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'o':       goto yy192;
-       default:        goto yy43;
+               case 'o': goto yy168;
+               default: goto yy30;
        }
-yy192:
-       YYDEBUG(192, YYPEEK());
+yy168:
+       YYDEBUG(168, YYPEEK());
        yyaccept = 3;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case 'n':       goto yy193;
-       default:        goto yy43;
+               case 'n': goto yy169;
+               default: goto yy30;
        }
-yy193:
-       YYDEBUG(193, YYPEEK());
+yy169:
+       YYDEBUG(169, YYPEEK());
        yyaccept = 19;
        YYSKIP();
        YYBACKUP();
        yych = YYPEEK();
        switch (yych) {
-       case '-':
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-       case 'A':
-       case 'B':
-       case 'C':
-       case 'D':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
-       case 'V':
-       case 'W':
-       case 'X':
-       case 'Y':
-       case 'Z':
-       case '_':
-       case 'a':
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'e':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'i':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'o':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 's':
-       case 't':
-       case 'u':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-       case 0xC2:
-       case 0xC3:
-       case 0xC4:
-       case 0xC5:
-       case 0xC6:
-       case 0xC7:
-       case 0xC8:
-       case 0xC9:
-       case 0xCA:
-       case 0xCB:
-       case 0xCC:
-       case 0xCD:
-       case 0xCE:
-       case 0xCF:
-       case 0xD0:
-       case 0xD1:
-       case 0xD2:
-       case 0xD3:
-       case 0xD4:
-       case 0xD5:
-       case 0xD6:
-       case 0xD7:
-       case 0xD8:
-       case 0xD9:
-       case 0xDA:
-       case 0xDB:
-       case 0xDC:
-       case 0xDD:
-       case 0xDE:
-       case 0xDF:
-       case 0xE0:
-       case 0xE1:
-       case 0xE2:
-       case 0xE3:
-       case 0xE4:
-       case 0xE5:
-       case 0xE6:
-       case 0xE7:
-       case 0xE8:
-       case 0xE9:
-       case 0xEA:
-       case 0xEB:
-       case 0xEC:
-       case 0xED:
-       case 0xEE:
-       case 0xEF:
-       case 0xF0:
-       case 0xF1:
-       case 0xF2:
-       case 0xF3:
-       case 0xF4:      goto yy43;
-       default:        goto yy194;
+               case '-':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+               case 'A':
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'E':
+               case 'F':
+               case 'G':
+               case 'H':
+               case 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+               case 'Q':
+               case 'R':
+               case 'S':
+               case 'T':
+               case 'U':
+               case 'V':
+               case 'W':
+               case 'X':
+               case 'Y':
+               case 'Z':
+               case '_':
+               case 'a':
+               case 'b':
+               case 'c':
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'g':
+               case 'h':
+               case 'i':
+               case 'j':
+               case 'k':
+               case 'l':
+               case 'm':
+               case 'n':
+               case 'o':
+               case 'p':
+               case 'q':
+               case 'r':
+               case 's':
+               case 't':
+               case 'u':
+               case 'v':
+               case 'w':
+               case 'x':
+               case 'y':
+               case 'z':
+               case 0xC2:
+               case 0xC3:
+               case 0xC4:
+               case 0xC5:
+               case 0xC6:
+               case 0xC7:
+               case 0xC8:
+               case 0xC9:
+               case 0xCA:
+               case 0xCB:
+               case 0xCC:
+               case 0xCD:
+               case 0xCE:
+               case 0xCF:
+               case 0xD0:
+               case 0xD1:
+               case 0xD2:
+               case 0xD3:
+               case 0xD4:
+               case 0xD5:
+               case 0xD6:
+               case 0xD7:
+               case 0xD8:
+               case 0xD9:
+               case 0xDA:
+               case 0xDB:
+               case 0xDC:
+               case 0xDD:
+               case 0xDE:
+               case 0xDF:
+               case 0xE0:
+               case 0xE1:
+               case 0xE2:
+               case 0xE3:
+               case 0xE4:
+               case 0xE5:
+               case 0xE6:
+               case 0xE7:
+               case 0xE8:
+               case 0xE9:
+               case 0xEA:
+               case 0xEB:
+               case 0xEC:
+               case 0xED:
+               case 0xEE:
+               case 0xEF:
+               case 0xF0:
+               case 0xF1:
+               case 0xF2:
+               case 0xF3:
+               case 0xF4: goto yy30;
+               default: goto yy170;
        }
-yy194:
-       YYDEBUG(194, YYPEEK());
+yy170:
+       YYDEBUG(170, YYPEEK());
 #line 258 "../wisitoken_grammar.re2c"
        {*id = 6; continue;}
-#line 5740 "../wisitoken_grammar_re2c.c"
+#line 5697 "../wisitoken_grammar_re2c.c"
 }
 #line 297 "../wisitoken_grammar.re2c"
 
diff --git a/wisitoken_grammar_runtime.adb b/wisitoken_grammar_runtime.adb
index 36a68f0a8e..6639f88c1c 100644
--- a/wisitoken_grammar_runtime.adb
+++ b/wisitoken_grammar_runtime.adb
@@ -730,10 +730,6 @@ package body WisiToken_Grammar_Runtime is
                Data.Language_Params.Language_Runtime_Name :=
                  +Get_Text (Data, Tree, Tree.Child (Nonterm, 3), Strip_Quotes 
=> True);
 
-            elsif Kind = "lr1_hash_table_size" then
-               Data.Language_Params.LR1_Hash_Table_Size :=
-                 Positive'Value (Get_Text (Data, Tree, Tree.Child (Nonterm, 
3), Strip_Quotes => True));
-
             elsif Kind = "max_parallel" then
                Data.Max_Parallel := SAL.Base_Peek_Type'Value (Get_Text (Data, 
Tree, Tree.Child (Nonterm, 3)));
 
@@ -813,10 +809,11 @@ package body WisiToken_Grammar_Runtime is
                Data.Language_Params.Use_Language_Runtime := False;
 
             elsif Kind = "no_error_recover" then
-               Data.Language_Params.Error_Recover := False;
+               Data.Language_Params.Error_Recover      := False;
+               Data.Language_Params.Recursion_Strategy := None;
 
             elsif Kind = "partial_recursion" then
-               Data.Language_Params.Partial_Recursion := True;
+               Data.Language_Params.Recursion_Strategy := Partial;
 
             elsif Kind = "start" then
                Data.Language_Params.Start_Token := +Get_Text (Data, Tree, 
Tree.Child (Nonterm, 3));



reply via email to

[Prev in Thread] Current Thread [Next in Thread]