----------------------------------------------------------------------- -- genentities -- Read JSON entities file and generates Ada specification -- Copyright (C) 2013, 2017, 2021, 2022 Stephane Carrez -- Written by Stephane Carrez (Stephane.Carrez@gmail.com) -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. ----------------------------------------------------------------------- with Ada.Characters.Handling; with Ada.Text_IO; with Ada.Containers.Indefinite_Ordered_Maps; with Util.Serialize.IO.JSON; with Ada.Containers; with Util.Strings; with Util.Beans.Objects; with Util.Beans.Objects.Maps; with Util.Strings.Sets; procedure Genentities is use Ada.Characters.Handling; package UBO renames Util.Beans.Objects; procedure Collect (Name : in String; Item : in UBO.Object); -- Ordered map to generate a table of entity names which is sorted. package Entity_Maps is new Ada.Containers.Indefinite_Ordered_Maps (Key_Type => String, Element_Type => Natural, "<" => "<", "=" => "="); Entities : Entity_Maps.Map; procedure Collect (Name : in String; Item : in UBO.Object) is Codepoints : constant UBO.Object := UBO.Get_Value (Item, "codepoints"); begin if Name (Name'Last) = ';' then Entities.Include (Name (Name'First + 1 .. Name'Last - 1), UBO.To_Integer (UBO.Get_Value (Codepoints, 1))); end if; end Collect; Root : UBO.Object; begin Root := Util.Serialize.IO.JSON.Read ("samples/entities.json"); Util.Beans.Objects.Maps.Iterate (Root, Collect'Access); Ada.Text_IO.Put_Line ("-- Generated by genentities.adb with entities.json"); Ada.Text_IO.Put_Line ("package Entities is"); Ada.Text_IO.New_Line; Ada.Text_IO.Put_Line (" pragma Preelaborate;"); Ada.Text_IO.New_Line; Ada.Text_IO.Put_Line (" type String_Access is access constant String;"); Ada.Text_IO.Put (" type Keyword_Array is array (Positive range 1 .."); Ada.Text_IO.Put (Ada.Containers.Count_Type'Image (Entities.Length)); Ada.Text_IO.Put_Line (") of String_Access;"); Ada.Text_IO.Put (" type Char_Array is array (Positive range 1 .."); Ada.Text_IO.Put (Ada.Containers.Count_Type'Image (Entities.Length)); Ada.Text_IO.Put_Line (") of Wide_Wide_Character;"); Ada.Text_IO.New_Line; -- Step 1: generate the entity name declarations in upper case with _NAME postfix. -- We must append a __ marker on some entity names because some or case sensitive. declare Names : Util.Strings.Sets.Set; Ident : Natural := 0; begin for Entity in Entities.Iterate loop declare Name : constant String := Entity_Maps.Key (Entity); Upper : constant String := To_Upper (Name); begin Ada.Text_IO.Put (" "); Ada.Text_IO.Put (Upper); if Names.Contains (Upper) then Ident := Ident + 1; Ada.Text_IO.Put ("_"); Ada.Text_IO.Put (Util.Strings.Image (Ident)); end if; Ada.Text_IO.Put ("_NAME"); Ada.Text_IO.Set_Col (30); Ada.Text_IO.Put (" : aliased constant String := """); Ada.Text_IO.Put (Name); Ada.Text_IO.Put_Line (""";"); Names.Include (Upper); end; end loop; end; -- Step 2: generate the Keywords table sorted on the entity name. declare Names : Util.Strings.Sets.Set; Ident : Natural := 0; First : Boolean := True; begin Ident := 0; Ada.Text_IO.New_Line; Ada.Text_IO.Put_Line (" Keywords : constant Keyword_Array := ("); for Entity in Entities.Iterate loop declare Name : constant String := Entity_Maps.Key (Entity); Upper : constant String := To_Upper (Name); begin if not First then Ada.Text_IO.Put_Line (","); end if; Ada.Text_IO.Put (" "); Ada.Text_IO.Put (Upper); if Names.Contains (Upper) then Ident := Ident + 1; Ada.Text_IO.Put ("_"); Ada.Text_IO.Put (Util.Strings.Image (Ident)); end if; Ada.Text_IO.Put ("_NAME'Access"); First := False; Names.Include (Upper); end; end loop; Ada.Text_IO.Put_Line (");"); end; -- Step 3: generate the mapping table in the same order as the keyword table. declare First : Boolean := True; begin Ada.Text_IO.New_Line; Ada.Text_IO.Put_Line (" Mapping : constant Char_Array := ("); for Entity in Entities.Iterate loop declare Value : constant Natural := Entity_Maps.Element (Entity); begin if not First then Ada.Text_IO.Put_Line (","); end if; Ada.Text_IO.Put (" Wide_Wide_Character'Val ("); Ada.Text_IO.Put (Util.Strings.Image (Value)); Ada.Text_IO.Put (")"); First := False; end; end loop; Ada.Text_IO.Put_Line (");"); end; Ada.Text_IO.New_Line; Ada.Text_IO.Put_Line ("end Entities;"); end Genentities;