aboutsummaryrefslogtreecommitdiffstats
path: root/src/file_comments.ads
blob: 5357819541311e1a3c6411c60ed616bf74cbac92 (plain)
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
--  Comments table.
--  Copyright (C) 2022 Tristan Gingold
--
--  This program is free software: you can redistribute it and/or modify
--  it under the terms of the GNU General Public License as published by
--  the Free Software Foundation, either version 2 of the License, 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
--  along with this program.  If not, see <gnu.org/licenses>.

with Types; use Types;
with Dyn_Tables;
with Tables;

package File_Comments is
   --  Usage of File_Comments:
   --  There are two parts: the generating part which gather comments and
   --  associate them to nodes, and the user part which allow to get comments
   --  for a node.
   --
   --  The generating part is combined work done by the scanner and the
   --  parser.  The scanner calls Add_Comment on evey comment, and
   --  Comment_Newline on every newlines after a comment.
   --  The parser does the remaining work: it initializes and finishes the
   --  process (calls Comment_Init_Scan and Comment_Close_Scan).
   --  It also associate comments with nodes.
   --
   --  There are two modes of association: block and line.
   --
   --  Line is the simplest mode: it starts by calling Gather_Comments_Line.
   --  First, it associates previous comments to the node, and then if a
   --  comment appear on the same line as the node, all consecutive comments
   --  are associated with the node.  Consecutive comments mean comments
   --  without empty lines.  Another declaration or statement will also
   --  interrupt this association because the comments will be associated
   --  with this new declaration or statement.  After interruption, comments
   --  are not associated anymore; they will be associated by the next
   --  call.  Finally, Gather_Comments_End will simply discard unassociated
   --  comments that appears at an end (or before an 'end').
   --
   --  Block is the default mode.  Gathered but unassociated comments are
   --  simply associated with a node.  The following comments are also
   --  associated with the current node only when an empty line appears.
   --  The block mode is made more complex by the possibility of saving
   --  a range of comments because parsing and scanning needs to be
   --  continued before building a node (eg: to distinguish package
   --  declaration and package instantiation, or to distinguish process and
   --  sensitized process).
   --
   --  Before use, Sort_Comments_By_Node must be called to sort comments.
   --  Then the iterator can be called to get the comments associated to a
   --  node.

   --  To be called at begin/end of scan to initialize the context.
   --  TODO: nested context ?
   procedure Comment_Init_Scan (File : Source_File_Entry);
   procedure Comment_Close_Scan;

   --  Add a comment for FILE.
   --  This procedure is called from a scanner when a comment is scanned.
   --
   --  For a line comment, START is the position of the token that starts the
   --  comment (the '--' in vhdl).  LAST is the position of the last character
   --  of the comment (before the new line).
   --  LINE_START is the start of the current line (to detect comments in
   --  the same line as a node).
   procedure Add_Comment (Start, Last : Source_Ptr;
                          Line_Start : Source_Ptr);

   --  A newline *after a comment* has been scanned.
   --  If this is a blank line, comments before the blank line are attached
   --  to the previous node.
   procedure Comment_Newline (Line_Start : Source_Ptr);

   type Comments_Range is private;

   --  Save comments recently scanned and not yet gathered.
   procedure Save_Comments (Rng : out Comments_Range);

   --  Assign node N to the saved RNG comments.
   --  This procedure is called by the parser when a node that could be
   --  annotated with a comment is parsed.
   procedure Gather_Comments_Block (Rng : Comments_Range;
                                    N : Uns32);
   procedure Gather_Comments_Line (Pos : Source_Ptr;
                                   N : Uns32);

   --  Assign node N to the last comments scanned.
   --  Identical to Save_Comments followed by above Gather_Comments.
   procedure Gather_Comments (N : Uns32);

   --  To be called at the end of a lexical block.
   --  Assign last comments to the block (if any).
   procedure Gather_Comments_End;

   --  Sort comments; to be done once all comments have been gathered and
   --  before searching comments.
   --  Discard unassigned comments ?
   procedure Sort_Comments_By_Node;

   type Comment_Index is new Nat32;
   No_Comment_Index : constant Comment_Index := 0;

   --  Return the first comment index for node N.
   --  Return No_Comment_Index if not found.
   function Find_First_Comment (File : Source_File_Entry; N : Uns32)
                               return Comment_Index;

   --  Return the source bounds of comment IDX.
   procedure Get_Comment (File : Source_File_Entry;
                          Idx : Comment_Index;
                          Start, Last : out Source_Ptr);

   --  Simpler functions for python binding.
   function Get_Comment_Start (File : Source_File_Entry;
                               Idx : Comment_Index) return Source_Ptr;
   function Get_Comment_Last (File : Source_File_Entry;
                              Idx : Comment_Index) return Source_Ptr;

   --  Return the next comment after IDX.
   --  Return No_Comment_Index if no related comment exists.
   function Get_Next_Comment (File : Source_File_Entry;
                              Idx : Comment_Index)
                             return Comment_Index;

   --  For the whole package.
   procedure Initialize;
   procedure Finalize;
private
   type Comments_Range is record
      --  Range of saved comments.
      First, Last : Comment_Index;
   end record;

   type Comment_Record is record
      --  Comment range in the source.
      Start : Source_Ptr;
      Last : Source_Ptr;

      --  Associated node.
      N : Uns32;
   end record;

   type Comment_State is
     (
      --  Keep comments, to be attached.
      --  This is the initial state.
      State_Before,

      --  Comments until the first newline are attached to LAST_NODE.
      State_Block,

      --  If the next comment is on the same line, it will be attached to
      --  LAST_NODE, and so will be the next comments.
      State_Line,

      --  Continuation of line.  Any comment is attached to the LAST_NODE,
      --  until an empty line.
      State_Line_Cont
     );

   type Comment_Context is record
      --  Current file.
      File : Source_File_Entry;

      --  Current state.
      State : Comment_State;

      --  Next unassigned comment.
      Next : Comment_Index;

      Last_Newline : Comment_Index;

      --  Node to attach for next comments.
      Last_Node : Uns32;

      Line_Start : Source_Ptr;
   end record;

   package File_Comments_Tables is new Dyn_Tables
     (Table_Component_Type => Comment_Record,
      Table_Index_Type => Comment_Index,
      Table_Low_Bound => 1);

   subtype File_Comments_Table is File_Comments_Tables.Instance;

   --  Table of comments, indexed by files.
   package Comments_Table is new Tables
     (Table_Component_Type => File_Comments_Table,
      Table_Index_Type => Source_File_Entry,
      Table_Low_Bound => No_Source_File_Entry + 1,
      Table_Initial => 8);
end File_Comments;