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