comparison gcc/ada/repinfo-input.adb @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents
children
comparison
equal deleted inserted replaced
131:84e7813d76e9 145:1830386684a0
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- R E P I N F O - I N P U T --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2018-2019, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
17 -- --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
21 -- --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
26 -- --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
29 -- --
30 ------------------------------------------------------------------------------
31
32 with Alloc;
33 with Csets; use Csets;
34 with Hostparm; use Hostparm;
35 with Namet; use Namet;
36 with Output; use Output;
37 with Snames; use Snames;
38 with Table;
39
40 package body Repinfo.Input is
41
42 SSU : constant := 8;
43 -- Value for Storage_Unit, we do not want to get this from TTypes, since
44 -- this introduces problematic dependencies in ASIS, and in any case this
45 -- value is assumed to be 8 for the implementation of the DDA.
46
47 type JSON_Entity_Kind is (JE_Record_Type, JE_Array_Type, JE_Other);
48 -- Kind of an entiy
49
50 type JSON_Entity_Node (Kind : JSON_Entity_Kind := JE_Other) is record
51 Esize : Node_Ref_Or_Val;
52 RM_Size : Node_Ref_Or_Val;
53 case Kind is
54 when JE_Record_Type => Variant : Nat;
55 when JE_Array_Type => Component_Size : Node_Ref_Or_Val;
56 when JE_Other => Dummy : Boolean;
57 end case;
58 end record;
59 pragma Unchecked_Union (JSON_Entity_Node);
60 -- Record to represent an entity
61
62 package JSON_Entity_Table is new Table.Table (
63 Table_Component_Type => JSON_Entity_Node,
64 Table_Index_Type => Nat,
65 Table_Low_Bound => 1,
66 Table_Initial => Alloc.Rep_JSON_Table_Initial,
67 Table_Increment => Alloc.Rep_JSON_Table_Increment,
68 Table_Name => "JSON_Entity_Table");
69 -- Table of entities
70
71 type JSON_Component_Node is record
72 Bit_Offset : Node_Ref_Or_Val;
73 Esize : Node_Ref_Or_Val;
74 end record;
75 -- Record to represent a component
76
77 package JSON_Component_Table is new Table.Table (
78 Table_Component_Type => JSON_Component_Node,
79 Table_Index_Type => Nat,
80 Table_Low_Bound => 1,
81 Table_Initial => Alloc.Rep_JSON_Table_Initial,
82 Table_Increment => Alloc.Rep_JSON_Table_Increment,
83 Table_Name => "JSON_Component_Table");
84 -- Table of components
85
86 type JSON_Variant_Node is record
87 Present : Node_Ref_Or_Val;
88 Variant : Nat;
89 Next : Nat;
90 end record;
91 -- Record to represent a variant
92
93 package JSON_Variant_Table is new Table.Table (
94 Table_Component_Type => JSON_Variant_Node,
95 Table_Index_Type => Nat,
96 Table_Low_Bound => 1,
97 Table_Initial => Alloc.Rep_JSON_Table_Initial,
98 Table_Increment => Alloc.Rep_JSON_Table_Increment,
99 Table_Name => "JSON_Variant_Table");
100 -- Table of variants
101
102 -------------------------------------
103 -- Get_JSON_Component_Bit_Offset --
104 -------------------------------------
105
106 function Get_JSON_Component_Bit_Offset
107 (Name : String;
108 Record_Name : String) return Node_Ref_Or_Val
109 is
110 Namid : constant Valid_Name_Id := Name_Find (Record_Name & '.' & Name);
111 Index : constant Int := Get_Name_Table_Int (Namid);
112
113 begin
114 -- Return No_Uint if no information is available for the component
115
116 if Index = 0 then
117 return No_Uint;
118 end if;
119
120 return JSON_Component_Table.Table (Index).Bit_Offset;
121 end Get_JSON_Component_Bit_Offset;
122
123 -------------------------------
124 -- Get_JSON_Component_Size --
125 -------------------------------
126
127 function Get_JSON_Component_Size (Name : String) return Node_Ref_Or_Val is
128 Namid : constant Valid_Name_Id := Name_Find (Name);
129 Index : constant Int := Get_Name_Table_Int (Namid);
130
131 begin
132 -- Return No_Uint if no information is available for the component
133
134 if Index = 0 then
135 return No_Uint;
136 end if;
137
138 return JSON_Entity_Table.Table (Index).Component_Size;
139 end Get_JSON_Component_Size;
140
141 ----------------------
142 -- Get_JSON_Esize --
143 ----------------------
144
145 function Get_JSON_Esize (Name : String) return Node_Ref_Or_Val is
146 Namid : constant Valid_Name_Id := Name_Find (Name);
147 Index : constant Int := Get_Name_Table_Int (Namid);
148
149 begin
150 -- Return No_Uint if no information is available for the entity
151
152 if Index = 0 then
153 return No_Uint;
154 end if;
155
156 return JSON_Entity_Table.Table (Index).Esize;
157 end Get_JSON_Esize;
158
159 ----------------------
160 -- Get_JSON_Esize --
161 ----------------------
162
163 function Get_JSON_Esize
164 (Name : String;
165 Record_Name : String) return Node_Ref_Or_Val
166 is
167 Namid : constant Valid_Name_Id := Name_Find (Record_Name & '.' & Name);
168 Index : constant Int := Get_Name_Table_Int (Namid);
169
170 begin
171 -- Return No_Uint if no information is available for the entity
172
173 if Index = 0 then
174 return No_Uint;
175 end if;
176
177 return JSON_Component_Table.Table (Index).Esize;
178 end Get_JSON_Esize;
179
180 ------------------------
181 -- Get_JSON_RM_Size --
182 ------------------------
183
184 function Get_JSON_RM_Size (Name : String) return Node_Ref_Or_Val is
185 Namid : constant Valid_Name_Id := Name_Find (Name);
186 Index : constant Int := Get_Name_Table_Int (Namid);
187
188 begin
189 -- Return No_Uint if no information is available for the entity
190
191 if Index = 0 then
192 return No_Uint;
193 end if;
194
195 return JSON_Entity_Table.Table (Index).RM_Size;
196 end Get_JSON_RM_Size;
197
198 -----------------------
199 -- Read_JSON_Stream --
200 -----------------------
201
202 procedure Read_JSON_Stream (Text : Text_Buffer; File_Name : String) is
203
204 type Text_Position is record
205 Index : Text_Ptr := 0;
206 Line : Natural := 0;
207 Column : Natural := 0;
208 end record;
209 -- Record to represent position in the text
210
211 type Token_Kind is
212 (J_NULL,
213 J_TRUE,
214 J_FALSE,
215 J_NUMBER,
216 J_INTEGER,
217 J_STRING,
218 J_ARRAY,
219 J_OBJECT,
220 J_ARRAY_END,
221 J_OBJECT_END,
222 J_COMMA,
223 J_COLON,
224 J_EOF);
225 -- JSON Token kind. Note that in ECMA 404 there is no notion of integer.
226 -- Only numbers are supported. In our implementation we return J_INTEGER
227 -- if there is no decimal part in the number. The semantic is that this
228 -- is a J_NUMBER token that might be represented as an integer. Special
229 -- token J_EOF means that end of stream has been reached.
230
231 function Decode_Integer (Lo, Hi : Text_Ptr) return Uint;
232 -- Decode and return the integer in Text (Lo .. Hi)
233
234 function Decode_Name (Lo, Hi : Text_Ptr) return Valid_Name_Id;
235 -- Decode and return the name in Text (Lo .. Hi)
236
237 function Decode_Symbol (Lo, Hi : Text_Ptr) return TCode;
238 -- Decode and return the expression symbol in Text (Lo .. Hi)
239
240 procedure Error (Msg : String);
241 pragma No_Return (Error);
242 -- Print an error message and raise an exception
243
244 procedure Read_Entity;
245 -- Read an entity
246
247 function Read_Name return Valid_Name_Id;
248 -- Read a name
249
250 function Read_Name_With_Prefix return Valid_Name_Id;
251 -- Read a name and prepend a prefix
252
253 function Read_Number return Uint;
254 -- Read a number
255
256 function Read_Numerical_Expr return Node_Ref_Or_Val;
257 -- Read a numerical expression
258
259 procedure Read_Record;
260 -- Read a record
261
262 function Read_String return Valid_Name_Id;
263 -- Read a string
264
265 procedure Read_Token
266 (Kind : out Token_Kind;
267 Token_Start : out Text_Position;
268 Token_End : out Text_Position);
269 -- Read a token and return it (this is a standard JSON lexer)
270
271 procedure Read_Token_And_Error
272 (TK : Token_Kind;
273 Token_Start : out Text_Position;
274 Token_End : out Text_Position);
275 pragma Inline (Read_Token_And_Error);
276 -- Read a specified token and error out on failure
277
278 function Read_Variant_Part return Nat;
279 -- Read a variant part
280
281 procedure Skip_Value;
282 -- Skip a value
283
284 Pos : Text_Position := (Text'First, 1, 1);
285 -- The current position in the text buffer
286
287 Name_Buffer : Bounded_String (4 * Max_Name_Length);
288 -- The buffer used to build full qualifed names
289
290 Prefix_Len : Natural := 0;
291 -- The length of the prefix present in Name_Buffer
292
293 ----------------------
294 -- Decode_Integer --
295 ----------------------
296
297 function Decode_Integer (Lo, Hi : Text_Ptr) return Uint is
298 Len : constant Nat := Int (Hi) - Int (Lo) + 1;
299
300 begin
301 -- Decode up to 9 characters manually, otherwise call into Uint
302
303 if Len < 10 then
304 declare
305 Val : Int := 0;
306
307 begin
308 for J in Lo .. Hi loop
309 Val := Val * 10
310 + Character'Pos (Text (J)) - Character'Pos ('0');
311 end loop;
312 return UI_From_Int (Val);
313 end;
314
315 else
316 declare
317 Val : Uint := Uint_0;
318
319 begin
320 for J in Lo .. Hi loop
321 Val := Val * 10
322 + Character'Pos (Text (J)) - Character'Pos ('0');
323 end loop;
324 return Val;
325 end;
326 end if;
327 end Decode_Integer;
328
329 -------------------
330 -- Decode_Name --
331 -------------------
332
333 function Decode_Name (Lo, Hi : Text_Ptr) return Valid_Name_Id is
334 begin
335 -- Names are stored in lower case so fold them if need be
336
337 if Is_Upper_Case_Letter (Text (Lo)) then
338 declare
339 S : String (Integer (Lo) .. Integer (Hi));
340
341 begin
342 for J in Lo .. Hi loop
343 S (Integer (J)) := Fold_Lower (Text (J));
344 end loop;
345
346 return Name_Find (S);
347 end;
348
349 else
350 declare
351 S : String (Integer (Lo) .. Integer (Hi));
352 for S'Address use Text (Lo)'Address;
353
354 begin
355 return Name_Find (S);
356 end;
357 end if;
358 end Decode_Name;
359
360 ---------------------
361 -- Decode_Symbol --
362 ---------------------
363
364 function Decode_Symbol (Lo, Hi : Text_Ptr) return TCode is
365
366 function Cmp12 (A, B : Character) return Boolean;
367 pragma Inline (Cmp12);
368 -- Compare Text (Lo + 1 .. Lo + 2) with A & B.
369
370 -------------
371 -- Cmp12 --
372 -------------
373
374 function Cmp12 (A, B : Character) return Boolean is
375 begin
376 return Text (Lo + 1) = A and then Text (Lo + 2) = B;
377 end Cmp12;
378
379 Len : constant Nat := Int (Hi) - Int (Lo) + 1;
380
381 -- Start of processing for Decode_Symbol
382
383 begin
384 case Len is
385 when 1 =>
386 case Text (Lo) is
387 when '+' =>
388 return Plus_Expr;
389 when '-' =>
390 return Minus_Expr; -- or Negate_Expr
391 when '*' =>
392 return Mult_Expr;
393 when '<' =>
394 return Lt_Expr;
395 when '>' =>
396 return Gt_Expr;
397 when '&' =>
398 return Bit_And_Expr;
399 when '#' =>
400 return Discrim_Val;
401 when others =>
402 null;
403 end case;
404 when 2 =>
405 if Text (Lo) = '/' then
406 case Text (Lo + 1) is
407 when 't' =>
408 return Trunc_Div_Expr;
409 when 'c' =>
410 return Ceil_Div_Expr;
411 when 'f' =>
412 return Floor_Div_Expr;
413 when 'e' =>
414 return Exact_Div_Expr;
415 when others =>
416 null;
417 end case;
418 elsif Text (Lo + 1) = '=' then
419 case Text (Lo) is
420 when '<' =>
421 return Le_Expr;
422 when '>' =>
423 return Ge_Expr;
424 when '=' =>
425 return Eq_Expr;
426 when '!' =>
427 return Ne_Expr;
428 when others =>
429 null;
430 end case;
431 elsif Text (Lo) = 'o' and then Text (Lo + 1) = 'r' then
432 return Truth_Or_Expr;
433 end if;
434 when 3 =>
435 case Text (Lo) is
436 when '?' =>
437 if Cmp12 ('<', '>') then
438 return Cond_Expr;
439 end if;
440 when 'a' =>
441 if Cmp12 ('b', 's') then
442 return Abs_Expr;
443 elsif Cmp12 ('n', 'd') then
444 return Truth_And_Expr;
445 end if;
446 when 'm' =>
447 if Cmp12 ('a', 'x') then
448 return Max_Expr;
449 elsif Cmp12 ('i', 'n') then
450 return Min_Expr;
451 end if;
452 when 'n' =>
453 if Cmp12 ('o', 't') then
454 return Truth_Not_Expr;
455 end if;
456 when 'x' =>
457 if Cmp12 ('o', 'r') then
458 return Truth_Xor_Expr;
459 end if;
460 when 'v' =>
461 if Cmp12 ('a', 'r') then
462 return Dynamic_Val;
463 end if;
464 when others =>
465 null;
466 end case;
467 when 4 =>
468 if Text (Lo) = 'm'
469 and then Text (Lo + 1) = 'o'
470 and then Text (Lo + 2) = 'd'
471 then
472 case Text (Lo + 3) is
473 when 't' =>
474 return Trunc_Mod_Expr;
475 when 'c' =>
476 return Ceil_Mod_Expr;
477 when 'f' =>
478 return Floor_Mod_Expr;
479 when others =>
480 null;
481 end case;
482 end if;
483
484 pragma Annotate
485 (CodePeer, Intentional,
486 "condition predetermined", "Error called as defensive code");
487
488 when others =>
489 null;
490 end case;
491
492 Error ("unknown symbol");
493 end Decode_Symbol;
494
495 -----------
496 -- Error --
497 -----------
498
499 procedure Error (Msg : String) is
500 L : constant String := Pos.Line'Img;
501 C : constant String := Pos.Column'Img;
502
503 begin
504 Set_Standard_Error;
505 Write_Eol;
506 Write_Str (File_Name);
507 Write_Char (':');
508 Write_Str (L (L'First + 1 .. L'Last));
509 Write_Char (':');
510 Write_Str (C (C'First + 1 .. C'Last));
511 Write_Char (':');
512 Write_Line (Msg);
513 raise Invalid_JSON_Stream;
514 end Error;
515
516 ------------------
517 -- Read_Entity --
518 ------------------
519
520 procedure Read_Entity is
521 Ent : JSON_Entity_Node;
522 Nam : Name_Id := No_Name;
523 Siz : Node_Ref_Or_Val;
524 Token_Start : Text_Position;
525 Token_End : Text_Position;
526 TK : Token_Kind;
527
528 begin
529 Ent.Esize := No_Uint;
530 Ent.RM_Size := No_Uint;
531 Ent.Component_Size := No_Uint;
532
533 -- Read the members as string : value pairs
534
535 loop
536 case Read_String is
537 when Name_Name =>
538 Nam := Read_Name;
539 when Name_Record =>
540 if Nam = No_Name then
541 Error ("name expected");
542 end if;
543 Ent.Variant := 0;
544 Prefix_Len := Natural (Length_Of_Name (Nam));
545 Name_Buffer.Chars (1 .. Prefix_Len) := Get_Name_String (Nam);
546 Read_Record;
547 when Name_Variant =>
548 Ent.Variant := Read_Variant_Part;
549 when Name_Size =>
550 Siz := Read_Numerical_Expr;
551 Ent.Esize := Siz;
552 Ent.RM_Size := Siz;
553 when Name_Object_Size =>
554 Ent.Esize := Read_Numerical_Expr;
555 when Name_Value_Size =>
556 Ent.RM_Size := Read_Numerical_Expr;
557 when Name_Component_Size =>
558 Ent.Component_Size := Read_Numerical_Expr;
559 when others =>
560 Skip_Value;
561 end case;
562
563 Read_Token (TK, Token_Start, Token_End);
564 if TK = J_OBJECT_END then
565 exit;
566 elsif TK /= J_COMMA then
567 Error ("comma expected");
568 end if;
569 end loop;
570
571 -- Store the entity into the table
572
573 JSON_Entity_Table.Append (Ent);
574
575 -- Associate the name with the entity
576
577 if Nam = No_Name then
578 Error ("name expected");
579 end if;
580
581 Set_Name_Table_Int (Nam, JSON_Entity_Table.Last);
582 end Read_Entity;
583
584 -----------------
585 -- Read_Name --
586 -----------------
587
588 function Read_Name return Valid_Name_Id is
589 Token_Start : Text_Position;
590 Token_End : Text_Position;
591
592 begin
593 -- Read a single string
594
595 Read_Token_And_Error (J_STRING, Token_Start, Token_End);
596
597 return Decode_Name (Token_Start.Index + 1, Token_End.Index - 1);
598 end Read_Name;
599
600 -----------------------------
601 -- Read_Name_With_Prefix --
602 -----------------------------
603
604 function Read_Name_With_Prefix return Valid_Name_Id is
605 Len : Natural;
606 Lo, Hi : Text_Ptr;
607 Token_Start : Text_Position;
608 Token_End : Text_Position;
609
610 begin
611 -- Read a single string
612
613 Read_Token_And_Error (J_STRING, Token_Start, Token_End);
614 Lo := Token_Start.Index + 1;
615 Hi := Token_End.Index - 1;
616
617 -- Prepare for the concatenation with the prefix
618
619 Len := Integer (Hi) - Integer (Lo) + 1;
620 if Prefix_Len + 1 + Len > Name_Buffer.Max_Length then
621 Error ("Name buffer too small");
622 end if;
623
624 Name_Buffer.Length := Prefix_Len + 1 + Len;
625 Name_Buffer.Chars (Prefix_Len + 1) := '.';
626
627 -- Names are stored in lower case so fold them if need be
628
629 if Is_Upper_Case_Letter (Text (Lo)) then
630 for J in Lo .. Hi loop
631 Name_Buffer.Chars (Prefix_Len + 2 + Integer (J - Lo)) :=
632 Fold_Lower (Text (J));
633 end loop;
634
635 else
636 declare
637 S : String (Integer (Lo) .. Integer (Hi));
638 for S'Address use Text (Lo)'Address;
639
640 begin
641 Name_Buffer.Chars (Prefix_Len + 2 .. Prefix_Len + 1 + Len) := S;
642 end;
643 end if;
644
645 return Name_Find (Name_Buffer);
646 end Read_Name_With_Prefix;
647
648 ------------------
649 -- Read_Number --
650 ------------------
651
652 function Read_Number return Uint is
653 Token_Start : Text_Position;
654 Token_End : Text_Position;
655
656 begin
657 -- Only integers are to be expected here
658
659 Read_Token_And_Error (J_INTEGER, Token_Start, Token_End);
660
661 return Decode_Integer (Token_Start.Index, Token_End.Index);
662 end Read_Number;
663
664 --------------------------
665 -- Read_Numerical_Expr --
666 --------------------------
667
668 function Read_Numerical_Expr return Node_Ref_Or_Val is
669 Code : TCode;
670 Nop : Integer;
671 Ops : array (1 .. 3) of Node_Ref_Or_Val;
672 TK : Token_Kind;
673 Token_Start : Text_Position;
674 Token_End : Text_Position;
675
676 begin
677 -- Read either an integer or an expression
678
679 Read_Token (TK, Token_Start, Token_End);
680 if TK = J_INTEGER then
681 return Decode_Integer (Token_Start.Index, Token_End.Index);
682
683 elsif TK = J_OBJECT then
684 -- Read the code of the expression and decode it
685
686 if Read_String /= Name_Code then
687 Error ("name expected");
688 end if;
689
690 Read_Token_And_Error (J_STRING, Token_Start, Token_End);
691 Code := Decode_Symbol (Token_Start.Index + 1, Token_End.Index - 1);
692 Read_Token_And_Error (J_COMMA, Token_Start, Token_End);
693
694 -- Read the array of operands
695
696 if Read_String /= Name_Operands then
697 Error ("operands expected");
698 end if;
699
700 Read_Token_And_Error (J_ARRAY, Token_Start, Token_End);
701
702 Nop := 0;
703 Ops := (others => No_Uint);
704 loop
705 Nop := Nop + 1;
706 Ops (Nop) := Read_Numerical_Expr;
707 Read_Token (TK, Token_Start, Token_End);
708 if TK = J_ARRAY_END then
709 exit;
710 elsif TK /= J_COMMA then
711 Error ("comma expected");
712 end if;
713 end loop;
714
715 Read_Token_And_Error (J_OBJECT_END, Token_Start, Token_End);
716
717 -- Resolve the ambiguity for '-' now
718
719 if Code = Minus_Expr and then Nop = 1 then
720 Code := Negate_Expr;
721 end if;
722
723 return Create_Node (Code, Ops (1), Ops (2), Ops (3));
724
725 else
726 Error ("numerical expression expected");
727 end if;
728 end Read_Numerical_Expr;
729
730 -------------------
731 -- Read_Record --
732 -------------------
733
734 procedure Read_Record is
735 Comp : JSON_Component_Node;
736 First_Bit : Node_Ref_Or_Val := No_Uint;
737 Is_First : Boolean := True;
738 Nam : Name_Id := No_Name;
739 Position : Node_Ref_Or_Val := No_Uint;
740 TK : Token_Kind;
741 Token_Start : Text_Position;
742 Token_End : Text_Position;
743
744 begin
745 -- Read a possibly empty array of components
746
747 Read_Token_And_Error (J_ARRAY, Token_Start, Token_End);
748
749 loop
750 Read_Token (TK, Token_Start, Token_End);
751 if Is_First and then TK = J_ARRAY_END then
752 exit;
753 elsif TK /= J_OBJECT then
754 Error ("object expected");
755 end if;
756
757 -- Read the members as string : value pairs
758
759 loop
760 case Read_String is
761 when Name_Name =>
762 Nam := Read_Name_With_Prefix;
763 when Name_Discriminant =>
764 Skip_Value;
765 when Name_Position =>
766 Position := Read_Numerical_Expr;
767 when Name_First_Bit =>
768 First_Bit := Read_Number;
769 when Name_Size =>
770 Comp.Esize := Read_Numerical_Expr;
771 when others =>
772 Error ("invalid component");
773 end case;
774
775 Read_Token (TK, Token_Start, Token_End);
776 if TK = J_OBJECT_END then
777 exit;
778 elsif TK /= J_COMMA then
779 Error ("comma expected");
780 end if;
781 end loop;
782
783 -- Compute Component_Bit_Offset from Position and First_Bit,
784 -- either symbolically or literally depending on Position.
785
786 if Position = No_Uint or else First_Bit = No_Uint then
787 Error ("bit offset expected");
788 end if;
789
790 if Position < Uint_0 then
791 declare
792 Bit_Position : constant Node_Ref_Or_Val :=
793 Create_Node (Mult_Expr, Position, UI_From_Int (SSU));
794 begin
795 if First_Bit = Uint_0 then
796 Comp.Bit_Offset := Bit_Position;
797 else
798 Comp.Bit_Offset :=
799 Create_Node (Plus_Expr, Bit_Position, First_Bit);
800 end if;
801 end;
802 else
803 Comp.Bit_Offset := Position * SSU + First_Bit;
804 end if;
805
806 -- Store the component into the table
807
808 JSON_Component_Table.Append (Comp);
809
810 -- Associate the name with the component
811
812 if Nam = No_Name then
813 Error ("name expected");
814 end if;
815
816 Set_Name_Table_Int (Nam, JSON_Component_Table.Last);
817
818 Read_Token (TK, Token_Start, Token_End);
819 if TK = J_ARRAY_END then
820 exit;
821 elsif TK /= J_COMMA then
822 Error ("comma expected");
823 end if;
824
825 Is_First := False;
826 end loop;
827 end Read_Record;
828
829 ------------------
830 -- Read_String --
831 ------------------
832
833 function Read_String return Valid_Name_Id is
834 Token_Start : Text_Position;
835 Token_End : Text_Position;
836 Nam : Valid_Name_Id;
837
838 begin
839 -- Read the string and the following colon
840
841 Read_Token_And_Error (J_STRING, Token_Start, Token_End);
842 Nam := Decode_Name (Token_Start.Index + 1, Token_End.Index - 1);
843 Read_Token_And_Error (J_COLON, Token_Start, Token_End);
844
845 return Nam;
846 end Read_String;
847
848 ------------------
849 -- Read_Token --
850 ------------------
851
852 procedure Read_Token
853 (Kind : out Token_Kind;
854 Token_Start : out Text_Position;
855 Token_End : out Text_Position)
856 is
857 procedure Next_Char;
858 -- Update Pos to point to next char
859
860 function Is_Whitespace return Boolean;
861 pragma Inline (Is_Whitespace);
862 -- Return True of current character is a whitespace
863
864 function Is_Structural_Token return Boolean;
865 pragma Inline (Is_Structural_Token);
866 -- Return True if current character is one of the structural tokens
867
868 function Is_Token_Sep return Boolean;
869 pragma Inline (Is_Token_Sep);
870 -- Return True if current character is a token separator
871
872 procedure Delimit_Keyword (Kw : String);
873 -- Helper function to parse tokens such as null, false and true
874
875 ---------------
876 -- Next_Char --
877 ---------------
878
879 procedure Next_Char is
880 begin
881 if Pos.Index > Text'Last then
882 Pos.Column := Pos.Column + 1;
883 elsif Text (Pos.Index) = ASCII.LF then
884 Pos.Column := 1;
885 Pos.Line := Pos.Line + 1;
886 else
887 Pos.Column := Pos.Column + 1;
888 end if;
889 Pos.Index := Pos.Index + 1;
890 end Next_Char;
891
892 -------------------
893 -- Is_Whitespace --
894 -------------------
895
896 function Is_Whitespace return Boolean is
897 begin
898 return
899 Pos.Index <= Text'Last
900 and then
901 (Text (Pos.Index) = ASCII.LF
902 or else
903 Text (Pos.Index) = ASCII.CR
904 or else
905 Text (Pos.Index) = ASCII.HT
906 or else
907 Text (Pos.Index) = ' ');
908 end Is_Whitespace;
909
910 -------------------------
911 -- Is_Structural_Token --
912 -------------------------
913
914 function Is_Structural_Token return Boolean is
915 begin
916 return
917 Pos.Index <= Text'Last
918 and then
919 (Text (Pos.Index) = '['
920 or else
921 Text (Pos.Index) = ']'
922 or else
923 Text (Pos.Index) = '{'
924 or else
925 Text (Pos.Index) = '}'
926 or else
927 Text (Pos.Index) = ','
928 or else
929 Text (Pos.Index) = ':');
930 end Is_Structural_Token;
931
932 ------------------
933 -- Is_Token_Sep --
934 ------------------
935
936 function Is_Token_Sep return Boolean is
937 begin
938 return
939 Pos.Index > Text'Last
940 or else
941 Is_Whitespace
942 or else
943 Is_Structural_Token;
944 end Is_Token_Sep;
945
946 ---------------------
947 -- Delimit_Keyword --
948 ---------------------
949
950 procedure Delimit_Keyword (Kw : String) is
951 pragma Unreferenced (Kw);
952 begin
953 while not Is_Token_Sep loop
954 Token_End := Pos;
955 Next_Char;
956 end loop;
957 end Delimit_Keyword;
958
959 CC : Character;
960 Can_Be_Integer : Boolean := True;
961
962 -- Start of processing for Read_Token
963
964 begin
965 -- Skip leading whitespaces
966
967 while Is_Whitespace loop
968 Next_Char;
969 end loop;
970
971 -- Initialize token delimiters
972
973 Token_Start := Pos;
974 Token_End := Pos;
975
976 -- End of stream reached
977
978 if Pos.Index > Text'Last then
979 Kind := J_EOF;
980 return;
981 end if;
982
983 CC := Text (Pos.Index);
984
985 if CC = '[' then
986 Next_Char;
987 Kind := J_ARRAY;
988 return;
989 elsif CC = ']' then
990 Next_Char;
991 Kind := J_ARRAY_END;
992 return;
993 elsif CC = '{' then
994 Next_Char;
995 Kind := J_OBJECT;
996 return;
997 elsif CC = '}' then
998 Next_Char;
999 Kind := J_OBJECT_END;
1000 return;
1001 elsif CC = ',' then
1002 Next_Char;
1003 Kind := J_COMMA;
1004 return;
1005 elsif CC = ':' then
1006 Next_Char;
1007 Kind := J_COLON;
1008 return;
1009 elsif CC = 'n' then
1010 Delimit_Keyword ("null");
1011 Kind := J_NULL;
1012 return;
1013 elsif CC = 'f' then
1014 Delimit_Keyword ("false");
1015 Kind := J_FALSE;
1016 return;
1017 elsif CC = 't' then
1018 Delimit_Keyword ("true");
1019 Kind := J_TRUE;
1020 return;
1021 elsif CC = '"' then
1022 -- We expect a string
1023 -- Just scan till the end the of the string but do not attempt
1024 -- to decode it. This means that even if we get a string token
1025 -- it might not be a valid string from the ECMA 404 point of
1026 -- view.
1027
1028 Next_Char;
1029 while Pos.Index <= Text'Last and then Text (Pos.Index) /= '"' loop
1030 if Text (Pos.Index) in ASCII.NUL .. ASCII.US then
1031 Error ("control character not allowed in string");
1032 end if;
1033
1034 if Text (Pos.Index) = '\' then
1035 Next_Char;
1036 if Pos.Index > Text'Last then
1037 Error ("non terminated string token");
1038 end if;
1039
1040 case Text (Pos.Index) is
1041 when 'u' =>
1042 for Idx in 1 .. 4 loop
1043 Next_Char;
1044 if Pos.Index > Text'Last
1045 or else (Text (Pos.Index) not in 'a' .. 'f'
1046 and then
1047 Text (Pos.Index) not in 'A' .. 'F'
1048 and then
1049 Text (Pos.Index) not in '0' .. '9')
1050 then
1051 Error ("invalid unicode escape sequence");
1052 end if;
1053 end loop;
1054 when '\' | '/' | '"' | 'b' | 'f' | 'n' | 'r' | 't' =>
1055 null;
1056 when others =>
1057 Error ("invalid escape sequence");
1058 end case;
1059 end if;
1060 Next_Char;
1061 end loop;
1062
1063 -- No quote found report and error
1064
1065 if Pos.Index > Text'Last then
1066 Error ("non terminated string token");
1067 end if;
1068
1069 Token_End := Pos;
1070
1071 -- Go to next char and ensure that this is separator. Indeed
1072 -- construction such as "string1""string2" are not allowed
1073
1074 Next_Char;
1075 if not Is_Token_Sep then
1076 Error ("invalid syntax");
1077 end if;
1078 Kind := J_STRING;
1079 return;
1080 elsif CC = '-' or else CC in '0' .. '9' then
1081 -- We expect a number
1082 if CC = '-' then
1083 Next_Char;
1084 end if;
1085
1086 if Pos.Index > Text'Last then
1087 Error ("invalid number");
1088 end if;
1089
1090 -- Parse integer part of a number. Superfluous leading zeros are
1091 -- not allowed.
1092
1093 if Text (Pos.Index) = '0' then
1094 Token_End := Pos;
1095 Next_Char;
1096 elsif Text (Pos.Index) in '1' .. '9' then
1097 Token_End := Pos;
1098 Next_Char;
1099 while Pos.Index <= Text'Last
1100 and then Text (Pos.Index) in '0' .. '9'
1101 loop
1102 Token_End := Pos;
1103 Next_Char;
1104 end loop;
1105 else
1106 Error ("invalid number");
1107 end if;
1108
1109 if Is_Token_Sep then
1110 -- Valid integer number
1111
1112 Kind := J_INTEGER;
1113 return;
1114 elsif Text (Pos.Index) /= '.'
1115 and then Text (Pos.Index) /= 'e'
1116 and then Text (Pos.Index) /= 'E'
1117 then
1118 Error ("invalid number");
1119 end if;
1120
1121 -- Check for a fractional part
1122
1123 if Text (Pos.Index) = '.' then
1124 Can_Be_Integer := False;
1125 Token_End := Pos;
1126 Next_Char;
1127 if Pos.Index > Text'Last
1128 or else Text (Pos.Index) not in '0' .. '9'
1129 then
1130 Error ("invalid number");
1131 end if;
1132
1133 while Pos.Index <= Text'Last
1134 and then Text (Pos.Index) in '0' .. '9'
1135 loop
1136 Token_End := Pos;
1137 Next_Char;
1138 end loop;
1139
1140 end if;
1141
1142 -- Check for exponent part
1143
1144 if Pos.Index <= Text'Last
1145 and then (Text (Pos.Index) = 'e' or else Text (Pos.Index) = 'E')
1146 then
1147 Token_End := Pos;
1148 Next_Char;
1149 if Pos.Index > Text'Last then
1150 Error ("invalid number");
1151 end if;
1152
1153 if Text (Pos.Index) = '-' then
1154 -- Also a few corner cases can lead to an integer, assume
1155 -- that the number is not an integer.
1156
1157 Can_Be_Integer := False;
1158 end if;
1159
1160 if Text (Pos.Index) = '-' or else Text (Pos.Index) = '+' then
1161 Next_Char;
1162 end if;
1163
1164 if Pos.Index > Text'Last
1165 or else Text (Pos.Index) not in '0' .. '9'
1166 then
1167 Error ("invalid number");
1168 end if;
1169
1170 while Pos.Index <= Text'Last
1171 and then Text (Pos.Index) in '0' .. '9'
1172 loop
1173 Token_End := Pos;
1174 Next_Char;
1175 end loop;
1176 end if;
1177
1178 if Is_Token_Sep then
1179 -- Valid decimal number
1180
1181 if Can_Be_Integer then
1182 Kind := J_INTEGER;
1183 else
1184 Kind := J_NUMBER;
1185 end if;
1186 return;
1187 else
1188 Error ("invalid number");
1189 end if;
1190 elsif CC = EOF then
1191 Kind := J_EOF;
1192 else
1193 Error ("Unexpected character");
1194 end if;
1195 end Read_Token;
1196
1197 ----------------------------
1198 -- Read_Token_And_Error --
1199 ----------------------------
1200
1201 procedure Read_Token_And_Error
1202 (TK : Token_Kind;
1203 Token_Start : out Text_Position;
1204 Token_End : out Text_Position)
1205 is
1206 Kind : Token_Kind;
1207
1208 begin
1209 -- Read a token and errout out if not of the expected kind
1210
1211 Read_Token (Kind, Token_Start, Token_End);
1212 if Kind /= TK then
1213 Error ("specific token expected");
1214 end if;
1215 end Read_Token_And_Error;
1216
1217 -------------------------
1218 -- Read_Variant_Part --
1219 -------------------------
1220
1221 function Read_Variant_Part return Nat is
1222 Next : Nat := 0;
1223 TK : Token_Kind;
1224 Token_Start : Text_Position;
1225 Token_End : Text_Position;
1226 Var : JSON_Variant_Node;
1227
1228 begin
1229 -- Read a non-empty array of components
1230
1231 Read_Token_And_Error (J_ARRAY, Token_Start, Token_End);
1232
1233 loop
1234 Read_Token_And_Error (J_OBJECT, Token_Start, Token_End);
1235
1236 Var.Variant := 0;
1237
1238 -- Read the members as string : value pairs
1239
1240 loop
1241 case Read_String is
1242 when Name_Present =>
1243 Var.Present := Read_Numerical_Expr;
1244 when Name_Record =>
1245 Read_Record;
1246 when Name_Variant =>
1247 Var.Variant := Read_Variant_Part;
1248 when others =>
1249 Error ("invalid variant");
1250 end case;
1251
1252 Read_Token (TK, Token_Start, Token_End);
1253 if TK = J_OBJECT_END then
1254 exit;
1255 elsif TK /= J_COMMA then
1256 Error ("comma expected");
1257 end if;
1258 end loop;
1259
1260 -- Chain the variant and store it into the table
1261
1262 Var.Next := Next;
1263 JSON_Variant_Table.Append (Var);
1264 Next := JSON_Variant_Table.Last;
1265
1266 Read_Token (TK, Token_Start, Token_End);
1267 if TK = J_ARRAY_END then
1268 exit;
1269 elsif TK /= J_COMMA then
1270 Error ("comma expected");
1271 end if;
1272 end loop;
1273
1274 return Next;
1275 end Read_Variant_Part;
1276
1277 ------------------
1278 -- Skip_Value --
1279 ------------------
1280
1281 procedure Skip_Value is
1282 Array_Depth : Natural := 0;
1283 Object_Depth : Natural := 0;
1284 TK : Token_Kind;
1285 Token_Start : Text_Position;
1286 Token_End : Text_Position;
1287
1288 begin
1289 -- Read a value without recursing
1290
1291 loop
1292 Read_Token (TK, Token_Start, Token_End);
1293
1294 case TK is
1295 when J_STRING | J_INTEGER | J_NUMBER =>
1296 null;
1297 when J_ARRAY =>
1298 Array_Depth := Array_Depth + 1;
1299 when J_ARRAY_END =>
1300 Array_Depth := Array_Depth - 1;
1301 when J_OBJECT =>
1302 Object_Depth := Object_Depth + 1;
1303 when J_OBJECT_END =>
1304 Object_Depth := Object_Depth - 1;
1305 when J_COLON | J_COMMA =>
1306 if Array_Depth = 0 and then Object_Depth = 0 then
1307 Error ("value expected");
1308 end if;
1309 when others =>
1310 Error ("value expected");
1311 end case;
1312
1313 exit when Array_Depth = 0 and then Object_Depth = 0;
1314 end loop;
1315 end Skip_Value;
1316
1317 Token_Start : Text_Position;
1318 Token_End : Text_Position;
1319 TK : Token_Kind;
1320 Is_First : Boolean := True;
1321
1322 -- Start of processing for Read_JSON_Stream
1323
1324 begin
1325 -- Read a possibly empty array of entities
1326
1327 Read_Token_And_Error (J_ARRAY, Token_Start, Token_End);
1328
1329 loop
1330 Read_Token (TK, Token_Start, Token_End);
1331 if Is_First and then TK = J_ARRAY_END then
1332 exit;
1333 elsif TK /= J_OBJECT then
1334 Error ("object expected");
1335 end if;
1336
1337 Read_Entity;
1338
1339 Read_Token (TK, Token_Start, Token_End);
1340 if TK = J_ARRAY_END then
1341 exit;
1342 elsif TK /= J_COMMA then
1343 Error ("comma expected");
1344 end if;
1345
1346 Is_First := False;
1347 end loop;
1348 end Read_JSON_Stream;
1349
1350 end Repinfo.Input;