emacs_wisi_4.3.2_467a029c/wisi.ads

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
--  Abstract :
--
--  Ada implementation of wisi parser actions.
--
--  References
--
--  [1] wisi-parse-common.el - defines common stuff.
--
--  [2] wisi.texi - defines parse action functions.
--
--  [3] wisi-process-parse.el - defines elisp/process API
--
--  Copyright (C) 2017 - 2023 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
--  Software  Foundation;  either version 3,  or (at your  option) any later
--  version. This library is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN-
--  TABILITY or FITNESS FOR A PARTICULAR PURPOSE.

--  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);

with Ada.Containers.Doubly_Linked_Lists;
with Ada.Containers.Vectors;
with Ada.Strings.Unbounded;
with SAL.Gen_Unbounded_Definite_Red_Black_Trees;
with SAL.Gen_Unbounded_Definite_Vectors;
with SAL.Generic_Decimal_Image;
with WisiToken.Parse;
with WisiToken.Syntax_Trees;
package Wisi is
   use all type WisiToken.Syntax_Trees.Node_Access;
   use all type WisiToken.Line_Region;
   use all type WisiToken.Cache_Version;
   use all type WisiToken.Syntax_Trees.Augmented_Class_Access;
   use all type WisiToken.Base_Buffer_Pos;

   Protocol_Error : exception;

   procedure Skip
     (Source : in     String;
      Last   : in out Integer;
      Char   : in     Character);
   --  Check that Source (Last + 1) = Char. If so, increment Last.
   --  If not, raise Protocol_Error.

   function Get_String
     (Source : in     String;
      Last   : in out Integer)
     return String;
   --  Returns content of quoted string in Source at Last + 1 ... Handles
   --  all '\' escapes by copying them literally into result, while using
   --  them to find the terminating quote.
   --
   --  Raises Protocol_Error for a missing end quote.

   function Get_Enum
     (Source : in     String;
      Last   : in out Integer)
     return String;
   --  Returns next space-delimited word (nominally the value of some
   --  enumeration type) in Source at Last + 1 ...

   function Get_Integer
     (Source : in     String;
      Last   : in out Integer)
     return Integer;

   procedure To_Unix_Line_Endings
     (Source           : in     Ada.Strings.Unbounded.String_Access;
      Source_Byte_Last : in out Integer;
      Source_Char_Last : in out Integer);
   --  Source is assumed to have DOS line endings; convert them to Unix.

   function Image_Action (Action : in WisiToken.Syntax_Trees.Post_Parse_Action) return String;
   --  For Image_Action in Syntax_Trees.Image

   function Elisp_Escape_Quotes (Item : in String) return String;
   --  Prefix any '"' in Item with '\' for elisp.

   type Base_Post_Parse_Action_Type is (Navigate, Face, Indent, None);
   --  Must match first few items in wisi-parse-common.el wisi-post-parse-actions.

   subtype Post_Parse_Action_Type is Base_Post_Parse_Action_Type range Navigate .. Indent;

   type Parse_Data_Type is abstract new WisiToken.Syntax_Trees.User_Data_Type with private;
   type Parse_Data_Access is access all Parse_Data_Type'Class;
   type Parse_Data_Access_Constant is access constant Parse_Data_Type'Class;

   procedure Initialize (Data : in out Parse_Data_Type)
   is null;
   --  Initialize Data before parse.
   --
   --  User should later call Reset_Post_Parse before any post_parse
   --  action.

   procedure Parse_Language_Params
     (Data   : in out Parse_Data_Type;
      Params : in     String)
   is null;
   --  If Params /= "", set all language-specific parameters from Params,
   --  in declaration order; otherwise keep default values. Boolean is
   --  represented by 0 | 1. Parameter values are space delimited.

   procedure Reset_Post_Parse
     (Data                : in out Parse_Data_Type;
      Tree                : in     WisiToken.Syntax_Trees.Tree'Class;
      Post_Parse_Action   : in     Post_Parse_Action_Type;
      Action_Region_Bytes : in     WisiToken.Buffer_Region;
      Action_Region_Chars : in     WisiToken.Buffer_Region;
      Begin_Indent        : in     Integer);
   --  Reset for a new post-parse action.

   function Post_Parse_Action (Data : in Parse_Data_Type) return Post_Parse_Action_Type;
   function Action_Region_Bytes (Data : in Parse_Data_Type) return WisiToken.Buffer_Region;

   overriding
   function Copy_Augmented
     (User_Data : in Parse_Data_Type;
      Augmented : in not null WisiToken.Syntax_Trees.Augmented_Class_Access)
     return WisiToken.Syntax_Trees.Augmented_Class_Access;

   overriding
   procedure Initialize_Actions
     (Data : in out Parse_Data_Type;
      Tree : in     WisiToken.Syntax_Trees.Tree'Class);

   overriding
   procedure Insert_Token
     (Data           : in out Parse_Data_Type;
      Tree           : in out WisiToken.Syntax_Trees.Tree'Class;
      Inserted_Token : in     WisiToken.Syntax_Trees.Valid_Node_Access);

   type Navigate_Class_Type is (Motion, Statement_End, Statement_Override, Statement_Start, Misc);
   --  Matches [1] wisi-class-list.

   type Index_Navigate_Class is record
      Index : WisiToken.Positive_Index_Type; -- into Tokens
      Class : Navigate_Class_Type;
   end record;

   type Statement_Param_Array is array (Natural range <>) of Index_Navigate_Class;

   procedure Statement_Action
     (Data    : in out Parse_Data_Type;
      Tree    : in     WisiToken.Syntax_Trees.Tree;
      Nonterm : in     WisiToken.Syntax_Trees.Valid_Node_Access;
      Params  : in     Statement_Param_Array);
   --  Implements [2] wisi-statement-action.

   procedure Name_Action
     (Data    : in out Parse_Data_Type;
      Tree    : in     WisiToken.Syntax_Trees.Tree;
      Nonterm : in     WisiToken.Syntax_Trees.Valid_Node_Access;
      Name    : in     WisiToken.Positive_Index_Type);
   --  Implements [2] wisi-name-action.

   type Index_ID is record
      Index : WisiToken.Positive_Index_Type; -- into Tokens
      ID    : WisiToken.Token_ID;
      --  If ID is not Invalid_Token_ID, it is the first token in the
      --  nonterm that Index points to that should have a navigate cache for
      --  Motion_Action to link to; an error is reported by Motion_Action if
      --  it does not.
      --
      --  If ID is Invalid_Token_ID, and the token at Index is a
      --  nonterminal, the first token in that nonterminal must have a
      --  navigate cache; Motion_Action silently fails if not.
   end record;

   package Index_ID_Vectors is new Ada.Containers.Vectors (Ada.Containers.Count_Type, Index_ID);

   subtype Motion_Param_Array is Index_ID_Vectors.Vector;

   Invalid_Token_ID : WisiToken.Token_ID := WisiToken.Invalid_Token_ID;
   --  So Create_Parser can just use "Invalid_Token_ID".

   procedure Motion_Action
     (Data    : in out Parse_Data_Type;
      Tree    : in     WisiToken.Syntax_Trees.Tree;
      Nonterm : in     WisiToken.Syntax_Trees.Valid_Node_Access;
      Params  : in     Motion_Param_Array);
   --  Implements [2] wisi-motion-action.

   type Index_Faces is record
      Index       : WisiToken.Positive_Index_Type; -- into Tokens
      Prefix_Face : Integer; -- into grammar.Face_List
      Suffix_Face : Integer; -- into grammar.Face_List
   end record;

   type Face_Apply_Param_Array is array (Natural range <>) of Index_Faces;

   procedure Face_Apply_Action
     (Data    : in out Parse_Data_Type;
      Tree    : in     WisiToken.Syntax_Trees.Tree;
      Nonterm : in     WisiToken.Syntax_Trees.Valid_Node_Access;
      Params  : in     Face_Apply_Param_Array);
   --  Implements [2] wisi-face-apply-action.

   procedure Face_Apply_List_Action
     (Data    : in out Parse_Data_Type;
      Tree    : in     WisiToken.Syntax_Trees.Tree;
      Nonterm : in     WisiToken.Syntax_Trees.Valid_Node_Access;
      Params  : in     Face_Apply_Param_Array);
   --  Implements [2] wisi-face-apply-list-action.

   type Face_Class_Type is (Prefix, Suffix);

   type Index_Face_Class is record
      Index : WisiToken.Positive_Index_Type; -- into Tokens
      Class : Face_Class_Type;
   end record;

   type Face_Mark_Param_Array is array (Natural range <>) of Index_Face_Class;

   procedure Face_Mark_Action
     (Data    : in out Parse_Data_Type;
      Tree    : in     WisiToken.Syntax_Trees.Tree;
      Nonterm : in     WisiToken.Syntax_Trees.Valid_Node_Access;
      Params  : in     Face_Mark_Param_Array);
   --  Implements [2] wisi-face-mark-action.

   type Face_Remove_Param_Array is array (Natural range <>) of WisiToken.Positive_Index_Type;

   procedure Face_Remove_Action
     (Data    : in out Parse_Data_Type;
      Tree    : in     WisiToken.Syntax_Trees.Tree;
      Nonterm : in     WisiToken.Syntax_Trees.Valid_Node_Access;
      Params  : in     Face_Remove_Param_Array);
   --  Implements [2] wisi-face-remove-action.

   ----------
   --  Indent
   --
   --  Indent functions are represented by the Indent_Param type.

   type Simple_Indent_Param_Label is
     --  Not hanging
     (None,
      Int,
      Anchored_0, -- [2] wisi-anchored
      Anchored_1, -- [2] wisi-anchored%
      Block,      -- [2] wisi-block
      Language    -- [2] language-specific function
     );
   subtype Simple_Param_Anchored is Simple_Indent_Param_Label range Anchored_0 .. Anchored_1;

   --  Arguments to language-specific functions are integers; one of
   --  delta, Token_Number, or Token_ID - the syntax does not distinguish
   --  among these three types.

   package Indent_Arg_Arrays is new Ada.Containers.Vectors (WisiToken.Positive_Index_Type, Integer);

   function "+" (Item : in Integer) return Indent_Arg_Arrays.Vector;
   function "&" (List : in Indent_Arg_Arrays.Vector; Item : in Integer) return Indent_Arg_Arrays.Vector;
   function "&" (Left, Right : in Integer) return Indent_Arg_Arrays.Vector;

   type Delta_Type (<>) is private;

   type Indenting_Comment_Label is (None, Leading, Trailing);
   --  None    : indenting code
   --  Leading : comment indent from following token
   --  Trailing: comment indent from preceding token

   type Language_Indent_Function is access function
     (Data              : in out Parse_Data_Type'Class;
      Tree              : in     WisiToken.Syntax_Trees.Tree;
      Nonterm           : in     WisiToken.Syntax_Trees.Valid_Node_Access;
      Tree_Indenting    : in     WisiToken.Syntax_Trees.Valid_Node_Access;
      Indenting_Comment : in     Boolean;
      Args              : in     Indent_Arg_Arrays.Vector)
     return Delta_Type;

   Null_Args : Indent_Arg_Arrays.Vector renames Indent_Arg_Arrays.Empty_Vector;

   type Simple_Indent_Param (Label : Simple_Indent_Param_Label := None) is
   record
      case Label is
      when None =>
         null;

      when Block | Int =>
         Int_Delta : Integer;

      when Simple_Param_Anchored =>
         Anchored_Index : WisiToken.Positive_Index_Type;
         Anchored_Delta : Integer;

      when Language =>
         Function_Ptr : Language_Indent_Function;
         Args         : Indent_Arg_Arrays.Vector;
      end case;
   end record;

   function Image (Item : in Simple_Indent_Param) return String;

   function Add_Simple_Indent_Param (Left, Right : in Simple_Indent_Param) return Simple_Indent_Param;

   type Indent_Param_Label is
     (Simple,
      Hanging_0, -- [2] wisi-hanging
      Hanging_1, -- [2] wisi-hanging%
      Hanging_2  -- [2] wisi-hanging*
     );
   subtype Hanging_Label is Indent_Param_Label range Hanging_0 .. Hanging_2;

   type Indent_Param (Label : Indent_Param_Label := Simple) is
   record
      case Label is
      when Simple =>
         Param : Simple_Indent_Param;

      when Hanging_Label =>
         Hanging_Delta_1 : Simple_Indent_Param;
         Hanging_Delta_2 : Simple_Indent_Param;

      end case;
   end record;

   function Image (Item : in Indent_Param) return String;

   type Indent_Pair (Comment_Present : Boolean := False) is
   record
      Code_Delta : Indent_Param;
      case Comment_Present is
      when True =>
         Comment_Delta : Indent_Param;
      when False =>
         null;
      end case;
   end record;

   function Image (Item : in Indent_Pair) return String;

   type Indent_Param_Array is array (WisiToken.Positive_Index_Type range <>) of Indent_Pair;

   type Indenting is record
      Code : WisiToken.Line_Region := WisiToken.Null_Line_Region;
      --  Lines that need indenting; first token on these lines is contained
      --  in this token. Includes blank and comment lines between
      --  grammar tokens, but excludes trailing blanks and comments after the
      --  last token, so they can be indented differently.

      Comment : WisiToken.Line_Region := WisiToken.Null_Line_Region;
      --  Trailing comment or blank lines (after the last contained grammar
      --  token). Excludes comment following code on a line.
   end record;

   procedure Indent_Action_0
     (Data    : in out Parse_Data_Type'Class;
      Tree    : in     WisiToken.Syntax_Trees.Tree;
      Nonterm : in     WisiToken.Syntax_Trees.Valid_Node_Access;
      Params  : in     Indent_Param_Array);
   --  Implements [2] wisi-indent-action.

   function Indent_Hanging_1
     (Data              : in out Parse_Data_Type;
      Tree              : in     WisiToken.Syntax_Trees.Tree;
      Nonterm           : in     WisiToken.Syntax_Trees.Valid_Node_Access;
      Indenting_Token   : in     WisiToken.Syntax_Trees.Valid_Node_Access;
      Indenting_Comment : in     Boolean;
      Delta_1           : in     Simple_Indent_Param;
      Delta_2           : in     Simple_Indent_Param;
      Label             : in     Hanging_Label)
     return Delta_Type;
   --  Implements [2] wisi-hanging, wisi-hanging%, wisi-hanging*
   --
   --  Language specific child packages may override this to implement
   --  language-specific cases.

   ----------
   --  Other

   type Refactor_Action is range 0 .. Integer'Last;

   function Refactor_Parse  (Data : in Parse_Data_Type; Item : in String) return Refactor_Action;

   procedure Refactor_Help (Data : in Parse_Data_Type) is null;

   procedure Refactor
     (Data       : in out Parse_Data_Type;
      Tree       : in out WisiToken.Syntax_Trees.Tree;
      Action     : in     Refactor_Action;
      Edit_Begin : in     WisiToken.Buffer_Pos) is null;

   type Query_Label is (Node, Containing_Statement, Ancestor, Parent, Child, Print, Dump);
   --  Must match wisi-parse-common.el wisi-parse-tree-queries

   subtype Point_Query is Query_Label range Node .. Ancestor;
   subtype Node_Query is Query_Label range Parent .. Child;

   type Query (Label : Query_Label) is
   record
      case Label is
      when Point_Query =>
         Char_Point : WisiToken.Buffer_Pos;

         case Label is
         when Ancestor =>
            IDs : WisiToken.Token_ID_Arrays.Vector;
         when others =>
            null;
         end case;

      when Parent | Child =>
         Node : WisiToken.Syntax_Trees.Node_Access;
         N    : Positive;

      when Print =>
         null;

      when Dump =>
         File_Name : Ada.Strings.Unbounded.Unbounded_String;
      end case;
   end record;

   function Address_Image (Item : in WisiToken.Syntax_Trees.Valid_Node_Access) return String;
   --  Hexadecimal address of Item, for Query_Tree.

   function To_Node_Access (Item : in String) return WisiToken.Syntax_Trees.Valid_Node_Access;

   function Get_Token_IDs
     (User_Data    : in     Parse_Data_Type;
      Command_Line : in     String;
      Last         : in out Integer)
     return WisiToken.Token_ID_Arrays.Vector
   is abstract;
   --  Read an aggregate of Token_Enum_IDs from Command_Line.
   --
   --  Dispatching on User_Data because Token_Enum_IDs is
   --  language-specific.

   procedure Query_Tree
     (Data  : in Parse_Data_Access_Constant;
      Tree  : in WisiToken.Syntax_Trees.Tree;
      Query : in Wisi.Query);

   type Arg_Index_Array is array (Positive range <>) of WisiToken.Positive_Index_Type;

   procedure Put_Language_Action
     (Data    : in Parse_Data_Type;
      Content : in String);
   --  Send a Language_Action message to Emacs.

   procedure Put (Data : in out Parse_Data_Type; Parser : in WisiToken.Parse.Base_Parser'Class);
   --  Perform additional post-parse actions, then put result to
   --  Ada.Text_IO.Current_Output, as encoded responses as defined in [3]
   --  wisi-process-parse--execute.

   procedure Put_Errors (Tree : in WisiToken.Syntax_Trees.Tree);
   --  Put errors in Tree to Ada.Text_IO.Current_Output,
   --  as encoded error and recover responses as defined in [3]
   --  wisi-process-parse--execute.

   procedure Put_Error
     (Tree        : in WisiToken.Syntax_Trees.Tree;
      Line_Number : in WisiToken.Line_Number_Type;
      Message     : in String);
   --  Put an error elisp form to Ada.Text_IO.Current_Output.

   function Integer_Filled_Image is new SAL.Generic_Decimal_Image (Integer);

private

   type Augmented is new WisiToken.Syntax_Trees.Base_Augmented with
   record
      Cache_Version : WisiToken.Cache_Version := WisiToken.Cache_Version'First;

      Indenting : Wisi.Indenting;
      --  Computed on demand; see Compute_Indenting.
   end record;
   type Augmented_Access is access all Augmented;

   function Get_Augmented
     (Tree : in WisiToken.Syntax_Trees.Tree'Class;
      Node : in WisiToken.Syntax_Trees.Valid_Node_Access)
     return Augmented_Access;
   --  Return Node.Augmented. If that is null, set it to the default
   --  Augmented first.

   type Nil_Buffer_Pos (Set : Boolean := False) is record
      case Set is
      when True =>
         Item : WisiToken.Buffer_Pos;
      when False =>
         null;
      end case;
   end record;

   Nil : constant Nil_Buffer_Pos := (Set => False);

   function Image (Item : in Nil_Buffer_Pos) return String
   is (if Item.Set then Item.Item'Image else " nil");

   type Navigate_Cache_Type is record
      Pos : WisiToken.Buffer_Pos;
      --  Implicit in [1] wisi-cache. This is a character position in the
      --  source text; it must be on a Source_Terminal (not a virtual terminal).

      Statement_ID   : WisiToken.Token_ID;   -- [1] wisi-cache-nonterm
      ID             : WisiToken.Token_ID;   -- [1] wisi-cache-token
      Length         : Natural;              -- [1] wisi-cache-last
      Class          : Navigate_Class_Type;  -- [1] wisi-cache-class
      Containing_Pos : Nil_Buffer_Pos;       -- [1] wisi-cache-containing
      Prev_Pos       : Nil_Buffer_Pos;       -- [1] wisi-cache-prev
      Next_Pos       : Nil_Buffer_Pos;       -- [1] wisi-cache-next
      End_Pos        : Nil_Buffer_Pos;       -- [1] wisi-cache-end
   end record;

   function Key (Cache : in Navigate_Cache_Type) return WisiToken.Buffer_Pos is (Cache.Pos);

   function Key_Compare (Left, Right : in WisiToken.Buffer_Pos) return SAL.Compare_Result is
     (if Left > Right then SAL.Greater
      elsif Left = Right then SAL.Equal
      else SAL.Less);

   package Navigate_Cache_Trees is new SAL.Gen_Unbounded_Definite_Red_Black_Trees
     (Navigate_Cache_Type, WisiToken.Buffer_Pos);

   function Key (Cache : in WisiToken.Buffer_Region) return WisiToken.Buffer_Pos is (Cache.First);

   package Name_Cache_Trees is new SAL.Gen_Unbounded_Definite_Red_Black_Trees
     (WisiToken.Buffer_Region, WisiToken.Buffer_Pos);
   --  Character positions of names.

   type Nil_Integer (Set : Boolean := False) is record
      case Set is
      when True =>
         Item : Integer;
      when False =>
         null;
      end case;
   end record;

   type Face_Cache_Type is record
      Char_Region : WisiToken.Buffer_Region;
      Class       : Face_Class_Type;
      Face        : Nil_Integer; -- not set, or index into *-process-faces-names
   end record;

   function Key (Cache : in Face_Cache_Type) return WisiToken.Buffer_Pos is (Cache.Char_Region.First);

   package Face_Cache_Trees is new SAL.Gen_Unbounded_Definite_Red_Black_Trees (Face_Cache_Type, WisiToken.Buffer_Pos);

   type Indent_Label is (Not_Set, Int, Anchored);

   type Indent_Type (Label : Indent_Label := Not_Set) is record
      --  Indent values may be negative while indents are being computed.

      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 =>
         null;

      when Int =>
         Int_Indent : Integer;

      when Anchored =>
         Anchor_Line  : WisiToken.Line_Number_Type;
         Anchor_Delta : Integer;
      end case;
   end record;

   package Indent_Vectors is new SAL.Gen_Unbounded_Definite_Vectors
     (WisiToken.Line_Number_Type, Indent_Type, Default_Element => (others => <>));
   package Navigate_Cursor_Lists is new Ada.Containers.Doubly_Linked_Lists
     (Navigate_Cache_Trees.Cursor, Navigate_Cache_Trees."=");

   type Parse_Data_Type is abstract new WisiToken.Syntax_Trees.User_Data_Type with
   record
      --  Aux token info
      First_Comment_ID : WisiToken.Token_ID := WisiToken.Invalid_Token_ID;
      Last_Comment_ID  : WisiToken.Token_ID := WisiToken.Invalid_Token_ID;
      Left_Paren_ID    : WisiToken.Token_ID := WisiToken.Invalid_Token_ID;
      Right_Paren_ID   : WisiToken.Token_ID := WisiToken.Invalid_Token_ID;

      Statement_IDs : WisiToken.Token_ID_Arrays.Vector;
      --  Nonterms returned by containing_statement query.

      --  Data for post-parse actions

      Post_Parse_Action   : Post_Parse_Action_Type;
      Action_Region_Bytes : WisiToken.Buffer_Region := WisiToken.Null_Buffer_Region;
      Action_Region_Chars : WisiToken.Buffer_Region := WisiToken.Null_Buffer_Region;
      Action_Region_Lines : WisiToken.Line_Region   := WisiToken.Null_Line_Region;
      --  Actions are applied to tokens that overlap this region.

      Navigate_Caches   : Navigate_Cache_Trees.Tree;  -- Set by Navigate.
      Name_Caches       : Name_Cache_Trees.Tree;      -- Set by Navigate.
      End_Positions     : Navigate_Cursor_Lists.List; -- Dynamic data for Navigate.
      Face_Caches       : Face_Cache_Trees.Tree;      -- Set by Face.
      Indents           : Indent_Vectors.Vector;      -- Set by Indent.
      Begin_Indent      : Integer;                    -- Indentation of line at start of parse.

      --  Copied from language-specific parameters
      Indent_Comment_Col_0 : Boolean := False;

      Augmented_Cache_Version : WisiToken.Cache_Version := WisiToken.Cache_Version'First + 1;
   end record;

   type Simple_Delta_Labels is (None, Int, Anchored);

   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. Invalid when
      --  Label is None, and when Delta is from wisi-block,
      --  ada-indent-aggregate or similar indent function.

      case Label is
      when None =>
         null;

      when Int =>
         Int_Delta : Integer;

      when Anchored =>
         Anchor_Line    : WisiToken.Line_Number_Type;
         Anchored_Delta : Integer;

      end case;
   end record;

   function Image (Item : in Simple_Delta_Type) return String;
   --  For debugging

   type Delta_Labels is (Simple, Hanging);

   type Delta_Type (Label : Delta_Labels := Simple) is
   record
      case Label is
      when Simple =>
         Simple_Delta : Simple_Delta_Type;

      when Hanging =>
         Hanging_First_Line : WisiToken.Line_Number_Type;

         Hanging_Delta_1 : Simple_Delta_Type;
         --  Indentation of first line in token; Null_Delta if first line does
         --  not need indenting

         Hanging_Delta_2 : Simple_Delta_Type; -- indentation of continuation lines
      end case;
   end record;

   Null_Delta : constant Delta_Type := (Simple, (None, WisiToken.Invalid_Line_Number));

   function Image (Item : in Delta_Type) return String;
   --  For debugging

   ----------
   --  Utilities for language-specific child packages

   Emacs_Lisp_New_Line : constant String := "\n";
   --  For includinge New_Line in a text string sent to Emacs.

   function Compute_Indenting
     (Data : in Parse_Data_Type'Class;
      Tree : in WisiToken.Syntax_Trees.Tree;
      Node : in WisiToken.Syntax_Trees.Valid_Node_Access)
     return Wisi.Indenting
   with Pre => Tree.SOI /= Node and Tree.EOI /= Node;
   --  Return Node.Augmented.Indenting, computing it first if needed.

   function Current_Indent_Offset
     (Tree         : in WisiToken.Syntax_Trees.Tree'Class;
      Anchor_Token : in WisiToken.Syntax_Trees.Valid_Node_Access;
      Offset       : in Integer)
     return Integer;
   --  Return offset from beginning of first token on line containing
   --  Anchor_Token, to beginning of Anchor_Token, plus Offset.

   function Get_Text
     (Data       : in Parse_Data_Type;
      Tree       : in WisiToken.Syntax_Trees.Tree;
      Tree_Index : in WisiToken.Syntax_Trees.Valid_Node_Access)
     return String;
   --  Return text contained by Tree_Index token in source file
   --  (lexer.buffer).

   function Indent_Anchored_2
     (Data              : in Parse_Data_Type'Class;
      Tree              : in WisiToken.Syntax_Trees.Tree;
      Anchor_Token      : in WisiToken.Syntax_Trees.Valid_Node_Access;
      Indenting_Token   : in WisiToken.Syntax_Trees.Valid_Node_Access;
      Indenting_Comment : in Boolean;
      Offset            : in Integer)
     return Delta_Type;
   --  If Anchor_Token.Line = Indenting_Token.Line, return Null_Delta. Otherwise
   --  return an anchored delta using Anchor_Token.Line, Offset.

   function Indent_Compute_Delta
     (Data              : in out Parse_Data_Type'Class;
      Tree              : in     WisiToken.Syntax_Trees.Tree;
      Nonterm           : in     WisiToken.Syntax_Trees.Valid_Node_Access;
      Param             : in     Indent_Param;
      Indenting_Token   : in     WisiToken.Syntax_Trees.Valid_Node_Access;
      Indenting_Comment : in     Boolean)
     return Delta_Type;
   --  Return indent defined by Param for Indenting_Token (a child of Nonterm).

   procedure Indent_Token_1
     (Data              : in out Parse_Data_Type;
      Tree              : in     WisiToken.Syntax_Trees.Tree;
      Line_Region       : in     WisiToken.Line_Region;
      Delta_Indent      : in     Delta_Type;
      Indenting_Comment : in     Indenting_Comment_Label;
      Controlling_Delta : in     Delta_Type := Null_Delta);
   --  Apply Delta_Indent to lines in Line_Region.
   --
   --  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 Trailing | Leading. This allows adding previously computed
   --  indents for the token controlling a comment line to the comment
   --  line indent.
   --
   --  Sets Data.Indents, so caller may not be in a renames for a
   --  Data.Indents element.

   --  Visible for language-specific children. Must match list in
   --  [3] wisi-process-parse--execute.
   Navigate_Cache_Code        : constant String := "1";
   Face_Property_Code         : constant String := "2";
   Indent_Code                : constant String := "3";
   Lexer_Error_Code           : constant String := "4";
   Parser_Error_Code          : constant String := "5";
   In_Parse_Action_Error_Code : constant String := "6";
   Recover_Code               : constant String := "7 ";
   End_Code                   : constant String := "8";
   Name_Property_Code         : constant String := "9";
   Edit_Action_Code           : constant String := "10";
   Language_Action_Code       : constant String := "11 "; -- used by wisitoken_grammar for Check_Parens
   Query_Tree_Code            : constant String := "12";
end Wisi;