1 // This file is part of Visual D 2 // 3 // Visual D integrates the D programming language into Visual Studio 4 // Copyright (c) 2010-2011 by Rainer Schuetze, All Rights Reserved 5 // 6 // Distributed under the Boost Software License, Version 1.0. 7 // See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt 8 9 module vdc.parser.decl; 10 11 import vdc.util; 12 import vdc.lexer; 13 import vdc.parser.engine; 14 import vdc.parser.expr; 15 import vdc.parser.misc; 16 import vdc.parser.tmpl; 17 import vdc.parser.mod; 18 19 import ast = vdc.ast.all; 20 21 import stdext.util; 22 23 //-- GRAMMAR_BEGIN -- 24 //Declaration: 25 // alias LinkageAttribute_opt Decl 26 // typedef Decl /* for legacy code */ 27 // Decl 28 // alias Identifier this 29 // alias this = Identifier 30 class Declaration 31 { 32 static Action enter(Parser p) 33 { 34 switch(p.tok.id) 35 { 36 case TOK_alias: 37 p.pushState(&shiftAlias); 38 return Accept; 39 40 case TOK_typedef: 41 p.pushState(&shiftTypedef); 42 p.pushState(&Decl!true.enter); 43 return Accept; 44 default: 45 return Decl!true.enter(p); 46 } 47 } 48 49 static Action shiftAlias(Parser p) 50 { 51 switch(p.tok.id) 52 { 53 case TOK_extern: 54 p.pushState(&shiftAliasLinkage); 55 p.pushState(&Decl!true.enter); 56 return LinkageAttribute.enter(p); 57 58 case TOK_Identifier: 59 p.pushToken(p.tok); 60 p.pushState(&shiftAliasIdentifier); 61 return Accept; 62 63 case TOK_this: 64 p.pushState(&shiftThis); 65 return Accept; 66 67 default: 68 p.pushState(&shiftTypedef); 69 return Decl!true.enter(p); 70 } 71 } 72 73 static Action shiftAliasLinkage(Parser p) 74 { 75 auto decl = p.popNode!(ast.Decl)(); 76 auto link = p.popNode!(ast.AttributeSpecifier)(); 77 p.combineAttributes(decl.attr, link.attr); 78 p.pushNode(decl); 79 return Forward; 80 } 81 82 // assumes identifier token on the info stack 83 static Action shiftAliasIdentifier(Parser p) 84 { 85 switch(p.tok.id) 86 { 87 case TOK_this: 88 auto tok = p.popToken(); 89 p.pushNode(new ast.AliasThis(tok)); 90 p.pushState(&shiftAliasThis); 91 return Accept; 92 case TOK_assign: 93 p.pushState(&shiftAliasAssign); 94 p.pushState(&Type.enter); 95 return Accept; 96 default: 97 p.pushState(&shiftTypedef); 98 return Decl!true.enterTypeIdentifier(p); 99 } 100 } 101 102 static Action shiftThis(Parser p) 103 { 104 switch(p.tok.id) 105 { 106 case TOK_assign: 107 p.pushState(&shiftThisAssign); 108 return Accept; 109 default: 110 return p.parseError("'=' expected after alias this"); 111 } 112 } 113 114 static Action shiftThisAssign(Parser p) 115 { 116 switch(p.tok.id) 117 { 118 case TOK_Identifier: 119 p.pushNode(new ast.AliasThis(p.tok)); 120 p.pushState(&shiftAliasThis); 121 return Accept; 122 default: 123 return p.parseError("identifier expected after alias this ="); 124 } 125 } 126 127 static Action shiftAliasThis(Parser p) 128 { 129 switch(p.tok.id) 130 { 131 case TOK_semicolon: 132 return Accept; 133 default: 134 return p.parseError("semicolon expected after alias this;"); 135 } 136 } 137 138 // assumes identifier token on the info stack 139 static Action shiftAliasAssign(Parser p) 140 { 141 auto type = static_cast!(ast.Type)(p.popNode()); 142 143 auto tok = p.popToken(); 144 auto decl = new ast.Decl(type.id, type.span); 145 auto decls = new ast.Declarators(tok); 146 decls.addMember(new ast.Declarator(tok)); 147 // insert type before declarator identifier 148 decl.addMember(type); 149 decl.addMember(decls); 150 decl.isAlias = true; 151 decl.hasSemi = true; 152 p.pushNode(decl); 153 154 switch(p.tok.id) 155 { 156 case TOK_semicolon: 157 return Accept; 158 case TOK_comma: 159 default: 160 return p.parseError("semicolon expected after alias identifier = type"); 161 } 162 } 163 164 static Action shiftTypedef(Parser p) 165 { 166 //p.appendReplaceTopNode(new ast.AliasDeclaration(p.tok)); 167 p.topNode!(ast.Decl)().isAlias = true; 168 return Forward; 169 } 170 } 171 172 //-- GRAMMAR_BEGIN -- 173 //Decl: 174 // StorageClasses Decl 175 // BasicType BasicTypes2_opt Declarators ; 176 // BasicType BasicTypes2_opt Declarator FunctionBody 177 // AutoDeclaration 178 // 179 //AutoDeclaration: 180 // StorageClasses Identifier = AssignExpression ; 181 class Decl(bool checkSemi = true) 182 { 183 // storage class stored in Decl.attr, first child is Type (TOK_auto if not present) 184 static Action enter(Parser p) 185 { 186 auto decl = new ast.Decl(p.tok); 187 decl.hasSemi = checkSemi; 188 p.pushNode(decl); 189 190 if(isTypeModifier(p.tok.id)) 191 { 192 // could be storage class or BasicType 193 p.pushToken(p.tok); 194 p.pushState(&shiftTypeModifier); 195 return Accept; 196 } 197 if(isStorageClass(p.tok.id)) 198 { 199 p.combineAttributes(decl.attr, tokenToAttribute(p.tok.id)); 200 p.combineAnnotations(decl.annotation, tokenToAnnotation(p.tok.id)); 201 p.pushState(&shiftStorageClass); 202 return Accept; 203 } 204 p.pushState(&shiftBasicType); 205 return BasicType.enter(p); 206 } 207 208 // switch here from AttributeSpecifier when detecting a '(' after const,etc 209 // assumes modifier token on the info stack 210 static Action enterAttributeSpecifier(Parser p) 211 { 212 assert(p.tok.id == TOK_lparen); 213 214 auto decl = new ast.Decl(p.tok); 215 decl.hasSemi = checkSemi; 216 p.pushNode(decl); 217 p.pushState(&shiftBasicType); 218 return BasicType.shiftTypeModifier(p); 219 } 220 221 // disambiguate "const x" and "const(int) x" 222 // assumes modifier token on the info stack 223 static Action shiftTypeModifier(Parser p) 224 { 225 if(p.tok.id == TOK_lparen) 226 { 227 p.pushState(&shiftBasicType); 228 return BasicType.shiftTypeModifier(p); 229 } 230 231 auto decl = p.topNode!(ast.Decl)(); 232 Token tok = p.popToken(); 233 p.combineAttributes(decl.attr, tokenToAttribute(tok.id)); 234 return shiftStorageClass(p); 235 } 236 237 static Action enterAfterStorageClass(Parser p, TokenId storage) 238 { 239 auto decl = new ast.Decl(p.tok); 240 decl.hasSemi = checkSemi; 241 p.pushNode(decl); 242 decl.attr = tokenToAttribute(storage); 243 return shiftStorageClass(p); 244 } 245 246 static Action shiftStorageClass(Parser p) 247 { 248 if(p.tok.id == TOK_Identifier) 249 { 250 p.pushToken(p.tok); 251 p.pushState(&shiftIdentifier); 252 return Accept; 253 } 254 if(isTypeModifier(p.tok.id)) 255 { 256 // could be storage class or BasicType 257 p.pushToken(p.tok); 258 p.pushState(&shiftTypeModifier); 259 return Accept; 260 } 261 if(isStorageClass(p.tok.id)) 262 { 263 auto decl = p.topNode!(ast.Decl)(); 264 p.combineAttributes(decl.attr, tokenToAttribute(p.tok.id)); 265 p.combineAnnotations(decl.annotation, tokenToAnnotation(p.tok.id)); 266 p.pushState(&shiftStorageClass); 267 return Accept; 268 } 269 p.pushState(&shiftBasicType); 270 return BasicType.enter(p); 271 } 272 273 // switch here from Statement when detecting a declaration after an identifier 274 // assumes identifier token on the info stack 275 static Action enterTypeIdentifier(Parser p) 276 { 277 auto decl = new ast.Decl(p.tok); 278 decl.hasSemi = checkSemi; 279 p.pushNode(decl); 280 281 p.pushState(&shiftBasicType); 282 return BasicType.enterIdentifier(p); 283 } 284 285 // assumes identifier token on the info stack 286 static Action enterIdentifier(Parser p) 287 { 288 auto decl = new ast.Decl(p.tok); 289 decl.hasSemi = checkSemi; 290 p.pushNode(decl); 291 292 return shiftIdentifier(p); 293 } 294 295 // assumes identifier token on the info stack 296 static Action shiftIdentifier(Parser p) 297 { 298 switch(p.tok.id) 299 { 300 case TOK_assign: 301 auto bt = new ast.AutoType(TOK_auto, p.topToken().span); 302 p.topNode!(ast.Decl)().addMember(bt); 303 304 p.pushState(&shiftDeclarators); 305 return Declarators.enterAfterIdentifier(p); 306 case TOK_lparen: 307 // storageclass identifier(... must be function with auto return 308 auto bt = new ast.AutoType(TOK_auto, p.topToken().span); 309 p.topNode!(ast.Decl).addMember(bt); 310 p.pushState(&shiftDeclarators); 311 return Declarators.enterAfterIdentifier(p); 312 default: 313 p.pushState(&shiftBasicType); 314 return BasicType.enterIdentifier(p); 315 } 316 } 317 318 // assumes identifier token on the info stack 319 static Action enterAutoReturn(Parser p) 320 { 321 assert(p.tok.id == TOK_lparen); 322 323 auto decl = new ast.Decl(p.topToken()); 324 decl.hasSemi = checkSemi; 325 p.pushNode(decl); 326 327 auto bt = new ast.AutoType(TOK_auto, p.topToken().span); 328 decl.addMember(bt); 329 330 p.pushState(&shiftDeclarators); 331 return Declarators.enterAfterIdentifier(p); 332 } 333 334 static Action shiftBasicType(Parser p) 335 { 336 switch(p.tok.id) 337 { 338 mixin(BasicType2.case_TOKs); 339 p.pushState(&shiftBasicTypes2); 340 return BasicTypes2.enter(p); 341 default: 342 return shiftBasicTypes2(p); 343 } 344 } 345 346 static Action shiftBasicTypes2(Parser p) 347 { 348 p.popAppendTopNode!(ast.Decl, ast.Type)(); 349 p.pushState(&shiftDeclarators); 350 return Declarators.enter(p); 351 } 352 353 static Action shiftDeclarators(Parser p) 354 { 355 p.popAppendTopNode!(ast.Decl)(); 356 static if(checkSemi) 357 { 358 if(p.tok.id == TOK_RECOVER) 359 return Forward; 360 auto decl = p.topNode!(ast.Decl)(); 361 if(decl.members.length == 2 && // BasicType and Declarators 362 decl.members[1].members.length == 1 && // only one declarator 363 FunctionBody.isInitTerminal(p.tok)) 364 { 365 decl.hasSemi = false; 366 p.pushState(&shiftFunctionBody); 367 return FunctionBody.enter(p); 368 } 369 if(p.tok.id != TOK_semicolon) 370 return p.parseError("semicolon expected after declaration"); 371 return Accept; 372 } 373 else 374 { 375 return Forward; 376 } 377 } 378 379 static Action shiftFunctionBody(Parser p) 380 { 381 p.popAppendTopNode!(ast.Decl)(); 382 return Forward; 383 } 384 } 385 386 //-- GRAMMAR_BEGIN -- 387 //Declarators: 388 // DeclaratorInitializer 389 // DeclaratorInitializer , DeclaratorIdentifierList 390 class Declarators 391 { 392 mixin ListNode!(ast.Declarators, DeclaratorInitializer, TOK_comma); 393 394 // assumes identifier token on the info stack 395 static Action enterAfterIdentifier(Parser p) 396 { 397 p.pushNode(new ast.Declarators(p.tok)); 398 p.pushState(&shift); 399 return DeclaratorInitializer.enterAfterIdentifier(p); 400 } 401 } 402 403 //-- GRAMMAR_BEGIN -- 404 //DeclaratorInitializer: 405 // Declarator 406 // Declarator = Initializer 407 class DeclaratorInitializer 408 { 409 mixin OptionalNode!(ast.DeclaratorInitializer, Declarator, TOK_assign, Initializer); 410 411 // assumes identifier token on the info stack 412 static Action enterAfterIdentifier(Parser p) 413 { 414 switch(p.tok.id) 415 { 416 case TOK_assign: 417 auto tok = p.popToken(); 418 p.pushNode(new ast.Declarator(tok)); 419 return shiftSubType1(p); 420 default: 421 p.pushState(&shiftSubType1); 422 return Declarator.enterAfterIdentifier(p); 423 } 424 } 425 } 426 427 //-- GRAMMAR_BEGIN -- 428 //DeclaratorIdentifierList: 429 // DeclaratorIdentifier 430 // DeclaratorIdentifier , DeclaratorIdentifierList 431 class DeclaratorIdentifierList 432 { 433 mixin ListNode!(ast.DeclaratorIdentifierList, DeclaratorIdentifier, TOK_comma); 434 } 435 436 //-- GRAMMAR_BEGIN -- 437 //DeclaratorIdentifier: 438 // Identifier 439 // Identifier = Initializer 440 class DeclaratorIdentifier 441 { 442 mixin OptionalNode!(ast.DeclaratorIdentifier, Identifier, TOK_assign, Initializer); 443 } 444 445 //-- GRAMMAR_BEGIN -- 446 //Initializer: 447 // VoidInitializer 448 // NonVoidInitializer 449 // 450 //NonVoidInitializer: 451 // AssignExpression 452 // ArrayInitializer /* same as ArrayLiteral? */ 453 // StructInitializer 454 class Initializer 455 { 456 static Action enter(Parser p) 457 { 458 if(p.tok.id == TOK_void) 459 { 460 p.pushRollback(&rollbackVoid); 461 p.pushState(&shiftVoid); 462 return Accept; 463 } 464 // StructInitializer not implemented 465 return AssignExpression.enter(p); 466 } 467 468 static Action shiftVoid(Parser p) 469 { 470 switch(p.tok.id) 471 { 472 case TOK_dot: 473 return p.parseError("unexpected '.' in void initializer"); 474 default: 475 p.popRollback(); 476 p.pushNode(new ast.VoidInitializer(p.tok)); 477 return Forward; 478 } 479 } 480 481 static Action rollbackVoid(Parser p) 482 { 483 return AssignExpression.enter(p); 484 } 485 } 486 487 //-- GRAMMAR_BEGIN -- 488 //BasicType: 489 // BasicTypeX 490 // . IdentifierList 491 // IdentifierList 492 // Typeof 493 // Typeof . IdentifierList 494 // ModifiedType 495 // VectorType 496 // 497 //ModifiedType: 498 // const ( Type ) 499 // immutable ( Type ) 500 // shared ( Type ) 501 // inout ( Type ) 502 class BasicType 503 { 504 static Action enter(Parser p) 505 { 506 switch(p.tok.id) 507 { 508 case TOK_dot: 509 case TOK_Identifier: 510 p.pushNode(new ast.IdentifierType(p.tok)); 511 p.pushState(&shiftIdentifierList); 512 return GlobalIdentifierList.enter(p); 513 case TOK_typeof: 514 p.pushState(&shiftTypeof); 515 return Typeof.enter(p); 516 517 mixin(case_TOKs_BasicTypeX); 518 p.pushNode(new ast.BasicType(p.tok)); 519 return Accept; 520 521 mixin(case_TOKs_TypeModifier); 522 p.pushToken(p.tok); 523 p.pushState(&shiftTypeModifier); 524 return Accept; 525 526 case TOK___vector: 527 return VectorType.enter(p); 528 529 default: 530 return p.parseError("unexpected token in BasicType"); 531 } 532 } 533 534 // assumes modifier token on the info stack 535 static Action shiftTypeModifier(Parser p) 536 { 537 Token tok = p.popToken(); 538 p.pushNode(new ast.ModifiedType(tok)); 539 540 switch(p.tok.id) 541 { 542 case TOK_lparen: 543 p.pushState(&shiftParenType); 544 p.pushState(&Type.enter); 545 return Accept; 546 default: 547 p.pushState(&shiftType); 548 return Type.enter(p); 549 } 550 } 551 552 static Action shiftParenType(Parser p) 553 { 554 if(p.tok.id != TOK_rparen) 555 return p.parseError("closing parenthesis expected"); 556 p.popAppendTopNode(); 557 return Accept; 558 } 559 560 static Action shiftType(Parser p) 561 { 562 p.popAppendTopNode(); 563 return Forward; 564 } 565 566 // entry point on token after identifier 567 // assumes identifier token on the info stack 568 static Action enterIdentifier(Parser p) 569 { 570 p.pushNode(new ast.IdentifierType(p.topToken())); 571 p.pushState(&shiftIdentifierList); 572 return IdentifierList.enterAfterIdentifier(p); 573 } 574 575 static Action shiftIdentifierList(Parser p) 576 { 577 p.popAppendTopNode!(ast.IdentifierType)(); 578 return Forward; 579 } 580 581 static Action shiftTypeof(Parser p) 582 { 583 if(p.tok.id != TOK_dot) 584 return Forward; 585 586 p.pushState(&shiftTypeofIdentifierList); 587 p.pushState(&IdentifierList.enter); 588 return Accept; 589 } 590 591 static Action shiftTypeofIdentifierList(Parser p) 592 { 593 p.popAppendTopNode!(ast.Typeof, ast.IdentifierList)(); 594 return Forward; 595 } 596 597 } 598 599 enum case_TOKs_TypeModifier = q{ 600 case TOK_const: 601 case TOK_shared: 602 case TOK_immutable: 603 case TOK_inout: 604 }; 605 606 bool isTypeModifier(TokenId tok) 607 { 608 switch(tok) 609 { 610 mixin(case_TOKs_TypeModifier); 611 return true; 612 default: 613 return false; 614 } 615 } 616 617 //-- GRAMMAR_BEGIN -- 618 //BasicTypeX: 619 // bool 620 // byte 621 // ubyte 622 // short 623 // ushort 624 // int 625 // uint 626 // long 627 // ulong 628 // char 629 // wchar 630 // dchar 631 // float 632 // double 633 // real 634 // ifloat 635 // idouble 636 // ireal 637 // cfloat 638 // cdouble 639 // creal 640 // void 641 642 bool isBasicTypeX(TokenId tok) 643 { 644 switch(tok) 645 { 646 mixin(case_TOKs_BasicTypeX); 647 return true; 648 default: 649 return false; 650 } 651 } 652 653 //-- GRAMMAR_BEGIN -- 654 //VectorType: 655 // __vector ( Type ) 656 class VectorType 657 { 658 mixin SequenceNode!(ast.VectorType, TOK___vector, TOK_lparen, Type, TOK_rparen); 659 } 660 661 //-- GRAMMAR_BEGIN -- 662 //Typeof: 663 // typeof ( Expression ) 664 // typeof ( return ) 665 class Typeof 666 { 667 static Action enter(Parser p) 668 { 669 if(p.tok.id != TOK_typeof) 670 return p.parseError("typeof expected"); 671 p.pushNode(new ast.Typeof(p.tok)); 672 p.pushState(&shiftLparen); 673 return Accept; 674 } 675 676 static Action shiftLparen(Parser p) 677 { 678 if(p.tok.id != TOK_lparen) 679 return p.parseError("opening parenthesis expected"); 680 p.pushState(&shiftArgument); 681 return Accept; 682 } 683 684 static Action shiftArgument(Parser p) 685 { 686 if(p.tok.id == TOK_return) 687 { 688 p.topNode!(ast.Typeof).id = TOK_return; 689 p.pushState(&shiftRparen); 690 return Accept; 691 } 692 p.pushState(&shiftExpression); 693 return Expression.enter(p); 694 } 695 696 static Action shiftExpression(Parser p) 697 { 698 if(p.tok.id != TOK_rparen) 699 return p.parseError("closing parenthesis expected"); 700 p.popAppendTopNode!(ast.Typeof)(); 701 return Accept; 702 } 703 704 static Action shiftRparen(Parser p) 705 { 706 if(p.tok.id != TOK_rparen) 707 return p.parseError("closing parenthesis expected"); 708 return Accept; 709 } 710 } 711 712 //-- GRAMMAR_BEGIN -- 713 //Declarator: 714 // Identifier DeclaratorSuffixes_opt 715 class Declarator 716 { 717 static Action enter(Parser p) 718 { 719 switch(p.tok.id) 720 { 721 case TOK_Identifier: 722 p.pushNode(new ast.Declarator(p.tok)); 723 p.pushState(&shiftIdentifier); 724 return Accept; 725 726 default: 727 return p.parseError("unexpected token in Declarator"); 728 } 729 } 730 731 static Action shiftIdentifier(Parser p) 732 { 733 switch(p.tok.id) 734 { 735 case TOK_lparen: 736 case TOK_lbracket: 737 return DeclaratorSuffixes.enter(p); // appends to Declarator 738 default: 739 return Forward; 740 } 741 } 742 743 // assumes identifier token on the info stack 744 static Action enterAfterIdentifier(Parser p) 745 { 746 auto tok = p.popToken(); 747 p.pushNode(new ast.Declarator(tok)); 748 return shiftIdentifier(p); 749 } 750 } 751 752 //-- GRAMMAR_BEGIN -- 753 // always optional 754 //BasicType2: 755 // * 756 // [ ] 757 // [ AssignExpression ] 758 // [ AssignExpression .. AssignExpression ] 759 // [ Type ] 760 // delegate Parameters FunctionAttributes_opt 761 // function Parameters FunctionAttributes_opt 762 class BasicType2 763 { 764 enum case_TOKs = q{ 765 case TOK_mul: 766 case TOK_lbracket: 767 case TOK_delegate: 768 case TOK_function: 769 }; 770 771 static Action enter(Parser p) 772 { 773 assert(p.topNode!(ast.Type)); 774 switch(p.tok.id) 775 { 776 case TOK_mul: 777 p.appendReplaceTopNode(new ast.TypePointer(p.tok)); 778 return Accept; 779 case TOK_lbracket: 780 p.pushState(&shiftLbracket); 781 return Accept; 782 783 case TOK_delegate: 784 p.appendReplaceTopNode(new ast.TypeDelegate(p.tok)); 785 p.pushState(&shiftParameters); 786 p.pushState(&Parameters.enter); 787 return Accept; 788 789 case TOK_function: 790 p.appendReplaceTopNode(new ast.TypeFunction(p.tok)); 791 p.pushState(&shiftParameters); 792 p.pushState(&Parameters.enter); 793 return Accept; 794 default: 795 return p.parseError("unexpected token in BasicType2"); 796 } 797 } 798 799 static Action shiftLbracket(Parser p) 800 { 801 switch(p.tok.id) 802 { 803 case TOK_rbracket: 804 p.appendReplaceTopNode(new ast.TypeDynamicArray(p.tok)); 805 return Accept; 806 default: 807 p.pushState(&shiftTypeOrExpression); 808 return TypeOrExpression!TOK_rbracket.enter(p); 809 } 810 } 811 812 static Action shiftTypeOrExpression(Parser p) 813 { 814 if(cast(ast.Type) p.topNode()) 815 { 816 auto keyType = p.popNode!(ast.Type); 817 p.appendReplaceTopNode(new ast.TypeAssocArray(p.tok)); 818 p.topNode().addMember(keyType); 819 if(p.tok.id != TOK_rbracket) 820 return p.parseError("']' expected"); 821 return Accept; 822 } 823 824 switch(p.tok.id) 825 { 826 case TOK_rbracket: 827 auto dim = p.popNode!(ast.Expression); 828 p.appendReplaceTopNode(new ast.TypeStaticArray(p.tok)); 829 p.topNode().addMember(dim); 830 return Accept; 831 case TOK_slice: 832 auto low = p.popNode!(ast.Expression); 833 p.appendReplaceTopNode(new ast.TypeArraySlice(p.tok)); 834 p.topNode().addMember(low); 835 p.pushState(&shiftSliceUpper); 836 p.pushState(&AssignExpression.enter); 837 return Accept; 838 default: 839 return p.parseError("']' expected"); 840 } 841 } 842 843 static Action shiftSliceUpper(Parser p) 844 { 845 p.popAppendTopNode!(ast.TypeArraySlice)(); 846 switch(p.tok.id) 847 { 848 case TOK_rbracket: 849 return Accept; 850 default: 851 return p.parseError("']' expected"); 852 } 853 } 854 855 static Action shiftParameters(Parser p) 856 { 857 p.popAppendTopNode(); 858 return shiftAttributes(p); 859 } 860 861 static Action shiftAttributes(Parser p) 862 { 863 switch(p.tok.id) 864 { 865 mixin(case_TOKs_MemberFunctionAttribute); // no member attributes? 866 { 867 auto type = p.topNode!(ast.Type); 868 p.combineAttributes(type.attr, tokenToAttribute(p.tok.id)); 869 p.pushState(&shiftAttributes); 870 } 871 return Accept; 872 default: 873 return Forward; 874 } 875 } 876 } 877 878 //-- GRAMMAR_BEGIN -- 879 //BasicTypes2: 880 // BasicType2 881 // BasicType2 BasicTypes2 882 class BasicTypes2 883 { 884 static Action enter(Parser p) 885 { 886 assert(p.topNode!(ast.Type)); 887 switch(p.tok.id) 888 { 889 mixin(BasicType2.case_TOKs); 890 p.pushState(&shiftBasicType); 891 return BasicType2.enter(p); 892 default: 893 return p.parseError("unexpected token in BasicType2"); 894 } 895 } 896 897 static Action shiftBasicType(Parser p) 898 { 899 switch(p.tok.id) 900 { 901 mixin(BasicType2.case_TOKs); 902 p.pushState(&shiftBasicType); 903 return BasicType2.enter(p); 904 default: 905 return Forward; 906 } 907 } 908 } 909 910 //-- GRAMMAR_BEGIN -- 911 //DeclaratorSuffixes: 912 // DeclaratorSuffix 913 // DeclaratorSuffix DeclaratorSuffixes 914 // 915 // obsolete C-style? 916 //DeclaratorSuffix: 917 // TemplateParameterList_opt Parameters MemberFunctionAttributes_opt Constraint_opt 918 // [ ] 919 // [ AssignExpression ] 920 // [ Type ] 921 class DeclaratorSuffixes 922 { 923 static Action enter(Parser p) 924 { 925 switch(p.tok.id) 926 { 927 case TOK_lparen: 928 p.pushRollback(&rollbackParametersFailure); 929 p.pushState(&shiftParameters); 930 return Parameters.enter(p); 931 case TOK_lbracket: 932 p.pushState(&shiftLbracket); 933 return Accept; 934 default: 935 return p.parseError("opening parenthesis or bracket expected"); 936 } 937 } 938 939 static Action nextSuffix(Parser p) 940 { 941 switch(p.tok.id) 942 { 943 case TOK_lbracket: 944 p.pushState(&shiftLbracket); 945 return Accept; 946 default: 947 return Forward; 948 } 949 } 950 951 static Action shiftLbracket(Parser p) 952 { 953 switch(p.tok.id) 954 { 955 case TOK_rbracket: 956 p.topNode().addMember(new ast.SuffixDynamicArray(p.tok)); 957 p.pushState(&nextSuffix); 958 return Accept; 959 default: 960 p.pushState(&shiftTypeOrExpression); 961 return TypeOrExpression!(TOK_rbracket).enter(p); 962 } 963 // return p.notImplementedError("C style declarators"); 964 } 965 966 static Action shiftTypeOrExpression(Parser p) 967 { 968 switch(p.tok.id) 969 { 970 case TOK_rbracket: 971 auto node = p.popNode(); 972 ast.Node n = new ast.SuffixArray(p.tok); 973 n.addMember(node); 974 p.topNode().addMember(n); 975 p.pushState(&nextSuffix); 976 return Accept; 977 default: 978 return p.parseError("']' expected in C style declarator"); 979 } 980 } 981 982 static Action shiftParameters(Parser p) 983 { 984 switch(p.tok.id) 985 { 986 case TOK_lparen: 987 // somehow made it through the parameters, but another parameters list follow... 988 return Reject; // so rollback to retry with template parameter list 989 990 mixin(case_TOKs_MemberFunctionAttribute); 991 p.popRollback(); 992 auto param = p.topNode!(ast.ParameterList); 993 p.combineAttributes(param.attr, tokenToAttribute(p.tok.id)); 994 p.pushState(&shiftMemberFunctionAttribute); 995 return Accept; 996 case TOK_if: 997 p.popRollback(); 998 p.popAppendTopNode!(ast.Declarator, ast.ParameterList)(); 999 p.pushState(&shiftConstraint); 1000 return Constraint.enter(p); 1001 default: 1002 p.popRollback(); 1003 p.popAppendTopNode!(ast.Declarator, ast.ParameterList)(); 1004 return Forward; 1005 } 1006 } 1007 1008 static Action shiftMemberFunctionAttribute(Parser p) 1009 { 1010 switch(p.tok.id) 1011 { 1012 mixin(case_TOKs_MemberFunctionAttribute); 1013 { 1014 auto param = p.topNode!(ast.ParameterList); 1015 p.combineAttributes(param.attr, tokenToAttribute(p.tok.id)); 1016 p.pushState(&shiftMemberFunctionAttribute); 1017 } 1018 return Accept; 1019 case TOK_if: 1020 p.popAppendTopNode!(ast.Declarator, ast.ParameterList)(); 1021 p.pushState(&shiftConstraint); 1022 return Constraint.enter(p); 1023 default: 1024 p.popAppendTopNode!(ast.Declarator, ast.ParameterList)(); 1025 return Forward; 1026 } 1027 } 1028 1029 static Action shiftConstraint(Parser p) 1030 { 1031 p.popAppendTopNode!(ast.Declarator, ast.Constraint)(); 1032 return Forward; 1033 } 1034 1035 static Action rollbackParametersFailure(Parser p) 1036 { 1037 p.pushState(&shiftTemplateParameterList); 1038 return TemplateParameters.enter(p); 1039 } 1040 1041 static Action shiftTemplateParameterList(Parser p) 1042 { 1043 p.popAppendTopNode(); // append to declarator 1044 switch(p.tok.id) 1045 { 1046 case TOK_lparen: 1047 p.pushState(&shiftParametersAfterTempl); 1048 return Parameters.enter(p); 1049 default: 1050 return p.parseError("parameter list expected after template arguments"); 1051 } 1052 } 1053 1054 static Action shiftParametersAfterTempl(Parser p) 1055 { 1056 return shiftMemberFunctionAttribute(p); 1057 } 1058 } 1059 1060 //-- GRAMMAR_BEGIN -- 1061 //GlobalIdentifierList: 1062 // IdentifierList 1063 // . IdentifierList 1064 class GlobalIdentifierList 1065 { 1066 static Action enter(Parser p) 1067 { 1068 switch(p.tok.id) 1069 { 1070 case TOK_dot: 1071 return IdentifierList.enterGlobal(p); 1072 default: 1073 return IdentifierList.enter(p); 1074 } 1075 } 1076 1077 } 1078 1079 //-- GRAMMAR_BEGIN -- 1080 //IdentifierList: 1081 // Identifier 1082 // Identifier . IdentifierList 1083 // TemplateInstance 1084 // TemplateInstance . IdentifierList 1085 // 1086 // using IdentifierOrTemplateInstance 1087 class IdentifierList 1088 { 1089 mixin ListNode!(ast.IdentifierList, IdentifierOrTemplateInstance, TOK_dot); 1090 1091 // if preceded by '.', enter here fore global scope 1092 static Action enterGlobal(Parser p) 1093 { 1094 assert(p.tok.id == TOK_dot); 1095 1096 auto list = new ast.IdentifierList(p.tok); 1097 list.global = true; 1098 p.pushNode(list); 1099 p.pushState(&shift); 1100 p.pushState(&IdentifierOrTemplateInstance.enter); 1101 return Accept; 1102 } 1103 1104 // assumes identifier token on the info stack 1105 static Action enterAfterIdentifier(Parser p) 1106 { 1107 auto list = new ast.IdentifierList(p.topToken()); 1108 p.pushNode(list); 1109 p.pushState(&shift); 1110 return IdentifierOrTemplateInstance.enterIdentifier(p); 1111 } 1112 } 1113 1114 class Identifier 1115 { 1116 static Action enter(Parser p) 1117 { 1118 if(p.tok.id != TOK_Identifier) 1119 return p.parseError("identifier expected"); 1120 1121 p.pushNode(new ast.Identifier(p.tok)); 1122 return Accept; 1123 } 1124 } 1125 1126 //-- GRAMMAR_BEGIN -- 1127 //StorageClasses: 1128 // StorageClass 1129 // StorageClass StorageClasses 1130 // 1131 //StorageClass: 1132 // AttributeOrStorageClass 1133 // extern 1134 // nothrow 1135 // pure 1136 // synchronized 1137 bool isStorageClass(TokenId tok) 1138 { 1139 switch(tok) 1140 { 1141 case TOK_extern: 1142 case TOK_synchronized: 1143 mixin(case_TOKs_FunctionAttribute); 1144 mixin(case_TOKs_AttributeOrStorageClass); 1145 return true; 1146 default: 1147 return false; 1148 } 1149 } 1150 1151 //-- GRAMMAR_BEGIN -- 1152 //AttributeOrStorageClass: 1153 // deprecated 1154 // static 1155 // final 1156 // override 1157 // abstract 1158 // const 1159 // auto 1160 // scope 1161 // __gshared 1162 // __thread 1163 // shared 1164 // immutable 1165 // inout 1166 // ref 1167 enum case_TOKs_AttributeOrStorageClass = q{ 1168 case TOK_deprecated: 1169 case TOK_static: 1170 case TOK_final: 1171 case TOK_override: 1172 case TOK_abstract: 1173 case TOK_const: 1174 case TOK_auto: 1175 case TOK_scope: 1176 case TOK_volatile: 1177 case TOK___gshared: 1178 case TOK___thread: 1179 case TOK_shared: 1180 case TOK_immutable: 1181 case TOK_inout: 1182 case TOK_ref: 1183 }; 1184 bool isAttributeOrStorageClass(TokenId tok) 1185 { 1186 switch(tok) 1187 { 1188 mixin(case_TOKs_AttributeOrStorageClass); 1189 return true; 1190 default: 1191 return false; 1192 } 1193 } 1194 1195 //-- GRAMMAR_BEGIN -- 1196 //Type: 1197 // BasicType 1198 // BasicType Declarator2 1199 // 1200 //Declarator2: 1201 // BasicType2 Declarator2 1202 // ( Declarator2 ) 1203 // ( Declarator2 ) DeclaratorSuffixes 1204 // 1205 class Type 1206 { 1207 static Action enter(Parser p) 1208 { 1209 p.pushState(&shiftBasicType); 1210 return BasicType.enter(p); 1211 } 1212 1213 static Action shiftBasicType(Parser p) 1214 { 1215 switch(p.tok.id) 1216 { 1217 mixin(BasicType2.case_TOKs); 1218 p.pushState(&shiftBasicType); 1219 return BasicType2.enter(p); 1220 1221 case TOK_lparen: 1222 // not implemented, better forward, it might also be constructor arguments 1223 // p.pushState(&shiftDeclarator2); 1224 // return Accept; 1225 1226 default: 1227 return Forward; 1228 } 1229 } 1230 1231 // entry point from EnumMember: Type Identifier = AssignExpression 1232 // and ForeachType: ref_opt Type_opt Identifier 1233 // assumes identifier pushed onto token stack 1234 static Action enterIdentifier(Parser p) 1235 { 1236 p.pushState(&shiftBasicType); 1237 return BasicType.enterIdentifier(p); 1238 } 1239 1240 // assumes modifier token on the info stack 1241 static Action enterTypeModifier(Parser p) 1242 { 1243 p.pushState(&shiftBasicType); 1244 return BasicType.shiftTypeModifier(p); 1245 } 1246 1247 static Action shiftDeclarator2(Parser p) 1248 { 1249 return p.notImplementedError(); 1250 } 1251 1252 } 1253 1254 //-- GRAMMAR_BEGIN -- 1255 //TypeWithModifier: 1256 // Type 1257 // const TypeWithModifier 1258 // immutable TypeWithModifier 1259 // inout TypeWithModifier 1260 // shared TypeWithModifier 1261 class TypeWithModifier 1262 { 1263 static Action enter(Parser p) 1264 { 1265 switch(p.tok.id) 1266 { 1267 case TOK_const: 1268 case TOK_immutable: 1269 case TOK_inout: 1270 case TOK_shared: 1271 p.pushToken(p.tok); 1272 p.pushState(&shiftModifier); 1273 return Accept; 1274 default: 1275 return Type.enter(p); 1276 } 1277 } 1278 1279 static Action shiftModifier(Parser p) 1280 { 1281 switch(p.tok.id) 1282 { 1283 case TOK_lparen: 1284 return Type.enterTypeModifier(p); 1285 1286 default: 1287 auto tok = p.popToken(); 1288 p.pushNode(new ast.ModifiedType(tok)); 1289 p.pushState(&shiftModifiedType); 1290 return enter(p); 1291 } 1292 } 1293 1294 static Action shiftModifiedType(Parser p) 1295 { 1296 p.popAppendTopNode!(ast.ModifiedType)(); 1297 return Forward; 1298 } 1299 } 1300 1301 //-- GRAMMAR_BEGIN -- 1302 //Parameters: 1303 // ( ParameterList ) 1304 // ( ) 1305 class Parameters 1306 { 1307 static Action enter(Parser p) 1308 { 1309 switch(p.tok.id) 1310 { 1311 case TOK_lparen: 1312 p.pushState(&shiftLparen); 1313 return Accept; 1314 default: 1315 return p.parseError("opening parenthesis expected in parameter list"); 1316 } 1317 } 1318 1319 static Action shiftLparen(Parser p) 1320 { 1321 if(p.tok.id == TOK_rparen) 1322 { 1323 p.pushNode(new ast.ParameterList(p.tok)); 1324 return Accept; 1325 } 1326 p.pushState(&shiftParameterList); 1327 return ParameterList.enter(p); 1328 } 1329 1330 static Action shiftParameterList(Parser p) 1331 { 1332 if(p.tok.id != TOK_rparen) 1333 return p.parseError("closing parenthesis expected for parameter list"); 1334 return Accept; 1335 } 1336 } 1337 1338 //-- GRAMMAR_BEGIN -- 1339 //ParameterList: 1340 // Parameter 1341 // Parameter , ParameterList 1342 // Parameter ... 1343 // ... 1344 class ParameterList 1345 { 1346 static Action enter(Parser p) 1347 { 1348 p.pushNode(new ast.ParameterList(p.tok)); 1349 return shift(p); 1350 } 1351 1352 static Action shift(Parser p) 1353 { 1354 switch(p.tok.id) 1355 { 1356 case TOK_dotdotdot: 1357 p.topNode!(ast.ParameterList)().anonymous_varargs = true; 1358 return Accept; 1359 default: 1360 p.pushState(&shiftParameter); 1361 return Parameter.enter(p); 1362 } 1363 } 1364 1365 static Action shiftParameter(Parser p) 1366 { 1367 p.popAppendTopNode!(ast.ParameterList)(); 1368 1369 switch(p.tok.id) 1370 { 1371 case TOK_dotdotdot: 1372 p.topNode!(ast.ParameterList)().varargs = true; 1373 return Accept; 1374 case TOK_comma: 1375 p.pushState(&shift); 1376 return Accept; 1377 default: 1378 return Forward; 1379 } 1380 } 1381 } 1382 1383 //-- GRAMMAR_BEGIN -- 1384 ///* Declarator replaced with ParameterDeclarator */ 1385 //Parameter: 1386 // InOut_opt ParameterDeclarator DefaultInitializerExpression_opt 1387 // 1388 //DefaultInitializerExpression: 1389 // = AssignExpression 1390 // = __FILE__ // already in primary expression 1391 // = __LINE__ // already in primary expression 1392 class Parameter 1393 { 1394 static Action enter(Parser p) 1395 { 1396 p.pushNode(new ast.Parameter(p.tok)); 1397 p.pushState(&shiftParameterDeclarator); 1398 1399 if(isInOut(p.tok.id)) 1400 { 1401 p.topNode!(ast.Parameter)().io = p.tok.id; 1402 p.pushState(&ParameterDeclarator.enter); 1403 return Accept; 1404 } 1405 return ParameterDeclarator.enter(p); 1406 } 1407 1408 static Action shiftParameterDeclarator(Parser p) 1409 { 1410 p.popAppendTopNode!(ast.Parameter)(); 1411 if(p.tok.id != TOK_assign) 1412 return Forward; 1413 p.pushState(&shiftInitializer); 1414 p.pushState(&AssignExpression.enter); 1415 return Accept; 1416 } 1417 1418 static Action shiftInitializer(Parser p) 1419 { 1420 p.popAppendTopNode!(ast.Parameter)(); 1421 return Forward; 1422 } 1423 } 1424 1425 //-- GRAMMAR_BEGIN -- 1426 //ParameterDeclarator: 1427 // StorageClasses_opt BasicType BasicTypes2_opt Declarator_opt 1428 // /*Identifier DeclaratorSuffixes_opt*/ 1429 class ParameterDeclarator 1430 { 1431 // very similar to Decl, combine? 1432 // differences: no auto, single Declarator only 1433 static Action enter(Parser p) 1434 { 1435 auto decl = new ast.ParameterDeclarator(p.tok); 1436 p.pushNode(decl); 1437 return shift(p); 1438 } 1439 1440 static Action shift(Parser p) 1441 { 1442 if(isTypeModifier(p.tok.id)) 1443 { 1444 // could be storage class or BasicType 1445 p.pushToken(p.tok); 1446 p.pushState(&shiftTypeModifier); 1447 return Accept; 1448 } 1449 if(isStorageClass(p.tok.id)) 1450 { 1451 auto decl = p.topNode!(ast.ParameterDeclarator)(); 1452 p.combineAttributes(decl.attr, tokenToAttribute(p.tok.id)); 1453 p.combineAnnotations(decl.annotation, tokenToAnnotation(p.tok.id)); 1454 p.pushState(&shiftStorageClass); 1455 return Accept; 1456 } 1457 p.pushState(&shiftBasicType); 1458 return BasicType.enter(p); 1459 } 1460 1461 // disambiguate "const x" and "const(int) x" 1462 // assumes modifier token on the info stack 1463 static Action shiftTypeModifier(Parser p) 1464 { 1465 if(p.tok.id == TOK_lparen) 1466 { 1467 p.pushState(&shiftBasicType); 1468 return BasicType.shiftTypeModifier(p); 1469 } 1470 1471 auto decl = p.topNode!(ast.ParameterDeclarator)(); 1472 Token tok = p.popToken(); 1473 p.combineAttributes(decl.attr, tokenToAttribute(tok.id)); 1474 return shift(p); 1475 } 1476 1477 static Action shiftStorageClass(Parser p) 1478 { 1479 if(isTypeModifier(p.tok.id)) 1480 { 1481 // could be storage class or BasicType 1482 p.pushToken(p.tok); 1483 p.pushState(&shiftTypeModifier); 1484 return Accept; 1485 } 1486 if(isStorageClass(p.tok.id)) 1487 { 1488 auto decl = p.topNode!(ast.ParameterDeclarator)(); 1489 p.combineAttributes(decl.attr, tokenToAttribute(p.tok.id)); 1490 p.combineAnnotations(decl.annotation, tokenToAnnotation(p.tok.id)); 1491 p.pushState(&shiftStorageClass); 1492 return Accept; 1493 } 1494 p.pushState(&shiftBasicType); 1495 return BasicType.enter(p); 1496 } 1497 1498 // switch here from TemplateValueParameter when detecting a declaration after an identifier 1499 // assumes identifier token on the info stack 1500 static Action enterTypeIdentifier(Parser p) 1501 { 1502 auto decl = new ast.ParameterDeclarator(p.tok); 1503 p.pushNode(decl); 1504 1505 p.pushState(&shiftBasicType); 1506 return BasicType.enterIdentifier(p); 1507 } 1508 1509 static Action shiftBasicType(Parser p) 1510 { 1511 switch(p.tok.id) 1512 { 1513 mixin(BasicType2.case_TOKs); 1514 p.pushState(&shiftBasicTypes2); 1515 return BasicTypes2.enter(p); 1516 default: 1517 return shiftBasicTypes2(p); 1518 } 1519 } 1520 1521 static Action shiftBasicTypes2(Parser p) 1522 { 1523 p.popAppendTopNode!(ast.ParameterDeclarator, ast.Type)(); 1524 if(p.tok.id != TOK_Identifier) 1525 return Forward; 1526 p.pushState(&shiftDeclarator); 1527 return Declarator.enter(p); 1528 } 1529 1530 static Action shiftDeclarator(Parser p) 1531 { 1532 p.popAppendTopNode!(ast.ParameterDeclarator)(); 1533 return Forward; 1534 } 1535 1536 } 1537 1538 //-- GRAMMAR_BEGIN -- 1539 //InOut: 1540 // in 1541 // out 1542 // ref 1543 // lazy 1544 // scope /* ? */ 1545 enum case_TOKs_InOut = q{ 1546 case TOK_in: 1547 case TOK_out: 1548 case TOK_ref: 1549 case TOK_lazy: 1550 case TOK_scope: 1551 }; 1552 bool isInOut(TokenId tok) 1553 { 1554 switch(tok) 1555 { 1556 mixin(case_TOKs_InOut); 1557 return true; 1558 default: 1559 return false; 1560 } 1561 } 1562 1563 //-- GRAMMAR_BEGIN -- 1564 //FunctionAttributes: 1565 // FunctionAttribute 1566 // FunctionAttribute FunctionAttributes 1567 // 1568 //FunctionAttribute: 1569 // nothrow 1570 // pure 1571 enum case_TOKs_FunctionAttribute = q{ 1572 case TOK_nothrow: 1573 case TOK_pure: 1574 case TOK_safe: 1575 case TOK_system: 1576 case TOK_trusted: 1577 case TOK_property: 1578 case TOK_disable: 1579 case TOK_nogc: 1580 }; 1581 1582 bool isFunctionAttribute(TokenId tok) 1583 { 1584 switch(tok) 1585 { 1586 mixin(case_TOKs_FunctionAttribute); 1587 return true; 1588 default: 1589 return false; 1590 } 1591 } 1592 1593 //-- GRAMMAR_BEGIN -- 1594 //MemberFunctionAttributes: 1595 // MemberFunctionAttribute 1596 // MemberFunctionAttribute MemberFunctionAttributes 1597 // 1598 //MemberFunctionAttribute: 1599 // const 1600 // immutable 1601 // inout 1602 // shared 1603 // FunctionAttribute 1604 // 1605 enum case_TOKs_MemberFunctionAttribute = q{ 1606 case TOK_const: 1607 case TOK_immutable: 1608 case TOK_inout: 1609 case TOK_shared: 1610 } ~ case_TOKs_FunctionAttribute; 1611 1612 bool isMemberFunctionAttribute(TokenId tok) 1613 { 1614 switch(tok) 1615 { 1616 mixin(case_TOKs_MemberFunctionAttribute); 1617 return true; 1618 default: 1619 return false; 1620 } 1621 }