ADA SYNTAX ANALYZER
version 1.0
by Dmitry A. Kazakov

(mailbox@dmitry-kazakov.de)
[Home]

This library 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 library 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 library; if not, write to the Free Software Foundation, Inc., 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.


The current version provides a full Ada 2022 syntax analyzer library. The analyzer parses the source and creates the syntax tree and cross reference of defining identifiers in the source. Both structures are allocated in an arena pool storage and can be released as a whole. The code source can be file, stream or a user-defined container implementing multi-line source interface. Unicode is fully supported as well as Unicode identifiers normalization checks.

      ARM Intel
Download Ada syntax analyzer Platform:   64- 32- 64- 32bit
Arch packages Arch   precompiled and packaged for pacman       [Download page]  
Fedora packages fedora   precompiled and packaged using RPM     [Download page] [Download page] [Download page] [Download page]
CentOS packages CentOS   precompiled and packaged using RPM       [Download page] [Download page]
Debian packages Debian   precompiled and packaged for dpkg   [Download page] [Download page] [Download page] [Download page]
Ubuntu packages Ubuntu      precompiled and packaged for dpkg   [Download page] [Download page] [Download page] [Download page]
Source distribution (any platform)   ada_syntax_analyzer_1_0.tgz (tar + gzip, Windows users may use WinZip)   [Download]

See also changes log.


[TOC][Next]

1. The Ada parser

The package Parsers.Ada_Syntax_Analyzer provides an Ada syntax analyzer:

type Ada_Program
     (  Pool : access Root_Storage_Pool'Class;
        Xref : Cross_Reference_Ptr
     )  is new Ada_Expression with private;

The type is derived from the Ada expression parser from Simple Components. The discriminants are:

The following operations are defined on the type:

function Parse
         (  Context : access Ada_Program;
            Code    : access Source'Class;
            File    :
Source_Description_Ptr
         )  return Tokens.Argument_Token;

This function parses one compilation unit in the source Code and advances the source to the first position following the unit. The result is returned as the topmost node of the syntax tree allocated in the arena pool. The cross-reference Xref if specified is updated with the new defining identifiers declared across the unit and the contexts containing these identifiers. File is the source file description to be used with defining identifiers. It can be null if only one file is used. If multiple files are used the source file description is used to distinguish them in the cross-reference.

The Syntax_Error exception defined in the package Parsers is propagated on syntax errors. Upon an error the source is left at the last parsed position. The syntax error text contains the source primary source location of the error at its end. For example:

'end if' is expected at 18:6..10

The location can be extracted from the text using the function Get_Location. Upon failure the memory pool is cleared. The source can be any descendant of the type Parsers.Multiline_Source.Source_Type. It can be a text file, string, stream or user-defined.

function Get_Trace_File (Context : Ada_Program)
   return
Ada.Text_IO.File_Access;

This function returns the file presently used for tracing. It is null if tracing is inactive.

procedure Set_Trace_File
          (  Context : in out Ada_Program;
             File    : Ada.Text_IO.File_Access := null
          );

This procedure sets the trace file. When null tracing is deactivated.

type Tree_Stub (Context : access Ada_Program'Class) is
   new
Ada.Finalization.Limited_Controlled with private;

An instance of this type marks the pool used by Context. When finalized it frees all memory allocated there since initialization.

[Back][TOC][Next]

1.1. Compilation contexts

The following type is the base type of a context containing defining identifiers (ARM 3.1):

type Compilation_Context is abstract new Declaration_Node with record
   Parent : Context_Location;
   File   : Source_Description_Ptr;
   Scope  : Parsers.Multiline_Source.Location := Empty;
end record;
type Compilation_Context_Ptr is
   access constant
Compilation_Context'Class;;

A compilation context:

The operations to navigate contexts:

function Get_Item
         (  Context : Compilation_Context;
            Index   : Positive
         )  return Declaration_Ptr is abstract;

This function returns the declaration node by its index. Nodes are enumerated starting with 1. Constraint_Error is propagated when Index is wrong.

function Get_Items_Number (Context : Compilation_Context)
   return Natural is abstract;

This function returns the number of declaration nodes in the context.

type Context_Location is record
   Context : Compilation_Context_Ptr;
   After   : Natural := 0;
end record;

Values of this type indicates a declaration item:

function Is_Library_Unit (Context : Context_Location) return Boolean;

This function returns true if Context indicates an item declared in a library unit context.

function Get (Context : Context_Location) return Declaration_Ptr;

This function returns the declaration node specified by Context. Constraint_Error is propagated on errors.

package Context_Location_Sets is
   new
Generic_Set (Context_Location, (null, 0));

This instantiation provides sets of context locations.

function Precedes (Left, Right : Location) return Boolean;

This function orders source locations so that a location precedes another if it indicates a source interval preceding than the later or else contains it.

[Back][TOC][Next]

1.2. Defining identifiers

The defining identifier is declared as follows:

type Named_Term_Ptr is access constant Named_Term'Class;
type Defining_Identifier is record
   Declared : Context_Location;
   Outer    : Program_Node_Ptr;
   Name     : Named_Term_Ptr;
   Term     : Tokens.Argument_Token;
   File     : Source_Description_Ptr;
   Next     : Defining_Identifier_Ptr;
end record;
type Defining_Identifier_Ptr is access constant Defining_Identifier;

This type represents either a defining identifier or a defining symbol:

type Defining_Identifier_Array is
   array
(Positive range <>) of aliased Defining_Identifier;

type Source_Description is abstract tagged null record;
type
Source_Description_Ptr is
   access constant
Source_Description'Class;

The source description can be used with multiple sources to indicate which source the identifier was declared in. The following operations are defined on source descriptions:

Source_Description_Ptr is
   access constant
Source_Description'Class;

The source descriptio

[Back][TOC][Next]

1.3. Cross-reference

type Cross_Reference
     (  Pool : access Root_Storage_Pool'Class
     )  is new Ada.Finalization.Limited_Controlled with private;
type Cross_Reference_Ptr is access all Cross_Reference'Class;

This type represents a cross-reference of the items declared in the parsed units. The discriminant Pool can be the same storage pool as the pool used by the parser. Items added to the reference are allocated after the pool mark. When the parser object is finalized or when the stub is finalized Program_Error is propagated if the items from a still existing cross-reference are deallocated in the result.

The following operations are defined on cross-reference:

function Find
         (  Xref     : Cross_Reference;
            Name     : String;
            Location : Parsers.Multiline_Source.Location;
            File     : Source_Description_Ptr := null
         )  return Context_Location_Sets.Set;

This function searches for the name in the cross-reference Xref. Name is the name to search for. Location is the source location to start at. The result the set of defining identifier locations with the names matching Name. The set contains only identifiers with the visibility scope containing Location in File. The result is a set of potential candidates to resolve Name ignoring the use clauses.

function Get
         (  Xref : Cross_Reference;
            Name : String
         )  return Identifier_Entry;

This function returns the entry corresponding Name. The result is No_Identifier if no entry is found.

function Get
         (  Xref     : Cross_Reference;
            Location : Parsers.Multiline_Source.Location;
            File     : Source_Description_Ptr := null
         )  return Context_Entry;

This function returns the context entry corresponding to the narrowest scope containing Location in File. The result is No_Entry is no such entry exists.

function Get_First
         (  Xref : Cross_Reference
         )  return Identifier_Entry;

This function returns the first identifier entry in the reference. The result is No_Identifier if the reference is empty.

function Get_First
         (  Xref : Cross_Reference
         )  return Context_Entry;

This function returns the first context entry in the reference. The result is No_Context if the reference is empty.

function Get_Last
         (  Xref : Cross_Reference
         )  return Identifier_Entry;

This function returns the last identifier entry in the reference. The result is No_Identifier if the reference is empty.

function Get_Last
         (  Xref : Cross_Reference
         )  return Context_Entry;

This function returns the last context entry in the reference. The result is No_Context if the reference is empty.

[Back][TOC][Next]

1.4. Identifier entries

type Identifier_Entry is private;
No_Identifier : constant Identifier_Entry;

This type represents an entry in the cross-reference corresponding a name. All items in an entry are defining identifiers having this name.

function Get_First (Item : Identifier_Entry)
   return Defining_Identifier_Ptr;

This function returns the first defining identifier in the entry Item. Constraint_Error is propagated if Item is No_Identifier.

function Get_Identifiers_Number (Item : Identifier_Entry)
   return Positive;

This function returns the number of defining identifiers in the entry Item. The result is zero if Item is No_Identifier.

function Get_Last (Item : Identifier_Entry)
   return Defining_Identifier_Ptr;

This function returns the last defining identifiers in the entry Item. Constraint_Error is propagated if Item is No_Identifier.

function Get_Name (Item : Identifier_Entry) return String;

This function returns the name the entry Item corresponds to. Constraint_Error is propagated if Item is No_Identifier.

function Get_Next (Item : Identifier_Entry) return Identifier_Entry;

This function returns the next entry to Item in the cross-reference. The result is No_Identifier if there is none or if Item is No_Identifier.

function Get_Previous (Item : Identifier_Entry) return Identifier_Entry;

This function returns the previous entry to Item in the cross-reference. The result is No_Identifier if there is none or if Item is No_Identifier.

[Back][TOC][Next]

1.5. Context entries

type Context_Entry is private;
No_Context : constant Context_Entry;

This type represents an entry in the cross-reference corresponding a context. That is a declarative region and its scope. Entries are ordered in the textual order of the scopes where context declarations are directly visible. Note the difference between the location of declarations and the scope where these become visible.

function Get_Context (Item : Context_Entry)
   return Compilation_Context_Ptr;

This function returns the context corresponding to the entry Item. Constraint_Error is propagated if Item is No_Context.

function Get_Location (Item : Context_Entry)
   return
Parsers.Multiline_Source.Location;

This function returns the location in the source where context corresponding to entry Item is directly visible. It may or may not include the declaration of the context. For example parameter profile declarations are not visible inside the profile. Constraint_Error is propagated if Item is No_Context. See also Get_Scope which also returns the source description.

function Get_Next (Item : Context_Entry) return Context_Entry;

This function returns the next entry to Item in the cross-reference. The result is No_Identifier if there is none or if Item is No_Context.

function Get_Previous (Item : Context_Entry) return Context_Entry;

This function returns the previous entry to Item in the cross-reference. The result is No_Identifier if there is none or if Item is No_Context.

procedure Get_Scope
          (  Item     : Context_Entry;
            
File     : out Source_Description_Ptr;
             Location : out Parsers.Multiline_Source.Location
          );

This procedure returns the location and source description in the source where context corresponding to the entry Item is directly visible. It may or may not include the declaration of the context. For example parameter profile identifiers are not visible inside the profile itself. Constraint_Error is propagated if Item is No_Context.


[Back][TOC][Next]

2. The syntax tree

The syntax tree nodes are derived from Ada expression nodes:

type Program_Node is abstract new Node with null record;
type Program_Node_Ptr is
   access constant
Program_Node'Class;

A whole compilation unit is a single tree node.

All text internally are kept as Ada strings encoded in UTF-8.

function Get_Class (Item : Program_Node)
   return Program_Node_Class is abstract;

The function returns the enumeration type value corresponding to the program node. It can be used to avoid explicit tag testing:

type Program_Node_Class is
     (  Abort_Statement_Node,
        Accept_Statement_Node,
           ...
        With_Clause_Node
     );

[Back][TOC][Next]

2.1. Declaration nodes

All declaration nodes are descendants of Declaration_Node:

type Declaration_Node is abstract new Program_Node with record
  
Location : Parsers.Multiline_Source.Location;
end record;
type
Declaration_Ptr is access constant Declaration_Node'Class;

This type is the base type of all declaration nodes.

2.1.1. Common declaration types

The child package Parsers.Ada_Syntax_Analyzer.Declarations provides basic types used in declaration nodes.

type Compilation_Context_Type is
     (  Code_Block_Context,
        Generic_Formal_Parameters_Context,
        Library_Unit_Context,
        Package_Interface_Context,
        Package_Private_Context,
        Protected_Interface_Context,
        Protected_Private_Context,
        Protected_Body_Context,
        Record_Component_Context,
        Task_Interface_Context,
        Task_Private_Context
     );

This enumeration type specifies the type of a declaration context::
declare
   <Code_Block_Context>
begin
   ...
end;
          <Library_Unit_Context>
generic
   <Generic_Formal_Parameters_Context>
package P
   <Package_Interface_Context>
private
  
<Package_Private_Context>
end P;
     
protected type P is
  
<Protected_Interface_Context>
private
  
<Protected_Private_Context>
end
P;
  protected body P is
  
<Protected_Body_Context>
end P;
     
type T is record
  
<Record_Component_Context>
end record
;
  task type T is
  
<Task_Interface_Context>
private
  
<Task_Private_Context>
end
P;

function Image (Item : Compilation_Context_Type) return String;

The declaration context node.

type Declaration_Context (Kind_Of : Compilation_Context_Type) is
   new
Compilation_Context with
record

   Declarations    : Declaration_Ptr_Array_Ptr;
   Last_Use_Clause : Use_Clause_Ptr;
end record;
type Declaration_Context_Ptr is access constant Declaration_Context;

The declaration context contains a list of declarations:

type Declaration_Ptr_Array is
   array
(Positive range <>) of Declaration_Ptr;
type Declaration_Ptr_Array_Ptr is
   access constant
Declaration_Ptr_Array;

and the list of use clauses inside:

type Use_Clause is abstract new Context_Clause with record
   Location : Context_Location;
   Previous : Use_Clause_Ptr;
end record;
type Use_Clause_Ptr is access constant Use_Clause'Class;

The use clauses are linked inside the context in order to simplify resolution of names according to visibility.

type Context_Clause (Length : Positive) is
   abstract new
Declaration_Node with
record

   List : Argument_List (1..Length);
end record;

The context clause is the base type of with-, use- and use-type clause nodes. It contains list of nodes each represents a name.

2.1.2. Formal generic parameter nodes

The child package Parsers.Ada_Syntax_Analyzer.Declarations.Formal_Parameters provides declaration of nodes used for generic formal parameters.

type Formal_Parameter is abstract new Declaration_Node with record
   Name : aliased Defining_Identifier;
end record;

This is the base type of all formal parameters. The node types declared in the package:

2.1.3. Specification nodes

The child package Parsers.Ada_Syntax_Analyzer.Declarations.Specifications provides declaration of nodes used for specifications.

type Mode_Type is
     (  Inout_Mode,                    -- in out Sybtype_Mark
        Out_Mode,                      -- out Sybtype_Mark
        In_Mode,                       -- in Sybtype_Mark
        Access_To_All,                 -- access all
        Access_To_Constant,            -- access constant
        Access_To_Variable,            -- access
        Access_To_Procedure,           -- access procedure
        Access_To_Protected_Procedure, -- access protected procedure
        Access_To_Function,            -- access function
        Access_To_Protected_Function,  -- access protected function
        Object_Mode,                   -- Subtype_Indication
        Array_Mode,                    -- array
        Constant_Mode                  -- <number>
     );
subtype Parameter_Mode is Mode_Type
   range Inout_Mode..Access_To_Protected_Function;
subtype Access_Mode is Mode_Type
   range Access_To_All..Access_To_Protected_Function;
subtype Access_To_Mode_Type is Mode_Type
   range Access_To_Constant..Access_To_Variable;
subtype Access_To_Subprogram_Mode is Mode_Type
   range Access_To_Procedure..Access_To_Protected_Function;
subtype Component_Mode is Mode_Type
   range Access_To_All..Object_Mode;
subtype Result_Mode is Mode_Type
   range In_Mode..Access_To_Protected_Function;

The type mode enumeration specifies modes applied to a parameter or component.

type Anonymous_Access_Definition (Mode : Access_Mode) is record
   Not_Null : Boolean;
   case
Mode is
      when
Access_To_All..Access_To_Variable =>
         Object  : Subtype_Indication;
      when
Access_To_Subprogram_Mode =>
         Profile : Parameter_Profile_Ptr;
         case
Mode is
            when
Access_To_Function | Access_To_Protected_Function =>
               Result : Object_Specification_Ptr;
            when others
=>
               null
;
         end case
;
   end case
;
end record
;

This type defines components of an access type. It can be either an access to object or an access to a subprogram.

type Array_Type_Specification
     (  Mode              : Component_Mode;
        Dimension         : Positive;
        Aliased_Component : Boolean
     )  is
record
   Indices : Subtype_Indication_Array (1..Dimension);
   case
Mode is
      when
Access_Mode =>
         Access_Component : Anonymous_Access_Definition (Mode);
      when
Object_Mode =>
         Object_Component : Subtype_Indication;
   end case;
end record;
type
Array_Type_Specification_Ptr is
   access constant
Array_Type_Specification;

This type defines components of an access type. It can be either an access to object or an access to a subprogram.

type Object_Specification (Mode : Mode_Type) is record
   case
Mode is
      when
Object_Mode =>
         Variable     : Subtype_Indication;
      when I
n_Mode | Inout_Mode | Out_Mode =>
         Not_Null     : Boolean;
         Result       : Subtype_Mark;
      when
Access_Mode =>
         Pointer      : Anonymous_Access_Definition (Mode);
      when
Array_Mode =>
         Array_Object : Array_Type_Specification_Ptr;
      when
Constant_Mode =>
         null;
   end case
;
end record
;
type Object_Specification_Ptr is
   access constant
Object_Specification;

This type defines an object, component or result of a subprogram. It can be:

type Parameter_Profile
     (  Parameters_Count : Natural
     )  is new Compilation_Context with
record
   Outer : Program_Node_Ptr;
   List  : Parameter_Specification_Ptr_Array (1..Parameters_Count);
end record
;
type Parameter_Profile_Ptr is access constant Parameter_Profile;

This type defines parameters of a subprogram. The profile is a context since names of parameters are defining identifiers visible in the body of the subprogram.

type Parameter_Specification
     (  Mode              : Parameter_Mode;
        Aliased_Parameter : Boolean;
        Defaulted         : Boolean;
        Length            : Natural;
        Parameters_Count  : Positive;
        Aspects_Count     : Natural
     )  is new Declaration_Node with
record
   Parameters : Defining_Identifier_Array (1..Parameters_Count);
   Profile    : Parameter_Profile_Ptr;
   Aspects    : Aspect_Items_Array (1..Aspects_Count);
   Default    : Optional (Defaulted);
   case Mode is
      when
In_Mode | Inout_Mode | Out_Mode =>
         Not_Null : Boolean;
         Value    : Subtype_Mark;
      when
Access_Mode =>
         Pointer  : Anonymous_Access_Definition (Mode);
   end case
;
end record
;
type Parameter_Specification_Ptr is
   access constant
Parameter_Specification;
type
Parameter_Specification_Ptr_Array is
   array
(Positive range <>) of Parameter_Specification_Ptr;

This type defines parameters in the profile having the same definition like X, Y : Integer.

type Singleton_Parameter is new Compilation_Context with record
   Name    : aliased Defining_Identifier;
   Type_Of : Parameter_Type;
end record
;

Singleton parameter is a context with a single parameter defined, e.g. a loop parameter.

Further nodes are:

2.1.4. Renaming nodes

The child package Parsers.Ada_Syntax_Analyzer.Declarations.Renamings provides declaration of nodes used for renaming Ada entities.

type Abstract_Renaming
     (  Aspects_Count : Natural
     )  is abstract new Declaration_Node with
record

   Name    : aliased Defining_Identifier;
   Target  : Tokens.Argument_Token;
   Aspects : Aspect_Items_Array (1..Aspects_Count);
end record;

This is the base type of all renaming nodes:

2.1.5. Type declaration nodes

The child package Parsers.Ada_Syntax_Analyzer.Declarations.Types provides declaration of nodes used for type declarations.

type Abstract_Type_Declaration
     (  Aspects_Count : Natural
     )  is abstract new Declaration_Node with
record

   Name    : aliased Defining_Identifier;
   Aspects : Aspect_Items_Array (1..Aspects_Count);
end record;

This is the base type of all declaration nodes:

2.1.6. Stub declaration nodes

The child package Parsers.Ada_Syntax_Analyzer.Declarations.Stubs provides declaration of nodes used for stub declarations.

type Abstract_Stub
     (  Aspects_Count : Natural
     )  is abstract new Declaration_Node with
record

   Name    : aliased Defining_Identifier;
   Aspects : Aspect_Items_Array (1..Aspects_Count);
end record;

This is the base type of all stub declaration nodes:

[Back][TOC][Next]

2.2. Body nodes

The child package Parsers.Ada_Syntax_Analyzer.Bodies provides declaration of nodes used bodies.

type Abstract_Body
     (  Declarations  : access constant Declaration_Context;
        Aspects_Count : Natural
     )  is abstract new Declaration_Node with
record

   Name    : aliased Defining_Identifier;
   Aspects : Aspect_Items_Array (1..Aspects_Count);
end record;

This is the base type of all body declaration nodes:

[Back][TOC][Next]

2.3. Statement nodes

The child package Parsers.Ada_Syntax_Analyzer.Statements provides declaration of nodes used bodies.

type Abstract_Statement_Node (Labels_Count : Natural) is abstract
   new
Program_Node with
record

   Location : Parsers.Multiline_Source.Location;
   Path     : Statement_Location;
   Labels   : Defining_Identifier_Array (1..Labels_Count);
end record;
type Statement_Ptr is access constant Abstract_Statement_Node'Class;
type Statement_Ptr_Array is
   array
(Positive range <>) of Statement_Ptr;

This is the base type of all statement nodes. The statement has a location in the source and a location in a statement sequence. The statement also has a list of labels. The labels are located in front of the statement except for a sequence of statements which has labels at its end.

type Statement_Location is record
   Sequence : Statement_Sequence_Ptr;
   Position : Positive;
end record;

The statement location points a sequence and position inside it.

type Statement_Sequence
     (  Labels_Count : Natural;
        Length       : Positive
     )  is new Abstract_Statement_Node (Labels_Count) with
record

   Context : Context_Location;
   Outer   : Program_Node_Ptr;
   List    : Statement_Ptr_Array (1..Length);
end record;
type Statement_Sequence_Ptr is
   access constant
Statement_Sequence'Class;
type Unhandled_Statement_Sequence_Ptr is
   access constant
Statement_Sequence;

A statement sequence is a statement that contains other statements. Context is the location of context in where the sequence is located. Outer is the node that contains the sequence. List is the statements list. For example:

 procedure P is       
   I : Integer;
   A : Float;
  Context  
begin      
   if I < 0 then      
      A := 0.0;         Sequence      Outer (if statement)   
   end if;      
end P;      

type Handled_Statement_Sequence
     (  Labels_Count   : Natural;
        Length         : Positive;
        Handlers_Count : Natural
     )  is new Statement_Sequence
               (  Labels_Count => Labels_Count,
                  Length       => Length
               )  with
record

   Handlers : Exception_Handler_Ptr_Array (1..Handlers_Count);
end record;
type Handled_Statement_Sequence_Ptr is
   access constant
Handled_Statement_Sequence;

A handled statement sequence has exception handlers attached to it.

type Exception_Handler
     (  Has_Parameter : Boolean;
        Choices_Count : Natural
     )  is
record

   Outer    : Handled_Statement_Sequence_Ptr;
   Sequence : Unhandled_Statement_Sequence_Ptr;
   Choices  : Argument_List (1..Choices_Count);
   case Has_Parameter is
      when
True =>
         Parameter : aliased Singleton_Parameter;
      when False =>
         null;
   end case;
end record;
type Exception_Handler_Ptr is access constant Exception_Handler;
type Exception_Handler_Ptr_Array is
   array
(Positive range <>) of Exception_Handler_Ptr;

A handler has a list of choices, sequence of statements and optionally a parameter.

The statement nodes are:

[Back][TOC][Next]

2.4. Tree and cross-reference output

The child package Parsers.Ada_Syntax_Analyzer.Text_IO provides procedures to output the tree and cross-reference.

procedure Put
          (  Tree   : Tokens.Argument_Token;
             Output : File_Type := Standard_Output;
             Prefix : String := "";
             Nested : Nesting := Top
          );
procedure Put
          (  Tree   : Tokens.Argument_Token;
             Name   : String;
             Prefix : String := "";
             Nested : Nesting:= Top
          );

These procedures output the abstract syntax tree. For example, the output of Hello-World procedure:

<library>
   declarations
   |__with at 10:1..13:16
   |  |__Ada.Text_IO at 8:6..16
   |__use at 10:1..13:16
      |__Ada.Text_IO at 8:24..34
procedure Hello_World at 10:1..13:16
begin
|__*() at 12:13..28
   |__Put_Line at 12:4..11
   |__"Hello world!" at 12:14..27

procedure Put_Contexts (File : File_Type; Xref : Cross_Reference);
procedure Put_Contexts (Xref : Cross_Reference);

These procedures output the contexts from the cross-reference. The output contains the list context visibility scopes with the context type, its location and the chain of it parent contexts. For example the cross-reference of this program:

01     --
02     -- ARM 3.10(21-26) Access Types
03     --
04     -- Success: 21:1..39:13 Tree *
05     --
06     -- package body ARM_3_10 is
07     --    type Frame is access Matrix;
08     --    type Peripheral_Ref is not null access Peripheral;
09     --    type Binop_Ptr is access all Binary_Operation'Class;
10     --    subtype Drum_Ref is Peripheral_Ref (Drum);
11     --    type Message_Procedure is access procedure (M : String := "Error!");
12     --    procedure Default_Message_Procedure (M : String);
13     --    Give_Message : Message_Procedure := Default_Message_Procedure'Access;
14     --    procedure Other_Procedure (M : String);
15     -- begin
16     --    Give_Message := Other_Procedure'Access;
17     --    Give_Message ("File not found.");
18     --    Give_Message.all;
19     -- end ARM_3_10;
20     --
21     package body ARM_3_10 is
22        type Frame is access Matrix;  -- see 3.6
23        type Peripheral_Ref is not null access Peripheral;  -- see 3.8.1
24        type Binop_Ptr is access all Binary_Operation'Class;
25                                   -- general access-to-class-wide, see 3.9.1
26        subtype Drum_Ref is Peripheral_Ref(Drum); -- see 3.8.1
27      
28        type Message_Procedure is access procedure (M : in String := "Error!");
29        procedure Default_Message_Procedure(M : in String);
30        Give_Message : Message_Procedure := Default_Message_Procedure'Access;
31      
32        procedure Other_Procedure(M : in String);
33     begin
34        Give_Message := Other_Procedure'Access;
35      
36        Give_Message("File not found.");
37                                 -- call with parameter (.all is optional)
38        Give_Message.all;        -- call with no parameters
39     end ARM_3_10;

looks like::

Scopes         Defining identifiers context
------         ----------------------------
21:1..39:13    library unit context at 21:1 (0 items)
22:4..39:0     declarative part at 22:4..33:0 (8 items)
                  after library unit context at 21:1 (0 items)

There are two contexts. The library unit context with no items declared. The package body is attached to that context. The visibility scope covers all package body. The package body has a declaration context with 8 items declared in it. Its parent context is the library unit context.

procedure Put_Defining_Identifiers
          (  File  : File_Type;
             Xref  : Cross_Reference;
             Field : Output_Length := 50
          );
procedure Put_Defining_Identifiers
          (  Xref  : Cross_Reference;
             Field : Output_Length := 50
          );

These procedures output the list of declared items in the cross-reference. The parameter Field specified the maximum identifier name length. If the name exceeds this limit, it is truncated in the output. For the program above:

Identifier           Locations
----------           ---------
ARM_3_10             21:14..21
Binop_Ptr            24:9..17
Default_M...rocedure 29:14..38
Drum_Ref             26:12..19
Frame                22:9..13
Give_Message         30:4..15
M                    28:48..48, 29:40..40, 32:30..30
Message_Procedure    28:9..25
Other_Procedure      32:14..28
Peripheral_Ref       23:9..22

[Back][TOC][Next]

2.5. Serialization

The child package Parsers.Ada_Syntax_Analyzer.Serialization provides syntax tree serialization. The following subprograms are defined in the package:

procedure Restore
          (  Stream : in out Root_Stream_Type'Class;
             Pool   : in out Root_Storage_Pool'Class;
             Offset : in out Stream_Element_Offset;
             Result : out Tokens.Argument_Token;
             Xref   : Cross_Reference_Ptr    := null;
             File   : Source_Description_Ptr := null;
             Trace  : File_Access            := null;
             Prefix : String                 := ""
          );

This procedure restores a syntax tree from Stream. The tree is allocated in Pool. Offset is incremented by the number of storage elements read. Result is the tree. Xref is the cross-reference to update with the defining identifiers and scopes read. File is the source description to apply to the input. Trace is the trace file. Prefix is the prefix to use with the trace file output. Constraint_Error is propagated on errors.

function Restore
         (  Stream : access Root_Stream_Type'Class;
            Pool   : access Root_Storage_Pool'Class;
            Xref   : Cross_Reference_Ptr    := null;
            File   : Source_Description_Ptr := null;
            Trace  : File_Access            := null;
            Prefix : String                 := ""
         )  return Tokens.Argument_Token;

This function is a variant of the above procedure.

procedure Store
          (  Stream : in out Root_Stream_Type'Class;
             Tree   : Tokens.Argument_Token;
           [ Offset : in out Stream_Element_Offset; ]
             Trace  : File_Access := null;
             Prefix : String      := ""
          );

This procedure stores the syntax tree Tree into Stream. Offset is incremented by the number of storage elements written. Trace is the trace file. Prefix is the prefix to use with the trace file output. Constraint_Error is propagated on errors.


[Back][TOC][Next]

3. Test suite

The test suite is provided for testing the analyzer. The suite is located in the subdirectory ./test_suite. Some of the test sources are:

[Back][TOC][Next]

3.1. The test program

The test suite directory contains the project test_suite.gpr. The arguments of the program is the list of files or directories containing tests. When the keyword trace appears then tracing is enabled for the following arguments. Without file or directory arguments the subdirectory tests is used. The program scans each directory and uses each file as a test. It stops at the first test failed. The program exist code is success only when all tests pass.

[Back][TOC][Next]

3.2. The syntax of a test file

The test is a source of an Ada program that may consist of several compilation units. The source starts with a comment. The comment specifies the required outcome.

3.2.1. Success tests

A succes test contains the keyword Success followed by colon. For example:

01     --
02     -- Description: Hello world test
03     --
04     -- Success: 10:1..13:16 Tree *
05     --
06     -- with Ada.Text_IO; use Ada.Text_IO; procedure Hello_World is begin Put_Line ("Hello world!"); end Hello_World;
07     --
08     with Ada.Text_IO; use Ada.Text_IO;
09      
10     procedure Hello_World is
11     begin
12        Put_Line ("Hello world!");
13     end Hello_World;

The keyword Success is followed by a comma-separated list of excepted locations. For each unit in the test there is one item in the list. Then the following optional elements may follow:

A cross-reference check starts with the keyword find. The has the syntax

<check>      ::= find <name> at <location> = <places-set> | empty
<places-set> ::= <place> [,<places-set>]
<place>      ::= <location>(<position>)

The set of places specifies the list of locations where an identifier matching the specified one is declared. The position is one of the declaration. The check is made against the function Find. For example:

01     --
02     -- Object orientation https://en.wikibooks.org/wiki/Ada_Programming/Object_Orientation
03     --
04     -- Success: 26:1..37:15 find Object           at 27:9..14  = empty
05     --                      find Class_Member_1   at 35:14..27 = 27:4..37:0(2)
06     --                      find New_Class_Member at 37:0      = 27:4..37:0(3)
07     --                      find Skilled_In       at 31:23..35 = empty
08     --                      find Skilled_In       at 32:1..1   = 31:1..32:6(1)
09     --                      find Programmer       at 27:1      = 25:1..26:0(2)
10     --
11     --  with Person;
12     --  package Programmer is
13     --     type Object is new Person.Object
14     --                    and Printable.Object
15     --     with
16     --        record
17     --           Skilled_In : Language_List;
18     --        end record;
19     --     overriding
20     --     procedure Class_Member_1   (This : Object);
21     --     not overriding
22     --     procedure New_Class_Member (This : Object; That : String);
23     --  end Programmer;
24     --
25     with Person;
26     package Programmer is
27        type Object is new Person.Object
28                       and Printable.Object
29        with
30           record
31              Skilled_In : Language_List;
32           end record;
33        overriding
34        procedure Class_Member_1   (This : in Object);
35        not overriding
36        procedure New_Class_Member (This : Object; That : String);
37     end Programmer;

If ! appears before Success the test is the last test to run.

3.2.2. Failure tests

A test for invalid program contains the keyword Failure followed by colon. The expected error message is specified on the same line. For example:

01     --
02     -- ACATS B55A01V
03     --
04     -- Failure: Expression is expected at 12:20
05     --
06     PROCEDURE B55A01V IS
07      
08          VBF : BOOLEAN := FALSE;
09      
10     BEGIN
11      
12          WHILE VBF LOOP;     -- ERROR: ';'.
13               NULL;
14          END LOOP;
15      
16     END B55A01V;

If ! appears before Failure the test is the last test to run.


[Back][TOC][Next]

4. Changes log

The following versions were tested with the compilers:

First release 1.0


[Back][TOC]

5. Table of Contents

1 The Ada parser
    1.1. Compilation contexts
    1.2. Defining identifiers
    1.3. Cross-reference
    1.4. Identifier entries
    1.5. Context_Entries

2 The syntax tree
    2.1. Declaration nodes
       2.1.1.Common declaration types
       2.1.2.Formal generic parameter nodes
       2.1.3.Specification nodes
       2.1.4.Renaming nodes
       2.1.5.Type declaration nodes
       2.1.6.Stub declaration nodes
    2.2. Body nodes
    2.3. Statement nodes
    2.4. Tree and cross-reference nodes
    2.5. Serialization
3 Test suite
    3.1. The test program
    3.2. The syntax of a test file
       3.2.1. Success test
       3.2.2. Failure test
4 Changes log

5 Table of contents