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.expr; 10 11 import vdc.util; 12 import vdc.lexer; 13 import vdc.parser.engine; 14 import vdc.parser.decl; 15 import vdc.parser.tmpl; 16 import vdc.parser.misc; 17 import vdc.parser.aggr; 18 import ast = vdc.ast.all; 19 20 alias ast.PREC PREC; 21 22 //////////////////////////////////////////////////////////////// 23 //-- GRAMMAR_BEGIN -- 24 //Expression: 25 // CommaExpression 26 class Expression 27 { 28 static Action enter(Parser p) 29 { 30 return CommaExpression.enter(p); 31 } 32 } 33 34 class BinaryExpression : Expression 35 { 36 } 37 38 mixin template BinaryExpr(ASTNodeType, PREC prec, string recursion, SubType, ops...) 39 { 40 shared static this() 41 { 42 foreach(o; ops) 43 { 44 ast.precedence[o] = prec; 45 ast.recursion[o] = recursion[0]; 46 } 47 } 48 49 mixin BinaryNode!(ASTNodeType, recursion, SubType, ops); 50 } 51 52 //-- GRAMMAR_BEGIN -- 53 //CommaExpression: 54 // AssignExpression 55 // AssignExpression , CommaExpression 56 class CommaExpression : BinaryExpression 57 { 58 mixin BinaryExpr!(ast.CommaExpression, PREC.expr, "R", AssignExpression, TOK_comma); 59 } 60 61 //-- GRAMMAR_BEGIN -- 62 //AssignExpression: 63 // ConditionalExpression 64 // ConditionalExpression = AssignExpression 65 // ConditionalExpression += AssignExpression 66 // ConditionalExpression -= AssignExpression 67 // ConditionalExpression *= AssignExpression 68 // ConditionalExpression /= AssignExpression 69 // ConditionalExpression %= AssignExpression 70 // ConditionalExpression &= AssignExpression 71 // ConditionalExpression |= AssignExpression 72 // ConditionalExpression ^= AssignExpression 73 // ConditionalExpression ~= AssignExpression 74 // ConditionalExpression <<= AssignExpression 75 // ConditionalExpression >>= AssignExpression 76 // ConditionalExpression >>>= AssignExpression 77 // ConditionalExpression ^^= AssignExpression 78 class AssignExpression : BinaryExpression 79 { 80 mixin BinaryExpr!(ast.AssignExpression, PREC.assign, "R", ConditionalExpression, 81 TOK_assign, TOK_addass, TOK_minass, TOK_mulass, TOK_divass, TOK_modass, 82 TOK_andass, TOK_orass, TOK_xorass, TOK_catass, TOK_shlass, TOK_shrass, 83 TOK_ushrass, TOK_powass); 84 } 85 86 //-- GRAMMAR_BEGIN -- 87 //ConditionalExpression: 88 // OrOrExpression 89 // OrOrExpression ? Expression : ConditionalExpression 90 class ConditionalExpression : Expression 91 { 92 mixin TernaryNode!(ast.ConditionalExpression, OrOrExpression, TOK_question, Expression, TOK_colon); 93 } 94 95 //-- GRAMMAR_BEGIN -- 96 //OrOrExpression: 97 // AndAndExpression 98 // OrOrExpression || AndAndExpression 99 class OrOrExpression : BinaryExpression 100 { 101 mixin BinaryExpr!(ast.OrOrExpression, PREC.oror, "L", AndAndExpression, TOK_oror); 102 } 103 104 //-- GRAMMAR_BEGIN -- 105 //AndAndExpression: 106 // OrExpression 107 // AndAndExpression && OrExpression 108 class AndAndExpression : BinaryExpression 109 { 110 mixin BinaryExpr!(ast.AndAndExpression, PREC.andand, "L", OrExpression, TOK_andand); 111 } 112 113 //-- GRAMMAR_BEGIN -- 114 //OrExpression: 115 // XorExpression 116 // OrExpression | XorExpression 117 class OrExpression : BinaryExpression 118 { 119 mixin BinaryExpr!(ast.OrExpression, PREC.or, "L", XorExpression, TOK_or); 120 } 121 122 //-- GRAMMAR_BEGIN -- 123 //XorExpression: 124 // AndExpression 125 // XorExpression ^ AndExpression 126 class XorExpression : BinaryExpression 127 { 128 mixin BinaryExpr!(ast.XorExpression, PREC.xor, "L", AndExpression, TOK_xor); 129 } 130 131 //-- GRAMMAR_BEGIN -- 132 //AndExpression: 133 // CmpExpression 134 // AndExpression & CmpExpression 135 class AndExpression : BinaryExpression 136 { 137 mixin BinaryExpr!(ast.AndExpression, PREC.and, "L", CmpExpression, TOK_and); 138 } 139 140 //-- GRAMMAR_BEGIN -- 141 //CmpExpression: 142 // ShiftExpression 143 // EqualExpression 144 // IdentityExpression 145 // RelExpression 146 // InExpression 147 // 148 //EqualExpression: 149 // ShiftExpression == ShiftExpression 150 // ShiftExpression != ShiftExpression 151 // 152 //IdentityExpression: 153 // ShiftExpression is ShiftExpression 154 // ShiftExpression !is ShiftExpression 155 // 156 //RelExpression: 157 // ShiftExpression < ShiftExpression 158 // ShiftExpression <= ShiftExpression 159 // ShiftExpression > ShiftExpression 160 // ShiftExpression >= ShiftExpression 161 // ShiftExpression !<>= ShiftExpression 162 // ShiftExpression !<> ShiftExpression 163 // ShiftExpression <> ShiftExpression 164 // ShiftExpression <>= ShiftExpression 165 // ShiftExpression !> ShiftExpression 166 // ShiftExpression !>= ShiftExpression 167 // ShiftExpression !< ShiftExpression 168 // ShiftExpression !<= ShiftExpression 169 // 170 //InExpression: 171 // ShiftExpression in ShiftExpression 172 // ShiftExpression !in ShiftExpression 173 class CmpExpression : BinaryExpression 174 { 175 static if(!supportUnorderedCompareOps) 176 mixin BinaryExpr!(ast.CmpExpression, PREC.rel, "N", ShiftExpression, 177 TOK_equal, TOK_notequal, TOK_is, TOK_notidentity, 178 TOK_lt, TOK_le, TOK_gt, TOK_ge, 179 // TOK_unord, TOK_ue, TOK_lg, TOK_leg, TOK_ule, TOK_ul, TOK_uge, TOK_ug, 180 TOK_in, TOK_notcontains); 181 else 182 mixin BinaryExpr!(ast.CmpExpression, PREC.rel, "N", ShiftExpression, 183 TOK_equal, TOK_notequal, TOK_is, TOK_notidentity, 184 TOK_lt, TOK_le, TOK_gt, TOK_ge, 185 // TOK_unord, TOK_ue, TOK_lg, TOK_leg, TOK_ule, TOK_ul, TOK_uge, TOK_ug, 186 TOK_in, TOK_notcontains); 187 } 188 189 //-- GRAMMAR_BEGIN -- 190 //ShiftExpression: 191 // AddExpression 192 // ShiftExpression << AddExpression 193 // ShiftExpression >> AddExpression 194 // ShiftExpression >>> AddExpression 195 class ShiftExpression : BinaryExpression 196 { 197 mixin BinaryExpr!(ast.ShiftExpression, PREC.shift, "L", AddExpression, TOK_shl, TOK_shr, TOK_ushr); 198 } 199 200 //-- GRAMMAR_BEGIN -- 201 //AddExpression: 202 // MulExpression 203 // AddExpression + MulExpression 204 // AddExpression - MulExpression 205 // CatExpression: 206 //CatExpression: 207 // AddExpression ~ MulExpression 208 class AddExpression : BinaryExpression 209 { 210 mixin BinaryExpr!(ast.AddExpression, PREC.add, "L", MulExpression, TOK_add, TOK_min, TOK_tilde); 211 } 212 213 //-- GRAMMAR_BEGIN -- 214 //MulExpression: 215 // SignExpression 216 // MulExpression * SignExpression 217 // MulExpression / SignExpression 218 // MulExpression % SignExpression 219 class MulExpression : BinaryExpression 220 { 221 mixin BinaryExpr!(ast.MulExpression, PREC.mul, "L", SignExpression, TOK_mul, TOK_div, TOK_mod); 222 } 223 224 //-- GRAMMAR_BEGIN -- 225 //SignExpression: 226 // PowExpression 227 // + SignExpression 228 // - SignExpression 229 class SignExpression : Expression 230 { 231 static Action enter(Parser p) 232 { 233 switch(p.tok.id) 234 { 235 case TOK_min: 236 case TOK_add: 237 auto expr = new ast.UnaryExpression(p.tok); 238 p.pushNode(expr); 239 p.pushState(&shift); 240 p.pushState(&enter); 241 return Accept; 242 default: 243 return PowExpression.enter(p); 244 } 245 } 246 247 static Action shift(Parser p) 248 { 249 p.popAppendTopNode!(ast.UnaryExpression)(); 250 return Forward; 251 } 252 } 253 254 //-- GRAMMAR_BEGIN -- 255 //PowExpression: 256 // UnaryExpression 257 // UnaryExpression ^^ SignExpression 258 class PowExpression : BinaryExpression 259 { 260 static Action shiftExponent(Parser p) 261 { 262 p.popAppendTopNode!(ast.PowExpression)(); 263 return Forward; 264 } 265 266 static Action shiftPow(Parser p) 267 { 268 switch(p.tok.id) 269 { 270 case TOK_pow: 271 auto pe = new ast.PowExpression(p.tok); 272 p.appendReplaceTopNode(pe); 273 p.pushState(&shiftExponent); 274 p.pushState(&SignExpression.enter); 275 return Accept; 276 default: 277 return Forward; 278 } 279 } 280 mixin stateEnterClass!(UnaryExpression, NoASTNode, shiftPow); 281 } 282 283 //-- GRAMMAR_BEGIN -- 284 //UnaryExpression: 285 // PostfixExpression 286 // & UnaryExpression 287 // ++ UnaryExpression 288 // -- UnaryExpression 289 // * UnaryExpression 290 // - UnaryExpression 291 // + UnaryExpression 292 // ! UnaryExpression 293 // ~ UnaryExpression 294 // NewExpression 295 // DeleteExpression 296 // CastExpression 297 // /*NewAnonClassExpression*/ 298 // 299 // DeleteExpression: 300 // delete UnaryExpression 301 class UnaryExpression : Expression 302 { 303 static Action enter(Parser p) 304 { 305 switch(p.tok.id) 306 { 307 case TOK_and: 308 case TOK_plusplus: 309 case TOK_minusminus: 310 case TOK_mul: 311 case TOK_min: 312 case TOK_add: 313 case TOK_not: 314 case TOK_tilde: 315 case TOK_delete: 316 auto expr = new ast.UnaryExpression(p.tok); 317 p.pushNode(expr); 318 p.pushState(&shift); 319 p.pushState(&enter); 320 return Accept; 321 case TOK_new: 322 return NewExpression.enter(p); 323 case TOK_cast: 324 return CastExpression.enter(p); 325 default: 326 return PostfixExpression.enter(p); 327 } 328 } 329 330 static Action shift(Parser p) 331 { 332 p.popAppendTopNode!(ast.UnaryExpression)(); 333 return Forward; 334 } 335 } 336 337 //-- GRAMMAR_BEGIN -- 338 //NewExpression: 339 // NewArguments Type [ AssignExpression ] 340 // NewArguments Type ( ArgumentList ) 341 // NewArguments Type 342 // NewArguments ClassArguments BaseClassList_opt { DeclDefs_opt } 343 // 344 //NewArguments: 345 // new ( ArgumentList ) 346 // new ( ) 347 // new 348 // 349 //ClassArguments: 350 // class ( ArgumentList ) 351 // class ( ) 352 // class 353 class NewExpression : UnaryExpression 354 { 355 static Action enter(Parser p) 356 { 357 p.pushNode(new ast.NewExpression(p.tok)); 358 switch(p.tok.id) 359 { 360 case TOK_new: 361 p.pushState(&shiftNew); 362 return Accept; 363 default: 364 return p.parseError("new expected"); 365 } 366 } 367 368 static Action shiftNew(Parser p) 369 { 370 switch(p.tok.id) 371 { 372 case TOK_lparen: 373 p.pushState(&shiftNewLparen); 374 return Accept; 375 case TOK_class: 376 p.pushState(&shiftClass); 377 return AnonymousClass.enter(p); 378 default: 379 p.pushState(&shiftType); 380 return Type.enter(p); 381 } 382 } 383 384 static Action shiftType(Parser p) 385 { 386 p.popAppendTopNode!(ast.NewExpression); 387 switch(p.tok.id) 388 { 389 // [] are parsed as part of the type 390 case TOK_lparen: 391 p.pushState(&shiftTypeLparen); 392 return Accept; 393 default: 394 return Forward; 395 } 396 } 397 398 static Action shiftTypeLparen(Parser p) 399 { 400 switch(p.tok.id) 401 { 402 case TOK_rparen: 403 return Accept; // empty argument list as good as none 404 default: 405 p.pushState(&shiftArgumentList); 406 return ArgumentList.enter(p); 407 } 408 } 409 static Action shiftArgumentList(Parser p) 410 { 411 switch(p.tok.id) 412 { 413 // [] are parsed as part of the type 414 case TOK_rparen: 415 p.popAppendTopNode!(ast.NewExpression); 416 return Accept; 417 default: 418 return p.parseError("')' expected"); 419 } 420 } 421 422 static Action shiftNewLparen(Parser p) 423 { 424 p.pushState(&shiftNewArgumentList); 425 return ArgumentList.enter(p); 426 } 427 428 static Action shiftNewArgumentList(Parser p) 429 { 430 p.popAppendTopNode!(ast.NewExpression); 431 p.topNode!(ast.NewExpression).hasNewArgs = true; 432 433 switch(p.tok.id) 434 { 435 case TOK_rparen: 436 p.pushState(&shiftRparen); 437 return Accept; 438 default: 439 return p.parseError("')' expected for new argument list"); 440 } 441 } 442 443 static Action shiftRparen(Parser p) 444 { 445 switch(p.tok.id) 446 { 447 case TOK_class: 448 p.pushState(&shiftClass); 449 return AnonymousClass.enter(p); 450 default: 451 p.pushState(&shiftType); 452 return Type.enter(p); 453 } 454 } 455 456 static Action shiftClass(Parser p) 457 { 458 p.popAppendTopNode!(ast.NewExpression); 459 return Forward; 460 } 461 } 462 463 //-- GRAMMAR_BEGIN -- 464 // AnonymousClass: 465 // ClassArguments BaseClassList_opt { DeclDefs_opt } 466 class AnonymousClass 467 { 468 static Action enter(Parser p) 469 { 470 switch(p.tok.id) 471 { 472 case TOK_class: 473 p.pushNode(new ast.AnonymousClassType(p.tok)); 474 p.pushState(&shiftClass); 475 return Accept; 476 default: 477 return p.parseError("class expected"); 478 } 479 } 480 static Action shiftClass(Parser p) 481 { 482 switch(p.tok.id) 483 { 484 case TOK_lparen: 485 p.pushState(&shiftLparen); 486 return Accept; 487 default: 488 p.pushState(&shiftClassDeclaration); 489 return AggregateDeclaration.enterAnonymousClass(p); 490 } 491 } 492 493 static Action shiftLparen(Parser p) 494 { 495 switch(p.tok.id) 496 { 497 case TOK_rparen: 498 p.topNode!(ast.AnonymousClassType).addMember(new ast.ArgumentList(p.tok)); 499 p.pushState(&shiftClassDeclaration); 500 p.pushState(&AggregateDeclaration.enterAnonymousClass); 501 return Accept; 502 default: 503 p.pushState(&shiftArgumentList); 504 return ArgumentList.enter(p); 505 } 506 } 507 508 static Action shiftClassDeclaration(Parser p) 509 { 510 p.popAppendTopNode!(ast.AnonymousClassType); 511 return Forward; 512 } 513 514 static Action shiftArgumentList(Parser p) 515 { 516 switch(p.tok.id) 517 { 518 case TOK_rparen: 519 p.popAppendTopNode!(ast.AnonymousClassType); 520 p.pushState(&shiftClassDeclaration); 521 p.pushState(&AggregateDeclaration.enterAnonymousClass); 522 return Accept; 523 default: 524 return p.parseError("')' expected"); 525 } 526 } 527 } 528 529 //-- GRAMMAR_BEGIN -- 530 //CastExpression: 531 // cast ( Type ) UnaryExpression 532 // cast ( ) UnaryExpression 533 // cast ( const ) UnaryExpression 534 // cast ( const shared ) UnaryExpression 535 // cast ( immutable ) UnaryExpression 536 // cast ( inout ) UnaryExpression 537 // cast ( inout shared ) UnaryExpression 538 // cast ( shared ) UnaryExpression 539 // cast ( shared const ) UnaryExpression 540 // cast ( shared inout ) UnaryExpression 541 class CastExpression : UnaryExpression 542 { 543 mixin stateAppendClass!(UnaryExpression, Parser.forward) stateExpression; 544 545 static Action shiftType(Parser p) 546 { 547 p.popAppendTopNode!(ast.CastExpression)(); 548 switch(p.tok.id) 549 { 550 case TOK_rparen: 551 p.pushState(&stateExpression.shift); 552 return Accept; 553 default: 554 return p.parseError("')' expected"); 555 } 556 } 557 558 mixin stateShiftToken!(TOK_rparen, stateExpression.shift) stateRparen; 559 560 static Action shiftModifier(Parser p) 561 { 562 Token tok; 563 switch(p.tok.id) 564 { 565 case TOK_rparen: 566 tok = p.popToken(); 567 p.topNode!(ast.CastExpression)().attr = tokenToAttribute(tok.id); 568 p.pushState(&stateExpression.shift); 569 return Accept; 570 571 case TOK_const: 572 case TOK_inout: 573 tok = p.topToken(); 574 if(tok.id != TOK_shared) 575 goto default; 576 L_combineAttr: 577 tok = p.popToken(); 578 auto attr = tokenToAttribute(tok.id); 579 p.combineAttributes(attr, tokenToAttribute(p.tok.id)); 580 p.topNode!(ast.CastExpression)().attr = attr; 581 p.pushState(&stateRparen.shift); 582 return Accept; 583 584 case TOK_shared: 585 tok = p.topToken(); 586 if(tok.id != TOK_inout && tok.id != TOK_const) 587 goto default; 588 goto L_combineAttr; 589 590 default: 591 p.pushState(&shiftType); 592 return Type.enterTypeModifier(p); 593 } 594 } 595 596 static Action stateType(Parser p) 597 { 598 switch(p.tok.id) 599 { 600 case TOK_rparen: 601 p.pushState(&stateExpression.shift); 602 return Accept; 603 case TOK_const: 604 case TOK_immutable: 605 case TOK_inout: 606 case TOK_shared: 607 p.pushToken(p.tok); 608 p.pushState(&shiftModifier); 609 return Accept; 610 default: 611 p.pushState(&shiftType); 612 return Type.enter(p); 613 } 614 } 615 616 mixin stateShiftToken!(TOK_lparen, stateType) stateLparen; 617 618 mixin stateEnterToken!(TOK_cast, ast.CastExpression, stateLparen.shift); 619 } 620 621 //-- GRAMMAR_BEGIN -- 622 //PostfixExpression: 623 // PrimaryExpression 624 // PostfixExpression . IdentifierOrTemplateInstance 625 // PostfixExpression . NewExpression 626 // PostfixExpression ++ 627 // PostfixExpression -- 628 // PostfixExpression ( ) 629 // PostfixExpression ( ArgumentList ) 630 // IndexExpression 631 // SliceExpression 632 // 633 //IndexExpression: 634 // PostfixExpression [ ArgumentList ] 635 // 636 //SliceExpression: 637 // PostfixExpression [ ] 638 // PostfixExpression [ AssignExpression .. AssignExpression ] 639 class PostfixExpression : Expression 640 { 641 static Action enter(Parser p) 642 { 643 p.pushState(&shift); 644 return PrimaryExpression.enter(p); 645 } 646 647 static Action shift(Parser p) 648 { 649 switch(p.tok.id) 650 { 651 case TOK_plusplus: 652 case TOK_minusminus: 653 p.appendReplaceTopNode(new ast.PostfixExpression(p.tok)); 654 return Accept; 655 656 case TOK_dot: 657 p.pushState(&shiftDot); 658 p.appendReplaceTopNode(new ast.DotExpression(p.tok)); 659 return Accept; 660 661 case TOK_lparen: 662 p.pushState(&shiftLParen); 663 p.appendReplaceTopNode(new ast.PostfixExpression(p.tok)); 664 return Accept; 665 666 case TOK_lbracket: 667 p.pushState(&shiftLBracket); 668 p.appendReplaceTopNode(new ast.PostfixExpression(p.tok)); 669 return Accept; 670 671 default: 672 return Forward; 673 } 674 } 675 676 static Action shiftDot(Parser p) 677 { 678 switch(p.tok.id) 679 { 680 case TOK_Identifier: 681 auto expr = p.topNode!(ast.DotExpression)(); 682 expr.id = TOK_dot; 683 p.pushState(&shiftIdentifierOrTemplateInstance); 684 return IdentifierOrTemplateInstance.enter(p); 685 686 case TOK_RECOVER: 687 auto expr = p.topNode!(ast.DotExpression)(); 688 expr.id = TOK_dot; 689 auto id = new ast.Identifier(p.tok); 690 expr.addMember(id); 691 return Forward; 692 693 case TOK_new: 694 p.pushState(&shiftNewExpression); 695 return NewExpression.enter(p); 696 697 default: 698 return p.parseError("identifier or new expected after '.'"); 699 } 700 } 701 702 static Action shiftIdentifierOrTemplateInstance(Parser p) 703 { 704 p.popAppendTopNode!(ast.PostfixExpression, ast.Identifier)(); 705 return shift(p); 706 } 707 708 static Action shiftLParen(Parser p) 709 { 710 if(p.tok.id == TOK_rparen) 711 { 712 p.pushState(&shift); 713 return Accept; 714 } 715 716 p.pushState(&shiftRParen); 717 return ArgumentList.enter(p); // ArgumentList also starts with AssignExpression 718 } 719 720 static Action shiftRParen(Parser p) 721 { 722 if(p.tok.id != TOK_rparen) 723 return p.parseError("closing parenthesis expected"); 724 725 p.popAppendTopNode!(ast.PostfixExpression)(); 726 p.pushState(&shift); 727 return Accept; 728 } 729 730 static Action shiftLBracket(Parser p) 731 { 732 if(p.tok.id == TOK_rbracket) 733 { 734 p.pushState(&shift); 735 return Accept; 736 } 737 738 p.pushState(&shiftRBracket); 739 return ArgumentList.enter(p); 740 } 741 742 static Action shiftRBracket(Parser p) 743 { 744 if(p.tok.id == TOK_slice) 745 { 746 // throw away the argument list, just use the expression 747 ast.Node arglist = p.popNode(); 748 if (arglist.members.length != 1) 749 return p.parseError("a single expression is expected before .."); 750 751 p.topNode().addMember(arglist.removeMember(0)); 752 p.pushState(&shiftSlice); 753 p.pushState(&AssignExpression.enter); 754 return Accept; 755 } 756 else if(p.tok.id != TOK_rbracket) 757 return p.parseError("closing bracket or .. expected"); 758 759 p.popAppendTopNode!(ast.PostfixExpression)(); 760 p.pushState(&shift); 761 return Accept; 762 } 763 764 static Action shiftSlice(Parser p) 765 { 766 if(p.tok.id != TOK_rbracket) 767 return p.parseError("closing bracket expected"); 768 769 p.popAppendTopNode!(ast.PostfixExpression)(); 770 p.pushState(&shift); 771 return Accept; 772 } 773 774 static Action shiftNewExpression(Parser p) 775 { 776 p.popAppendTopNode!(ast.PostfixExpression)(); 777 auto expr = p.topNode!(ast.PostfixExpression)(); 778 expr.id = TOK_new; 779 return Forward; 780 } 781 } 782 783 //-- GRAMMAR_BEGIN -- 784 //ArgumentList: 785 // AssignExpression 786 // AssignExpression , 787 // AssignExpression , ArgumentList 788 class ArgumentList 789 { 790 mixin ListNode!(ast.ArgumentList, AssignExpression, TOK_comma, true); 791 } 792 793 //-- GRAMMAR_BEGIN -- 794 //Arguments: 795 // ( ) 796 // ( ArgumentList ) 797 class Arguments 798 { 799 mixin SequenceNode!(NoASTNode, TOK_lparen, EmptyArgumentList, TOK_rparen); 800 } 801 802 class EmptyArgumentList 803 { 804 mixin ListNode!(ast.ArgumentList, AssignExpression, TOK_comma, false, true); 805 } 806 807 //-- GRAMMAR_BEGIN -- 808 //PrimaryExpression: 809 // IdentifierOrTemplateInstance 810 // . IdentifierOrTemplateInstance 811 // this 812 // super 813 // null 814 // true 815 // false 816 // $ 817 // __FILE__ 818 // __LINE__ 819 // IntegerLiteral 820 // FloatLiteral 821 // CharacterLiteral 822 // StringLiteral 823 // ArrayLiteral 824 // AssocArrayLiteral 825 // Lambda 826 // FunctionLiteral 827 // StructLiteral // deprecated 828 // AssertExpression 829 // MixinExpression 830 // ImportExpression 831 // TypeidExpression 832 // IsExpression 833 // ( Expression ) 834 // BasicType . IdentifierOrTemplateInstance 835 // Typeof . IdentifierOrTemplateInstance 836 // ( Type ) . IdentifierOrTemplateInstance 837 // BasicType Arguments 838 // Typeof Arguments 839 // ( Type ) Arguments 840 // TraitsExpression 841 842 class PrimaryExpression : Expression 843 { 844 static Action enter(Parser p) 845 { 846 switch(p.tok.id) 847 { 848 case TOK_typeid: 849 return TypeIdExpression.enter(p); 850 case TOK_is: 851 return IsExpression.enter(p); 852 case TOK_notidentity: 853 return IsExpression.enterNotIs(p); 854 case TOK_import: 855 return ImportExpression.enter(p); 856 case TOK_mixin: 857 return MixinExpression.enter(p); 858 case TOK_assert: 859 return AssertExpression.enter(p); 860 case TOK___traits: 861 return TraitsExpression.enter(p); 862 863 case TOK_this: 864 case TOK_super: 865 case TOK_null: 866 case TOK_true: 867 case TOK_false: 868 case TOK_dollar: 869 case TOK___FILE__: 870 case TOK___LINE__: 871 case TOK___FUNCTION__: 872 case TOK___PRETTY_FUNCTION__: 873 case TOK___MODULE__: 874 auto expr = new ast.PrimaryExpression(p.tok); 875 p.pushNode(expr); 876 return Accept; 877 878 case TOK_typeof: // cannot make this part of Type, because it will also eat the property 879 p.pushState(&shiftType); 880 return Typeof.enter(p); 881 882 case TOK___vector: 883 mixin(case_TOKs_TypeModifier); 884 mixin(case_TOKs_BasicTypeX); 885 p.pushState(&shiftType); 886 return Type.enter(p); 887 888 case TOK_dot: 889 p.pushState(&shiftDot); 890 return Accept; 891 case TOK_Identifier: 892 p.pushToken(p.tok); 893 p.pushState(&shiftIdentifier); 894 return Accept; 895 896 case TOK_IntegerLiteral: 897 p.pushNode(new ast.IntegerLiteralExpression(p.tok)); 898 return Accept; 899 case TOK_FloatLiteral: 900 p.pushNode(new ast.FloatLiteralExpression(p.tok)); 901 return Accept; 902 case TOK_CharacterLiteral: 903 p.pushNode(new ast.CharacterLiteralExpression(p.tok)); 904 return Accept; 905 case TOK_StringLiteral: 906 p.pushNode(new ast.StringLiteralExpression(p.tok)); 907 p.pushState(&shiftStringLiteral); 908 return Accept; 909 910 case TOK_lbracket: 911 return ArrayLiteral.enter(p); 912 913 case TOK_delegate: 914 case TOK_function: 915 return FunctionLiteral!true.enter(p); // SPEC: allowing lambda not in the language spec 916 case TOK_lcurly: 917 p.pushRollback(&rollbackFunctionLiteralFailure); 918 p.pushState(&shiftFunctionLiteral); 919 return FunctionLiteral!false.enter(p); 920 921 case TOK_lparen: 922 p.pushRollback(&rollbackExpressionFailure); 923 p.pushState(&shiftLparenExpr); 924 p.pushState(&Expression.enter); 925 return Accept; 926 927 default: 928 return p.parseError("primary expression expected"); 929 } 930 } 931 932 static Action shiftIdentifier(Parser p) 933 { 934 switch(p.tok.id) 935 { 936 case TOK_lambda: 937 // id => expr 938 auto tok = p.popToken(); 939 auto lambda = new ast.Lambda(p.tok); 940 auto pdecl = new ast.ParameterDeclarator; 941 auto type = new ast.AutoType; 942 auto id = new ast.Declarator(tok); 943 pdecl.addMember(type); 944 pdecl.addMember(id); 945 auto pl = new ast.ParameterList; 946 pl.addMember(pdecl); 947 lambda.addMember(pl); 948 p.pushNode(lambda); 949 p.pushState(&shiftLambda); 950 p.pushState(&AssignExpression.enter); 951 return Accept; 952 953 default: 954 auto tok = p.topToken(); 955 p.pushNode(new ast.IdentifierExpression(tok)); 956 p.pushState(&shiftIdentifierOrTemplateInstance); 957 return IdentifierOrTemplateInstance.enterIdentifier(p); 958 } 959 } 960 961 static Action shiftLambda(Parser p) 962 { 963 p.popAppendTopNode!(ast.Lambda)(); 964 return Forward; 965 } 966 967 // ( Expression ) 968 // ( Type ) . Identifier 969 // FunctionLiteral: ParameterAttributes FunctionBody 970 static Action shiftLparenExpr(Parser p) 971 { 972 if(p.tok.id != TOK_rparen) 973 return p.parseError("closing parenthesis expected"); 974 975 p.pushState(&shiftRparenExpr); 976 return Accept; 977 } 978 static Action shiftRparenExpr(Parser p) 979 { 980 if(p.tok.id == TOK_lcurly || p.tok.id == TOK_lambda) 981 return Reject; 982 983 p.popRollback(); 984 return Forward; 985 } 986 987 988 static Action rollbackExpressionFailure(Parser p) 989 { 990 assert(p.tok.id == TOK_lparen); 991 p.pushRollback(&rollbackTypeFailure); 992 p.pushState(&shiftLparenType); 993 p.pushState(&Type.enter); 994 return Accept; 995 } 996 997 static Action rollbackFunctionLiteralFailure(Parser p) 998 { 999 assert(p.tok.id == TOK_lcurly || p.tok.id == TOK_lambda); 1000 return StructLiteral.enter(p); 1001 } 1002 1003 static Action shiftFunctionLiteral(Parser p) 1004 { 1005 p.popRollback(); 1006 return Forward; 1007 } 1008 1009 static Action shiftLparenType(Parser p) 1010 { 1011 if(p.tok.id != TOK_rparen) 1012 return p.parseError("closing parenthesis expected"); 1013 p.pushState(&shiftLparenTypeDot); 1014 return Accept; 1015 } 1016 static Action shiftLparenTypeDot(Parser p) 1017 { 1018 switch(p.tok.id) 1019 { 1020 case TOK_dot: 1021 p.popRollback(); 1022 p.appendReplaceTopNode(new ast.TypeProperty(p.tok)); 1023 p.pushState(&shiftTypeDot); 1024 p.pushState(&IdentifierOrTemplateInstance.enter); 1025 return Accept; 1026 case TOK_lparen: 1027 p.popRollback(); 1028 p.appendReplaceTopNode(new ast.StructConstructor(p.tok)); 1029 p.pushState(&shiftStructArguments); 1030 return Arguments.enter(p); 1031 default: 1032 return p.parseError("'.' expected for type property"); 1033 } 1034 } 1035 1036 static Action rollbackTypeFailure(Parser p) 1037 { 1038 assert(p.tok.id == TOK_lparen); 1039 return FunctionLiteral!true.enter(p); 1040 } 1041 1042 static Action shiftDot(Parser p) 1043 { 1044 if(p.tok.id != TOK_Identifier) 1045 return p.parseError("identifier expected"); 1046 1047 auto id = new ast.IdentifierExpression(p.tok); 1048 id.global = true; 1049 p.pushNode(id); 1050 1051 p.pushState(&shiftIdentifierOrTemplateInstance); 1052 return IdentifierOrTemplateInstance.enter(p); 1053 } 1054 1055 static Action shiftIdentifierOrTemplateInstance(Parser p) 1056 { 1057 p.popAppendTopNode!(ast.IdentifierExpression, ast.Identifier)(); 1058 return Forward; 1059 } 1060 1061 // BasicType . Identifier 1062 static Action shiftType(Parser p) 1063 { 1064 switch(p.tok.id) 1065 { 1066 case TOK_dot: 1067 p.appendReplaceTopNode(new ast.TypeProperty(p.tok)); 1068 p.pushState(&shiftTypeDot); 1069 p.pushState(&IdentifierOrTemplateInstance.enter); 1070 return Accept; 1071 case TOK_lparen: 1072 p.appendReplaceTopNode(new ast.StructConstructor(p.tok)); 1073 p.pushState(&shiftStructArguments); 1074 return Arguments.enter(p); 1075 default: 1076 return p.parseError("'.' expected for type property"); 1077 } 1078 } 1079 1080 static Action shiftTypeDot(Parser p) 1081 { 1082 p.popAppendTopNode!(ast.TypeProperty)(); 1083 return Forward; 1084 } 1085 1086 static Action shiftStructArguments(Parser p) 1087 { 1088 p.popAppendTopNode!(ast.StructConstructor)(); 1089 return Forward; 1090 } 1091 1092 static Action shiftStringLiteral(Parser p) 1093 { 1094 switch(p.tok.id) 1095 { 1096 case TOK_StringLiteral: 1097 p.topNode!(ast.StringLiteralExpression).addText(p.tok); 1098 p.pushState(&shiftStringLiteral); 1099 return Accept; 1100 default: 1101 return Forward; 1102 } 1103 } 1104 } 1105 1106 //-- GRAMMAR_BEGIN -- 1107 //VoidInitializer: 1108 // void 1109 // 1110 //ArrayLiteral: 1111 // [ ArgumentList ] 1112 // 1113 //AssocArrayLiteral: 1114 // [ KeyValuePairs ] 1115 class ArrayLiteral : Expression 1116 { 1117 // combines all array literals, has to be disambiguated when assigned 1118 mixin SequenceNode!(ast.ArrayLiteral, TOK_lbracket, ArrayValueList, TOK_rbracket); 1119 } 1120 1121 //-- GRAMMAR_BEGIN -- 1122 //ArrayValueList: 1123 // ArrayValue 1124 // ArrayValue , ArrayValue 1125 class ArrayValueList 1126 { 1127 mixin ListNode!(ast.ArgumentList, ArrayValue, TOK_comma, true, true); 1128 } 1129 1130 //-- GRAMMAR_BEGIN -- 1131 //ArrayValue: 1132 // AssignExpression 1133 // AssignExpression : AssignExpression 1134 class ArrayValue : BinaryExpression 1135 { 1136 mixin stateAppendClass!(AssignExpression, Parser.forward) stateValue; 1137 1138 static Action statePrepareValue(Parser p) 1139 { 1140 auto kp = new ast.KeyValuePair(p.tok); 1141 p.appendReplaceTopNode(kp); 1142 return stateValue.shift(p); 1143 } 1144 1145 mixin stateShiftToken!(TOK_colon, statePrepareValue, -1) stateColon; 1146 mixin stateEnterClass!(AssignExpression, NoASTNode, stateColon.shift); 1147 } 1148 1149 //-- GRAMMAR_BEGIN -- 1150 //FunctionLiteral: 1151 // function Type_opt ParameterAttributes_opt FunctionBody 1152 // delegate Type_opt ParameterAttributes_opt FunctionBody 1153 // ParameterAttributes FunctionBody 1154 // FunctionBody 1155 // 1156 //ParameterAttributes: 1157 // Parameters 1158 // Parameters FunctionAttributes 1159 class FunctionLiteral(bool allowLambda) : Expression 1160 { 1161 static Action enter(Parser p) 1162 { 1163 auto lit = new ast.FunctionLiteral(0, p.tok.span); 1164 p.pushNode(lit); 1165 1166 switch(p.tok.id) 1167 { 1168 case TOK_function: 1169 case TOK_delegate: 1170 lit.id = p.tok.id; 1171 p.pushState(&shiftFunctionDelegate); 1172 return Accept; 1173 1174 case TOK_lcurly: 1175 lit.addMember(new ast.ParameterList(p.tok)); 1176 p.pushState(&shiftFunctionBody); 1177 return FunctionBody.enter(p); 1178 1179 case TOK_lparen: 1180 p.pushState(&shiftParameters); 1181 return Parameters.enter(p); 1182 1183 default: 1184 return p.parseError("unexpected token for function/delegate literal"); 1185 } 1186 } 1187 1188 static Action shiftFunctionDelegate(Parser p) 1189 { 1190 switch(p.tok.id) 1191 { 1192 case TOK_lcurly: 1193 auto lit = p.topNode!(ast.FunctionLiteral)(); 1194 lit.addMember(new ast.ParameterList(p.tok)); 1195 p.pushState(&shiftFunctionBody); 1196 return FunctionBody.enter(p); 1197 1198 case TOK_lparen: 1199 p.pushState(&shiftParameters); 1200 return Parameters.enter(p); 1201 1202 default: 1203 p.pushState(&shiftType); 1204 return Type.enter(p); 1205 } 1206 } 1207 1208 static Action shiftType(Parser p) 1209 { 1210 p.popAppendTopNode!(ast.FunctionLiteral); 1211 switch(p.tok.id) 1212 { 1213 case TOK_lcurly: 1214 auto lit = p.topNode!(ast.FunctionLiteral)(); 1215 lit.addMember(new ast.ParameterList(p.tok)); 1216 p.pushState(&shiftFunctionBody); 1217 return FunctionBody.enter(p); 1218 1219 case TOK_lparen: 1220 p.pushState(&shiftParameters); 1221 return Parameters.enter(p); 1222 1223 default: 1224 return p.parseError("'(' or '{' expected in function literal"); 1225 } 1226 } 1227 1228 static Action shiftParameters(Parser p) 1229 { 1230 p.popAppendTopNode!(ast.FunctionLiteral)(); 1231 return shiftFunctionAttribute(p); 1232 } 1233 1234 static Action shiftFunctionAttribute(Parser p) 1235 { 1236 switch(p.tok.id) 1237 { 1238 case TOK_lcurly: 1239 p.pushState(&shiftFunctionBody); 1240 return FunctionBody.enter(p); 1241 1242 static if(allowLambda) 1243 { 1244 case TOK_lambda: 1245 p.pushState(&shiftLambda); 1246 p.pushState(&AssignExpression.enter); 1247 return Accept; 1248 } 1249 mixin(case_TOKs_FunctionAttribute); 1250 auto lit = p.topNode!(ast.FunctionLiteral)(); 1251 p.combineAttributes(lit.attr, tokenToAttribute(p.tok.id)); 1252 p.combineAnnotations(lit.annotation, tokenToAnnotation(p.tok.id)); 1253 p.pushState(&shiftFunctionAttribute); 1254 return Accept; 1255 1256 default: 1257 return p.parseError("'{' expected in function literal"); 1258 } 1259 } 1260 1261 static Action shiftFunctionBody(Parser p) 1262 { 1263 p.popAppendTopNode!(ast.FunctionLiteral); 1264 return Forward; 1265 } 1266 1267 static Action shiftLambda(Parser p) 1268 { 1269 auto expr = p.popNode!(ast.Expression)(); 1270 auto ret = new ast.ReturnStatement; 1271 ret.addMember(expr); 1272 auto blk = new ast.BlockStatement; 1273 blk.addMember(ret); 1274 auto bdy = new ast.FunctionBody; 1275 bdy.addMember(blk); 1276 bdy.bodyStatement = blk; 1277 1278 auto lit = p.topNode!(ast.FunctionLiteral)(); 1279 lit.addMember(bdy); 1280 return Forward; 1281 } 1282 } 1283 1284 //-- GRAMMAR_BEGIN -- 1285 //StructLiteral: 1286 // { ArrayValueList } 1287 class StructLiteral : Expression 1288 { 1289 mixin SequenceNode!(ast.StructLiteral, TOK_lcurly, ArrayValueList, TOK_rcurly); 1290 1291 } 1292 1293 //-- GRAMMAR_BEGIN -- 1294 //AssertExpression: 1295 // assert ( AssignExpression ) 1296 // assert ( AssignExpression , AssignExpression ) 1297 class AssertExpression : Expression 1298 { 1299 // assert ( AssignExpression , AssignExpression $ ) 1300 mixin stateShiftToken!(TOK_rparen, Parser.forward) stateRparen; 1301 1302 // assert ( AssignExpression , $ AssignExpression ) 1303 mixin stateAppendClass!(AssignExpression, stateRparen.shift) stateMessage; 1304 1305 // assert ( AssignExpression $ ) 1306 // assert ( AssignExpression $ , AssignExpression ) 1307 mixin stateShiftToken!(TOK_rparen, Parser.forward, 1308 TOK_comma, stateMessage.shift) stateRparenComma; 1309 1310 // assert ( $ AssignExpression , AssignExpression ) 1311 mixin stateAppendClass!(AssignExpression, stateRparenComma.shift) stateExpression; 1312 1313 // assert $ ( AssignExpression , AssignExpression ) 1314 mixin stateShiftToken!(TOK_lparen, stateExpression.shift) stateLparen; 1315 1316 // $ assert ( AssignExpression , AssignExpression ) 1317 mixin stateEnterToken!(TOK_assert, ast.AssertExpression, stateLparen.shift); 1318 } 1319 1320 //-- GRAMMAR_BEGIN -- 1321 //MixinExpression: 1322 // mixin ( AssignExpression ) 1323 class MixinExpression : Expression 1324 { 1325 mixin SequenceNode!(ast.MixinExpression, TOK_mixin, TOK_lparen, AssignExpression, TOK_rparen); 1326 } 1327 1328 //-- GRAMMAR_BEGIN -- 1329 //ImportExpression: 1330 // import ( AssignExpression ) 1331 class ImportExpression : Expression 1332 { 1333 mixin SequenceNode!(ast.ImportExpression, TOK_import, TOK_lparen, AssignExpression, TOK_rparen); 1334 } 1335 1336 //-- GRAMMAR_BEGIN -- 1337 //TypeidExpression: 1338 // typeid ( Type ) 1339 // typeid ( Expression ) 1340 class TypeIdExpression : Expression 1341 { 1342 mixin SequenceNode!(ast.TypeIdExpression, TOK_typeid, TOK_lparen, TypeOrExpression!TOK_rparen, TOK_rparen); 1343 } 1344 1345 class TypeOrExpression(ops...) 1346 { 1347 static Action enter(Parser p) 1348 { 1349 p.pushRollback(&rollbackTypeFailure); 1350 p.pushState(&shiftType); 1351 return Type.enter(p); 1352 } 1353 1354 static Action shiftType(Parser p) 1355 { 1356 if(!isInOps!(ops)(p.tok.id)) 1357 return p.parseError("not a type!"); 1358 1359 p.popRollback(); 1360 return Forward; 1361 } 1362 1363 static Action rollbackTypeFailure(Parser p) 1364 { 1365 return AssignExpression.enter(p); 1366 } 1367 } 1368 1369 //-- GRAMMAR_BEGIN -- 1370 //IsExpression: 1371 // is ( Type ) 1372 // is ( Type : TypeSpecialization ) 1373 // is ( Type == TypeSpecialization ) 1374 // is ( Type Identifier ) 1375 // is ( Type Identifier : TypeSpecialization ) 1376 // is ( Type Identifier == TypeSpecialization ) 1377 // is ( Type Identifier : TypeSpecialization , TemplateParameterList ) 1378 // is ( Type Identifier == TypeSpecialization , TemplateParameterList ) 1379 // 1380 //TypeSpecialization: 1381 // TypeWithModifier 1382 // struct 1383 // union 1384 // class 1385 // interface 1386 // enum 1387 // function 1388 // delegate 1389 // super 1390 // const 1391 // immutable 1392 // inout 1393 // shared 1394 // return 1395 // __parameters 1396 // __argTypes 1397 // 1398 // !is specially treated, because it's a token to the lexer 1399 class IsExpression : Expression 1400 { 1401 // is ( Type Identifier == TypeSpecialization , TemplateParameterList $ ) 1402 mixin stateShiftToken!(TOK_rparen, Parser.forward) stateRparen; 1403 1404 // is ( Type Identifier == TypeSpecialization , $ TemplateParameterList ) 1405 mixin stateAppendClass!(TemplateParameterList, stateRparen.shift) stateTemplateParameterList; 1406 1407 // is ( Type : TypeSpecialization $ ) 1408 // ... 1409 // is ( Type Identifier == TypeSpecialization $ , TemplateParameterList ) 1410 mixin stateShiftToken!(TOK_rparen, Parser.forward, 1411 TOK_comma, stateTemplateParameterList.shift) stateRparenComma; 1412 1413 // is ( Type : $ TypeSpecialization ) 1414 // is ( Type == $ TypeSpecialization ) 1415 mixin stateAppendClass!(TypeSpecialization, stateRparenComma.shift) stateTypeSpecialization; 1416 1417 static Action rememberColon(Parser p) 1418 { 1419 p.topNode!(ast.IsExpression).kind = TOK_colon; 1420 return stateTypeSpecialization.shift(p); 1421 } 1422 static Action rememberAssign(Parser p) 1423 { 1424 p.topNode!(ast.IsExpression).kind = TOK_equal; 1425 return stateTypeSpecialization.shift(p); 1426 } 1427 mixin stateShiftToken!(TOK_rparen, Parser.forward, 1428 TOK_colon, rememberColon, 1429 TOK_equal, rememberAssign) stateAfterIdentifier; 1430 1431 static Action rememberIdentifier(Parser p) 1432 { 1433 switch(p.tok.id) 1434 { 1435 case TOK_Identifier: 1436 p.topNode!(ast.IsExpression).ident = p.tok.txt; 1437 p.pushState(&stateAfterIdentifier.shift); 1438 return Accept; 1439 default: 1440 return p.parseError("')', ':', '==' or identifier expected"); 1441 } 1442 } 1443 1444 // is ( Type $ ) 1445 // is ( Type $ : TypeSpecialization ) 1446 // is ( Type $ == TypeSpecialization ) 1447 // is ( Type $ Identifier == TypeSpecialization , TemplateParameterList ) 1448 mixin stateShiftToken!(TOK_rparen, Parser.forward, 1449 TOK_colon, rememberColon, 1450 TOK_equal, rememberAssign, 1451 -1, rememberIdentifier) stateIdentifier; 1452 1453 // is ( $ Type Identifier == TypeSpecialization , TemplateParameterList ) 1454 mixin stateAppendClass!(Type, stateIdentifier.shift) stateType; 1455 1456 // is $ ( Type Identifier == TypeSpecialization , TemplateParameterList ) 1457 mixin stateShiftToken!(TOK_lparen, stateType.shift) stateLparen; 1458 1459 // $ is ( Type Identifier == TypeSpecialization , TemplateParameterList ) 1460 mixin stateEnterToken!(TOK_is, ast.IsExpression, stateLparen.shift); 1461 1462 static Action enterNotIs(Parser p) 1463 { 1464 p.pushNode(new ast.UnaryExpression(TOK_not, p.tok.span)); 1465 p.pushNode(new ast.IsExpression(p.tok)); 1466 p.pushState(&shiftNotIsExpression); 1467 p.pushState(&stateLparen.shift); 1468 return Accept; 1469 } 1470 1471 static Action shiftNotIsExpression(Parser p) 1472 { 1473 p.popAppendTopNode!(ast.UnaryExpression)(); 1474 return Forward; 1475 } 1476 } 1477 1478 class TypeSpecialization 1479 { 1480 static Action enter(Parser p) 1481 { 1482 switch(p.tok.id) 1483 { 1484 case TOK_struct: 1485 case TOK_union: 1486 case TOK_class: 1487 case TOK_interface: 1488 case TOK_enum: 1489 case TOK_function: 1490 case TOK_delegate: 1491 case TOK_super: 1492 case TOK_return: 1493 case TOK_typedef: 1494 case TOK___parameters: 1495 case TOK___argTypes: 1496 p.pushNode(new ast.TypeSpecialization(p.tok)); 1497 return Accept; 1498 case TOK_const: 1499 case TOK_immutable: 1500 case TOK_inout: 1501 case TOK_shared: 1502 p.pushToken(p.tok); 1503 p.pushState(&shiftModifier); 1504 return Accept; 1505 default: 1506 p.pushNode(new ast.TypeSpecialization(0, p.tok.span)); 1507 p.pushState(&shiftType); 1508 return Type.enter(p); 1509 } 1510 } 1511 1512 static Action shiftModifier(Parser p) 1513 { 1514 switch(p.tok.id) 1515 { 1516 case TOK_lparen: 1517 p.pushNode(new ast.TypeSpecialization(0, p.tok.span)); 1518 p.pushState(&shiftType); 1519 return Type.enterTypeModifier(p); 1520 case TOK_rparen: 1521 case TOK_comma: 1522 auto tok = p.popToken(); 1523 p.pushNode(new ast.TypeSpecialization(tok)); 1524 return Forward; 1525 default: 1526 p.pushNode(new ast.TypeSpecialization(0, p.tok.span)); 1527 p.pushState(&shiftType); 1528 return TypeWithModifier.shiftModifier(p); 1529 } 1530 } 1531 1532 static Action shiftType(Parser p) 1533 { 1534 p.popAppendTopNode!(ast.TypeSpecialization)(); 1535 return Forward; 1536 } 1537 } 1538 1539 //-- GRAMMAR_BEGIN -- 1540 //TraitsExpression: 1541 // __traits ( TraitsKeyword , TraitsArguments ) 1542 // 1543 //TraitsKeyword: 1544 // "isAbstractClass" 1545 // "isArithmetic" 1546 // "isAssociativeArray" 1547 // "isFinalClass" 1548 // "isFloating" 1549 // "isIntegral" 1550 // "isScalar" 1551 // "isStaticArray" 1552 // "isUnsigned" 1553 // "isVirtualFunction" 1554 // "isAbstractFunction" 1555 // "isFinalFunction" 1556 // "isStaticFunction" 1557 // "isRef" 1558 // "isOut" 1559 // "isLazy" 1560 // "hasMember" 1561 // "identifier" 1562 // "getMember" 1563 // "getOverloads" 1564 // "getVirtualFunctions" 1565 // "classInstanceSize" 1566 // "allMembers" 1567 // "derivedMembers" 1568 // "isSame" 1569 // "compiles" 1570 class TraitsExpression : Expression 1571 { 1572 mixin stateShiftToken!(TOK_rparen, Parser.forward) stateRparen; 1573 1574 mixin stateAppendClass!(TraitsArguments, stateRparen.shift) stateArguments; 1575 1576 mixin stateShiftToken!(TOK_comma, stateArguments.shift, 1577 TOK_rparen, Parser.forward) stateComma; 1578 1579 mixin stateAppendClass!(Identifier, stateComma.shift) stateIdentifier; 1580 1581 mixin stateShiftToken!(TOK_lparen, stateIdentifier.shift) stateLparen; 1582 1583 mixin stateEnterToken!(TOK___traits, ast.TraitsExpression, stateLparen.shift); 1584 } 1585 1586 //-- GRAMMAR_BEGIN -- 1587 //TraitsArguments: 1588 // TraitsArgument 1589 // TraitsArgument , TraitsArguments 1590 // 1591 //TraitsArgument: 1592 // AssignExpression 1593 // Type 1594 class TraitsArguments 1595 { 1596 mixin ListNode!(ast.TraitsArguments, TypeOrExpression!(TOK_comma, TOK_rparen), TOK_comma, false, false); 1597 }