1--  EDIF parser.
2--  Copyright (C) 2019 Tristan Gingold
3--
4--  This program is free software: you can redistribute it and/or modify
5--  it under the terms of the GNU General Public License as published by
6--  the Free Software Foundation, either version 2 of the License, or
7--  (at your option) any later version.
8--
9--  This program is distributed in the hope that it will be useful,
10--  but WITHOUT ANY WARRANTY; without even the implied warranty of
11--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12--  GNU General Public License for more details.
13--
14--  You should have received a copy of the GNU General Public License
15--  along with this program.  If not, see <gnu.org/licenses>.
16
17with Types; use Types;
18with Std_Names; use Std_Names;
19with Errorout; use Errorout;
20with Edif.Tokens; use Edif.Tokens;
21with Edif.Scans; use Edif.Scans;
22with Edif.Nutils; use Edif.Nutils;
23
24package body Edif.Parse is
25   Parse_Error : exception;
26
27   procedure Error_Msg_Parse (Msg : String; Args : Earg_Arr := No_Eargs) is
28   begin
29      Report_Msg (Msgid_Error, Errorout.Parse, +Get_Token_Location, Msg, Args);
30   end Error_Msg_Parse;
31
32   procedure Error_Msg_Parse (Msg : String; Arg : Earg_Type) is
33   begin
34      Report_Msg (Msgid_Error, Errorout.Parse, +Get_Token_Location,
35                  Msg, (1 => Arg));
36   end Error_Msg_Parse;
37
38   procedure Set_Token_Location (N : Node) is
39   begin
40      Set_Location (N, Get_Token_Location);
41   end Set_Token_Location;
42
43   function Parse_Simple return Node;
44
45   procedure Parse_Simple_List_Body (Bod : Node)
46   is
47      Last : Node;
48      El : Node;
49   begin
50      Last := Bod;
51      while Current_Token /= Tok_Right_Paren loop
52         if Current_Token = Tok_Eof then
53            Error_Msg_Parse ("missing ')'");
54            exit;
55         end if;
56         El := Create_Node (N_Chain);
57         Set_Token_Location (El);
58         Set_CDR (Last, El);
59         Set_CAR (El, Parse_Simple);
60         Last := El;
61      end loop;
62
63      Set_CDR (Last, Null_Node);
64
65      if Current_Token = Tok_Right_Paren then
66         --  Skip ')'.
67         Scan;
68      end if;
69   end Parse_Simple_List_Body;
70
71   function Parse_Simple_List return Node
72   is
73      Res : Node;
74   begin
75      Res := Create_Node (N_Keyword);
76      Set_Token_Location (Res);
77
78      Set_Keyword (Res, Current_Identifier);
79
80      --  Skip '(' + keyword.
81      Scan;
82
83      Parse_Simple_List_Body (Res);
84
85      return Res;
86   end Parse_Simple_List;
87
88   function Parse_Symbol return Node
89   is
90      Res : Node;
91   begin
92      pragma Assert (Current_Token = Tok_Symbol);
93
94      Res := Create_Node (N_Symbol);
95      Set_Token_Location (Res);
96      Set_Symbol (Res, Current_Identifier);
97
98      --  Skip symbol.
99      Scan;
100
101      return Res;
102   end Parse_Symbol;
103
104   function Parse_String return Node
105   is
106      Res : Node;
107   begin
108      Res := Create_Node (N_String);
109      Set_Token_Location (Res);
110      Set_String_Id (Res, Current_String);
111      Set_String_Len (Res, Current_String_Len);
112
113      --  Skip string.
114      Scan;
115
116      return Res;
117   end Parse_String;
118
119   function Parse_Number return Node
120   is
121      Res : Node;
122   begin
123      Res := Create_Node (N_Number);
124      Set_Token_Location (Res);
125      Set_Number (Res, Current_Number);
126
127      --  Skip number.
128      Scan;
129
130      return Res;
131   end Parse_Number;
132
133   function Parse_Simple return Node is
134   begin
135      case Current_Token is
136         when Tok_Keyword =>
137            return Parse_Simple_List;
138
139         when Tok_Right_Paren =>
140            Error_Msg_Parse ("unexpected ')'");
141
142            --  Skip it.
143            Scan;
144
145            return Parse_Simple;
146
147         when Tok_Eof =>
148            Error_Msg_Parse ("unexpected end of file");
149            return Null_Node;
150
151         when Tok_Symbol =>
152            return Parse_Symbol;
153
154         when Tok_String =>
155            return Parse_String;
156
157         when Tok_Number =>
158            return Parse_Number;
159      end case;
160   end Parse_Simple;
161
162   function Parse_File_Simple return Node
163   is
164      Res : Node;
165   begin
166      --  Start the scanner.
167      Scan;
168
169      Res := Parse_Simple;
170
171      return Res;
172   end Parse_File_Simple;
173
174   procedure Expect_Keyword (Id : Name_Id) is
175   begin
176      if Current_Token /= Tok_Keyword
177        or else Current_Identifier /= Id
178      then
179         Error_Msg_Parse ("keyword %i expected here", +Id);
180         raise Parse_Error;
181      end if;
182   end Expect_Keyword;
183
184   procedure Expect_Symbol is
185   begin
186      if Current_Token /= Tok_Symbol then
187         Error_Msg_Parse ("symbol expected here");
188         raise Parse_Error;
189      end if;
190   end Expect_Symbol;
191
192   procedure Expect_String is
193   begin
194      if Current_Token /= Tok_String then
195         Error_Msg_Parse ("string expected here");
196         raise Parse_Error;
197      end if;
198   end Expect_String;
199
200   procedure Skip_Right_Paren is
201   begin
202      while Current_Token = Tok_Keyword loop
203         Error_Msg_Parse
204           ("unexpected %i keyword, skipped", +Current_Identifier);
205
206         declare
207            Count : Natural;
208         begin
209            Count := 1;
210            loop
211               --  Skip.
212               Scan;
213
214               if Current_Token = Tok_Right_Paren then
215                  Count := Count - 1;
216                  exit when Count = 0;
217               end if;
218            end loop;
219
220            --  Skip ')'.
221            Scan;
222         end;
223      end loop;
224
225      if Current_Token /= Tok_Right_Paren then
226         Error_Msg_Parse ("')' expected here");
227      else
228         --  Skip ')'.
229         Scan;
230      end if;
231   end Skip_Right_Paren;
232
233   procedure Expect_Number is
234   begin
235      if Current_Token /= Tok_Number then
236         Error_Msg_Parse ("number expected here");
237         raise Parse_Error;
238      end if;
239   end Expect_Number;
240
241   procedure Skip_Comments is
242   begin
243      while Current_Token = Tok_Keyword
244        and then Current_Identifier = Name_Comment
245      loop
246         --  Skip '(comment'.
247         Scan;
248
249         if Current_Token = Tok_String then
250            --  Skip string.
251            Scan;
252         else
253            Error_Msg_Parse ("string expected after comment");
254         end if;
255
256         --  Skip ')' (for comment).
257         Skip_Right_Paren;
258      end loop;
259   end Skip_Comments;
260
261   function Parse_Rename return Node
262   is
263      Res : Node;
264   begin
265      pragma Assert (Current_Token = Tok_Keyword);
266
267      --  Skip 'rename'.
268      Scan;
269
270      Res := Create_Node (N_Rename);
271      Expect_Symbol;
272      Set_Name (Res, Parse_Symbol);
273
274      Expect_String;
275      Set_String (Res, Parse_String);
276
277      Skip_Right_Paren;
278
279      return Res;
280   end Parse_Rename;
281
282   function Parse_Name return Node is
283   begin
284      if Current_Token = Tok_Symbol then
285         return Parse_Symbol;
286      elsif Current_Token = Tok_Keyword then
287         if Current_Identifier = Name_Rename then
288            return Parse_Rename;
289         end if;
290      end if;
291
292      Error_Msg_Parse ("symbol or rename expected");
293      raise Parse_Error;
294   end Parse_Name;
295
296   function Parse_Boolean return Node
297   is
298      Res : Node;
299   begin
300      if Current_Token /= Tok_Keyword then
301         Error_Msg_Parse ("true or false expected");
302         raise Parse_Error;
303      end if;
304
305      Res := Create_Node (N_Boolean);
306      Set_Token_Location (Res);
307
308      if Current_Identifier = Name_True then
309         Set_Boolean (Res, True);
310      elsif Current_Identifier = Name_False then
311         Set_Boolean (Res, False);
312      else
313         Error_Msg_Parse ("true or false expected");
314      end if;
315
316      --  Skip keyword.
317      Scan;
318
319      --  Skip ')' (for true/false).
320      Skip_Right_Paren;
321
322      return Res;
323   end Parse_Boolean;
324
325   function Parse_Userdata return Node
326   is
327      Res : Node;
328   begin
329      Res := Create_Node (N_Userdata);
330      Set_Token_Location (Res);
331
332      --  Skip '(property' or '(userdata'.
333      Scan;
334
335      Set_Name (Res, Parse_Name);
336
337      Parse_Simple_List_Body (Res);
338
339      return Res;
340   end Parse_Userdata;
341
342   function Parse_Property return Node
343   is
344      Prop : Node;
345      Ptype : Name_Id;
346   begin
347      Prop := Create_Node (N_Property);
348      Set_Token_Location (Prop);
349
350      --  Skip '(property' or '(userdata'.
351      Scan;
352
353      Set_Name (Prop, Parse_Name);
354
355      if Current_Token /= Tok_Keyword then
356         Error_Msg_Parse ("property value expected");
357         raise Parse_Error;
358      end if;
359
360      Ptype := Current_Identifier;
361
362      --  Skip type keyword.
363      Scan;
364
365      case Ptype is
366         when Name_String =>
367            Set_Value (Prop, Parse_String);
368
369         when Name_Integer =>
370            Set_Value (Prop, Parse_Number);
371
372         when Name_Boolean =>
373            Set_Value (Prop, Parse_Boolean);
374
375         when Name_Number =>
376            Set_Value (Prop, Parse_Simple);
377
378         when others =>
379            Error_Msg_Parse ("unknown property type %i", +Ptype);
380            raise Parse_Error;
381      end case;
382
383      --  Skip ')' (for value).
384      Skip_Right_Paren;
385
386      if Current_Token = Tok_Keyword
387        and then Current_Identifier = Name_Unit
388      then
389         --  Skip '(unit'.
390         Scan;
391
392         Expect_Symbol;
393         Set_Unit (Prop, Current_Identifier);
394         Scan;
395
396         --  Skip ')' (for unit).
397         Skip_Right_Paren;
398      end if;
399
400      if Current_Token = Tok_Keyword
401        and then Current_Identifier = Name_Owner
402      then
403         --  Skip '(owner'.
404         Scan;
405
406         Expect_String;
407            Set_Owner (Prop, Parse_String);
408
409            --  Skip ')' (for owner).
410            Skip_Right_Paren;
411      end if;
412
413      --  Skip ')' (for property).
414      Skip_Right_Paren;
415
416      return Prop;
417   end Parse_Property;
418
419   procedure Parse_Properties (Constr : in out Constr_Type)
420   is
421      El : Node;
422   begin
423      while Current_Token = Tok_Keyword loop
424         case Current_Identifier is
425            when Name_Property =>
426               El := Parse_Property;
427            when Name_Userdata =>
428               El := Parse_Userdata;
429            when others =>
430               exit;
431         end case;
432         Append_Node (Constr, El);
433      end loop;
434   end Parse_Properties;
435
436   procedure Parse_Properties (N : Node)
437   is
438      Constr : Constr_Type;
439   begin
440      Init_Constr (Constr);
441
442      Parse_Properties (Constr);
443
444      Set_Properties_Chain (N, Get_Constr_Chain (Constr));
445   end Parse_Properties;
446
447   function Parse_Edif_Version return Int32
448   is
449      Res : Int32;
450   begin
451      Expect_Keyword (Name_Edifversion);
452
453      --  Skip '(edifversion'.
454      Scan;
455
456      --  Major
457      --  FIXME: small number.
458      Expect_Number;
459      Res := Current_Number * 100;
460      Scan;
461
462      --  Minor
463      Expect_Number;
464      Res := Res + Current_Number * 10;
465      Scan;
466
467      --  Revision
468      Expect_Number;
469      Res := Res + Current_Number;
470      Scan;
471
472      --  Skip ')'.
473      Skip_Right_Paren;
474
475      return Res;
476   end Parse_Edif_Version;
477
478   function Parse_Edif_Level return Int32
479   is
480      Res : Int32;
481   begin
482      Expect_Keyword (Name_Ediflevel);
483
484      --  Skip '(ediflevel'.
485      Scan;
486
487      Expect_Number;
488      Res := Current_Number;
489
490      --  Skip number.
491      Scan;
492
493      --  Skip ')'.
494      Skip_Right_Paren;
495
496      return Res;
497   end Parse_Edif_Level;
498
499   function Parse_Technology return Node is
500   begin
501      Expect_Keyword (Name_Technology);
502
503      return Parse_Simple_List;
504   end Parse_Technology;
505
506   procedure Parse_Designator_Opt (N : Node) is
507   begin
508      if Current_Token = Tok_Keyword
509        and then Current_Identifier = Name_Designator
510      then
511         --  Skip '(designator'.
512         Scan;
513
514         Expect_String;
515         Set_Designator (N, Parse_String);
516
517         --  Skip ')' (for designator).
518         Skip_Right_Paren;
519      end if;
520   end Parse_Designator_Opt;
521
522   function Parse_Array return Node
523   is
524      Res : Node;
525   begin
526      Res := Create_Node (N_Array);
527      Set_Token_Location (Res);
528
529      --  Skip '(array'.
530      Scan;
531
532      Set_Name (Res, Parse_Name);
533
534      Expect_Number;
535      Set_Array_Length (Res, Current_Number);
536
537      --  Skip number.
538      Scan;
539
540      --  Skip ')' (for array).
541      Skip_Right_Paren;
542
543      return Res;
544   end Parse_Array;
545
546   function Parse_Port return Node
547   is
548      -- Constr : Constr_Type;
549      Res : Node;
550      Name : Node;
551   begin
552      Res := Create_Node (N_Port);
553      Set_Token_Location (Res);
554
555      --  Skip '(port'.
556      Scan;
557
558      if Current_Token = Tok_Keyword
559        and then Current_Identifier = Name_Array
560      then
561         Name := Parse_Array;
562      else
563         Name := Parse_Name;
564      end if;
565      Set_Name (Res, Name);
566
567      Expect_Keyword (Name_Direction);
568      --  Skip '(direction'.
569      Scan;
570
571      Expect_Symbol;
572      case Current_Identifier is
573         when Name_Input =>
574            Set_Direction (Res, Dir_Input);
575         when Name_Output =>
576            Set_Direction (Res, Dir_Output);
577         when Name_Inout =>
578            Set_Direction (Res, Dir_Inout);
579         when others =>
580            Error_Msg_Parse
581              ("unhandled port direction %i", +Current_Identifier);
582            raise Parse_Error;
583      end case;
584
585      --  Skip symbol.
586      Scan;
587
588      --  Skip ')' (for direction).
589      Skip_Right_Paren;
590
591      Parse_Designator_Opt (Res);
592
593      Parse_Properties (Res);
594
595      --  Skip ')' (for port).
596      Skip_Right_Paren;
597
598      return Res;
599   end Parse_Port;
600
601   function Parse_Library_Ref_Opt return Node
602   is
603      Res : Node;
604   begin
605      if Current_Token = Tok_Keyword
606        and then Current_Identifier = Name_Libraryref
607      then
608         --  Skip '(libraryref'.
609         Scan;
610
611         Expect_Symbol;
612         Res := Parse_Symbol;
613
614         --  Skip ')' (for libraryref).
615         Skip_Right_Paren;
616      else
617         Res := Null_Node;
618      end if;
619
620      return Res;
621   end Parse_Library_Ref_Opt;
622
623   function Parse_Cell_Ref return Node
624   is
625      Res : Node;
626   begin
627      Res := Create_Node (N_Cell_Ref);
628      Set_Token_Location (Res);
629
630      --  Skip '(cellref'.
631      Scan;
632
633      Expect_Symbol;
634      Set_Name (Res, Parse_Symbol);
635
636      Set_Library_Ref (Res, Parse_Library_Ref_Opt);
637
638      --  Skip ')' (for cellref).
639      Skip_Right_Paren;
640
641      return Res;
642   end Parse_Cell_Ref;
643
644   function Parse_View_Ref return Node
645   is
646      Res : Node;
647   begin
648      Res := Create_Node (N_View_Ref);
649      Set_Token_Location (Res);
650
651      Expect_Keyword (Name_Viewref);
652
653      --  Skip '(viewref'.
654      Scan;
655
656      Set_Name (Res, Parse_Name);
657
658      Set_Cell_Ref (Res, Parse_Cell_Ref);
659
660      --  Skip ')' (for viewref).
661      Skip_Right_Paren;
662
663      return Res;
664   end Parse_View_Ref;
665
666   procedure Parse_Port_Instances (N : Node)
667   is
668      Constr : Constr_Type;
669      Inst : Node;
670   begin
671      Init_Constr (Constr);
672
673      while Current_Token = Tok_Keyword
674        and then Current_Identifier = Name_Portinstance
675      loop
676         Inst := Create_Node (N_Port_Instance);
677         Set_Token_Location (Inst);
678         Append_Node (Constr, Inst);
679
680         --  Skip '(portinstance'.
681         Scan;
682
683         Set_Name (Inst, Parse_Name);
684         Parse_Properties (Inst);
685
686         --  Skip ')' (for portinstance).
687         Skip_Right_Paren;
688
689      end loop;
690
691      Set_Port_Instances_Chain (N, Get_Constr_Chain (Constr));
692   end Parse_Port_Instances;
693
694   function Parse_Instance return Node
695   is
696      Res : Node;
697   begin
698      Res := Create_Node (N_Instance);
699      Set_Token_Location (Res);
700
701      --  Skip '(instance'.
702      Scan;
703
704      Set_Name (Res, Parse_Name);
705      Set_Instance_Ref (Res, Parse_View_Ref);
706
707      Parse_Port_Instances (Res);
708
709      Parse_Properties (Res);
710
711      --  Skip ')' (for instance).
712      Skip_Right_Paren;
713
714      return Res;
715   end Parse_Instance;
716
717   function Parse_Member return Node
718   is
719      Res : Node;
720   begin
721      Res := Create_Node (N_Member);
722      Set_Token_Location (Res);
723
724      --  Skip '(member'.
725      Scan;
726
727      Set_Name (Res, Parse_Name);
728
729      Expect_Number;
730      Set_Index (Res, Current_Number);
731
732      --  Skip number.
733      Scan;
734
735      --  Skip ')' (for member).
736      Skip_Right_Paren;
737
738      return Res;
739   end Parse_Member;
740
741   function Parse_Net return Node
742   is
743      Constr : Constr_Type;
744      Res : Node;
745      Ref : Node;
746   begin
747      Res := Create_Node (N_Net);
748      Set_Token_Location (Res);
749
750      --  Skip '(net'.
751      Scan;
752
753      Set_Name (Res, Parse_Name);
754
755      if Current_Token = Tok_Keyword
756        and then Current_Identifier = Name_Joined
757      then
758         Init_Constr (Constr);
759
760         --  Skip '(joined'.
761         Scan;
762
763         while Current_Token = Tok_Keyword
764           and then Current_Identifier = Name_Portref
765         loop
766            Ref := Create_Node (N_Port_Ref);
767            Set_Token_Location (Ref);
768            Append_Node (Constr, Ref);
769
770            --  Skip '(portref'.
771            Scan;
772
773            if Current_Token = Tok_Keyword
774              and then Current_Identifier = Name_Member
775            then
776               Set_Port (Ref, Parse_Member);
777            else
778               Set_Port (Ref, Parse_Name);
779            end if;
780
781            if Current_Token = Tok_Keyword
782              and then Current_Identifier = Name_Instanceref
783            then
784               --  Skip '(instanceref'.
785               Scan;
786
787               Set_Instance_Ref (Ref, Parse_Name);
788
789               --  Skip ')' (for instanceref).
790               Skip_Right_Paren;
791            end if;
792
793            --  Skip ')' (for portref).
794            Skip_Right_Paren;
795         end loop;
796         Set_Joined_Chain (Res, Get_Constr_Chain (Constr));
797
798         --  Skip ')' (for joined).
799         Skip_Right_Paren;
800      end if;
801
802      Parse_Properties (Res);
803
804      --  Skip ')' (for net).
805      Skip_Right_Paren;
806
807      return Res;
808   end Parse_Net;
809
810   function Parse_Interface return Node
811   is
812      Constr : Constr_Type;
813      Res : Node;
814   begin
815      Res := Create_Node (N_Interface);
816      Set_Token_Location (Res);
817
818      --  Skip '(interface'.
819      Scan;
820
821      Parse_Designator_Opt (Res);
822
823      Init_Constr (Constr);
824      while Current_Token = Tok_Keyword
825        and then Current_Identifier = Name_Port
826      loop
827         Append_Node (Constr, Parse_Port);
828      end loop;
829      Set_Ports_Chain (Res, Get_Constr_Chain (Constr));
830
831      Parse_Designator_Opt (Res);
832
833      Parse_Properties (Res);
834
835      --  Skip ')' (for interface).
836      Skip_Right_Paren;
837
838      return Res;
839   end Parse_Interface;
840
841   function Parse_View return Node
842   is
843      Constr : Constr_Type;
844      Prop_Constr : Constr_Type;
845      Res : Node;
846   begin
847      Res := Create_Node (N_View);
848      Set_Token_Location (Res);
849
850      --  Skip '(view'.
851      Scan;
852
853      Set_Name (Res, Parse_Name);
854
855      Expect_Keyword (Name_Viewtype);
856
857      --  Skip '(viewtype'.
858      Scan;
859
860      Expect_Symbol;
861      Set_View_Type (Res, Current_Identifier);
862
863      --  Skip symbol.
864      Scan;
865
866      --  Skip ')' (for viewtype).
867      Skip_Right_Paren;
868
869      Expect_Keyword (Name_Interface);
870      Set_Interface (Res, Parse_Interface);
871
872      Init_Constr (Prop_Constr);
873      Parse_Properties (Prop_Constr);
874
875      if Current_Token = Tok_Keyword
876        and then Current_Identifier = Name_Contents
877      then
878         --  Skip '(contents'.
879         Scan;
880
881         Init_Constr (Constr);
882         while Current_Token = Tok_Keyword loop
883            case Current_Identifier is
884               when Name_Instance =>
885                  Append_Node (Constr, Parse_Instance);
886               when Name_Net =>
887                  Append_Node (Constr, Parse_Net);
888               when Name_Userdata =>
889                  Append_Node (Constr, Parse_Userdata);
890               when others =>
891                  Error_Msg_Parse
892                    ("%i not supported in contents", +Current_Identifier);
893                  raise Parse_Error;
894            end case;
895         end loop;
896         Set_Contents_Chain (Res, Get_Constr_Chain (Constr));
897
898         --  Skip ')' (for contents).
899         Skip_Right_Paren;
900      end if;
901
902      Parse_Properties (Prop_Constr);
903      Set_Properties_Chain (Res, Get_Constr_Chain (Prop_Constr));
904
905      --  Skip ')' (for view).
906      Skip_Right_Paren;
907
908      return Res;
909   end Parse_View;
910
911   function Parse_Cell return Node
912   is
913      Res : Node;
914      Status : Node;
915      Prop_Constr : Constr_Type;
916      pragma Unreferenced (Status);
917   begin
918      Res := Create_Node (N_Cell);
919
920      --  Skip '(cell'.
921      Scan;
922
923      Set_Name (Res, Parse_Name);
924
925      Expect_Keyword (Name_Celltype);
926
927      --  Skip '(celltype'.
928      Scan;
929
930      Expect_Symbol;
931      Set_Cell_Type (Res, Current_Identifier);
932
933      --  Skip symbol.
934      Scan;
935
936      --  Skip ')' (for celltype).
937      Skip_Right_Paren;
938
939      Skip_Comments;
940
941      if Current_Token = Tok_Keyword
942        and then Current_Identifier = Name_Status
943      then
944         Status := Parse_Simple_List;
945         --  FIXME: free.
946      end if;
947
948      Init_Constr (Prop_Constr);
949      Parse_Properties (Prop_Constr);
950
951      Set_View (Res, Parse_View);
952
953      --  Properties can appear at several places...
954      Parse_Properties (Prop_Constr);
955      Set_Properties_Chain (Res, Get_Constr_Chain (Prop_Constr));
956
957      --  Skip ')' (for cell).
958      Skip_Right_Paren;
959
960      return Res;
961   end Parse_Cell;
962
963   procedure Parse_Library_Body (Res : Node)
964   is
965      Constr : Constr_Type;
966   begin
967      --  Skip '(external'.
968      Scan;
969
970      Set_Name (Res, Parse_Name);
971
972      Set_Edif_Level (Res, Parse_Edif_Level);
973      Set_Technology (Res, Parse_Technology);
974
975      Init_Constr (Constr);
976      while Current_Token = Tok_Keyword
977        and then Current_Identifier = Name_Cell
978      loop
979         Append_Node (Constr, Parse_Cell);
980      end loop;
981      Set_Cells_Chain (Res, Get_Constr_Chain (Constr));
982
983      --  Skip ')' (for external).
984      Skip_Right_Paren;
985   end Parse_Library_Body;
986
987   function Parse_Library return Node
988   is
989      Res : Node;
990   begin
991      Expect_Keyword (Name_Library);
992
993      Res := Create_Node (N_Library);
994      Set_Token_Location (Res);
995
996      Parse_Library_Body (Res);
997
998      return Res;
999   end Parse_Library;
1000
1001   function Parse_External return Node
1002   is
1003      Res : Node;
1004   begin
1005      Expect_Keyword (Name_External);
1006
1007      Res := Create_Node (N_External);
1008      Set_Token_Location (Res);
1009
1010      Parse_Library_Body (Res);
1011
1012      return Res;
1013   end Parse_External;
1014
1015   function Parse_Design return Node
1016   is
1017      Res : Node;
1018   begin
1019      Res := Create_Node (N_Design);
1020      Set_Token_Location (Res);
1021
1022      --  Skip '(design'.
1023      Scan;
1024
1025      Set_Name (Res, Parse_Name);
1026      Set_Cell_Ref (Res, Parse_Cell_Ref);
1027      Parse_Properties (Res);
1028
1029      --  Skip ')' (for design).
1030      Skip_Right_Paren;
1031
1032      return Res;
1033   end Parse_Design;
1034
1035   function Parse_Edif200 return Node
1036   is
1037      Res : Node;
1038      Constr : Constr_Type;
1039   begin
1040      --  Start the scanner.
1041      Scan;
1042
1043      Expect_Keyword (Name_Edif);
1044
1045      --  Skip '(edif'
1046      Scan;
1047
1048      Res := Create_Node (N_Edif);
1049
1050      Set_Name (Res, Parse_Name);
1051      Set_Edif_Version (Res, Parse_Edif_Version);
1052      Set_Edif_Level (Res, Parse_Edif_Level);
1053
1054      Expect_Keyword (Name_Keywordmap);
1055      --  Skip '(keywordmap'.
1056      Scan;
1057      Set_Keyword_Map (Res, Parse_Simple);
1058      --  Skip ')' (for keywordmap).
1059      Skip_Right_Paren;
1060
1061      if Current_Token = Tok_Keyword
1062        and then Current_Identifier = Name_Status
1063      then
1064         Set_Status (Res, Parse_Simple);
1065      end if;
1066
1067      Skip_Comments;
1068
1069      --  Parse externals.
1070      Init_Constr (Constr);
1071      while Current_Token = Tok_Keyword
1072        and then Current_Identifier = Name_External
1073      loop
1074         Append_Node (Constr, Parse_External);
1075      end loop;
1076      Set_External_Chain (Res, Get_Constr_Chain (Constr));
1077
1078      --  Parse libraries.
1079      Init_Constr (Constr);
1080      while Current_Token = Tok_Keyword
1081        and then Current_Identifier = Name_Library
1082      loop
1083         Append_Node (Constr, Parse_Library);
1084      end loop;
1085      Set_Library_Chain (Res, Get_Constr_Chain (Constr));
1086
1087      --  Parse design.
1088      if Current_Token = Tok_Keyword
1089        and then Current_Identifier = Name_Design
1090      then
1091         Set_Design (Res, Parse_Design);
1092      end if;
1093
1094      --  Skip ')' (for edif).
1095      Skip_Right_Paren;
1096
1097      if Current_Token /= Tok_Eof then
1098         Error_Msg_Parse ("end of file expected");
1099      end if;
1100
1101      return Res;
1102   end Parse_Edif200;
1103
1104end Edif.Parse;
1105