1 /// Author: Aziz Köksal 2 /// License: GPL3 3 /// $(Maturity very high) 4 module dil.parser.Parser; 5 6 import dil.lexer.Lexer, 7 dil.lexer.IdTable, 8 dil.lexer.Tables; 9 import dil.ast.Node, 10 dil.ast.Declarations, 11 dil.ast.Statements, 12 dil.ast.Expressions, 13 dil.ast.Types, 14 dil.ast.Parameters; 15 import dil.i18n.Messages; 16 import dil.Diagnostics, 17 dil.Enums, 18 dil.SourceText, 19 dil.Unicode; 20 import common; 21 22 /// The Parser produces a full parse tree by examining 23 /// the list of tokens provided by the Lexer. 24 class Parser 25 { 26 Lexer lexer; /// Used to lex the source code. 27 Token* token; /// Current non-whitespace token. 28 Token* prevToken; /// Previous non-whitespace token. 29 30 Diagnostics diag; /// Collects error messages. 31 ParserError[] errors; /// Array of parser error messages. 32 33 ImportDecl[] imports; /// ImportDeclarations in the source text. 34 35 /// Attributes are evaluated in the parsing phase. 36 /// TODO: will be removed. SemanticPass1 takes care of attributes. 37 LinkageType linkageType; 38 Protection protection; /// ditto 39 StorageClass storageClass; /// ditto 40 uint alignSize; /// ditto 41 42 43 private alias T = S2T; /// Used often in this class. 44 private alias Type = TypeNode; 45 46 /// Constructs a Parser object. 47 /// Params: 48 /// srcText = The UTF-8 source code. 49 /// tables = For the Lexer. 50 /// diag = Used for collecting error messages. 51 this(SourceText srcText, LexerTables tables, Diagnostics diag = null) 52 { 53 this.diag = diag ? diag : new Diagnostics(); 54 this.lexer = new Lexer(srcText, tables, diag); 55 } 56 57 /// Moves to the first non-whitespace token. 58 protected void init() 59 { 60 lexer.scanAll(); 61 token = lexer.firstToken.prev; 62 nT(); 63 prevToken = token; 64 } 65 66 /// Moves to the next token. 67 void nT() 68 { 69 prevToken = token; 70 do 71 token++; 72 while (token.isWhitespace); // Skip whitespace. 73 } 74 75 /// Starts the parser and returns the parsed Declarations. 76 CompoundDecl start() 77 { 78 init(); 79 auto begin = token; 80 auto decls = new CompoundDecl; 81 if (tokenIs!"module") 82 decls ~= parseModuleDecl(); 83 decls.addOptChildren(parseDeclarationDefinitions()); 84 set(decls, begin); 85 return decls; 86 } 87 88 /// Starts the parser and returns the parsed Expression. 89 Expression start2() 90 { 91 init(); 92 return parseExpression(); 93 } 94 95 // Members related to the method tryToParse(). 96 uint trying; /// Greater than 0 if Parser is in tryToParse(). 97 uint errorCount; /// Used to track nr. of errors while being in tryToParse(). 98 99 /// This method executes the delegate parseMethod and when an error occurs 100 /// the state of the lexer and parser is restored. 101 /// Returns: The return value of parseMethod(). 102 RetType tryToParse(RetType)(RetType delegate() parseMethod, out bool success) 103 { 104 // Save members. 105 auto oldToken = this.token; 106 auto oldPrevToken = this.prevToken; 107 auto oldCount = this.errorCount; 108 109 ++trying; 110 auto result = parseMethod(); 111 --trying; 112 // Check if an error occurred. 113 if (errorCount != oldCount) 114 { // Restore members. 115 token = oldToken; 116 prevToken = oldPrevToken; 117 errorCount = oldCount; 118 } 119 else 120 success = true; 121 return result; 122 } 123 124 /// Causes the current call to tryToParse() to fail. 125 void fail_tryToParse() 126 { 127 assert(trying); 128 errorCount++; 129 } 130 131 /// Backtracks the Parser to the given token(s). 132 void backtrackTo(Token* newtok, Token* newprev = null) 133 { 134 this.token = newtok; 135 this.prevToken = newprev ? newprev : newtok.prevNWS(); 136 } 137 138 /// Sets the begin and end tokens of a syntax tree node. 139 Class set(Class)(Class node, Token* begin) 140 { 141 assert(node !is null); 142 node.setTokens(begin, this.prevToken); 143 return node; 144 } 145 146 /// Sets the begin and end tokens of a syntax tree node. 147 Class set(Class)(Class node, Token* begin, Token* end) 148 { 149 assert(node !is null); 150 node.setTokens(begin, end); 151 return node; 152 } 153 154 /// Returns true if set() has been called on a node. 155 static bool isNodeSet(const Node node) 156 { 157 assert(node !is null); 158 return node.begin !is null && node.end !is null; 159 } 160 161 /// Returns true if the current token is of kind T!str. 162 bool tokenIs(string str)() 163 { 164 return token.kind == T!str; 165 } 166 167 /// Returns true if the next token is of kind T!str. 168 bool nextIs(string str)() 169 { 170 return peekNext() == T!str; 171 } 172 173 /// Returns the token kind of the next token. 174 TOK peekNext() 175 { 176 Token* next = token; 177 do 178 lexer.peek(next); 179 while (next.isWhitespace); // Skip whitespace 180 return next.kind; 181 } 182 183 /// Returns the token that comes after t. 184 Token* peekAfter(Token* t) 185 { 186 assert(t !is null); 187 do 188 lexer.peek(t); 189 while (t.isWhitespace); // Skip whitespace 190 return t; 191 } 192 193 /// Consumes the current token and returns it. 194 Token* consume()() 195 { 196 nT(); 197 return prevToken; 198 } 199 200 /// Consumes the current token if its kind matches T!str and returns true. 201 bool consumed(string str)() 202 { 203 return tokenIs!str ? (nT(), true) : false; 204 } 205 206 /// Consumes the current token if its kind matches T!str and returns it. 207 Token* consumedToken(string str)() 208 { 209 return tokenIs!str ? (nT(), prevToken) : null; 210 } 211 212 /// Asserts that the current token is of kind T!str, 213 /// and then moves to the next token. 214 void skip(string str)() 215 { 216 assert(tokenIs!str); 217 consume(); 218 } 219 220 /// Returns true if the token after the closing parenthesis 221 /// matches the searched kind. 222 /// Params: 223 /// kind = The token kind to test for. 224 bool tokenAfterParenIs(TOK kind) 225 { 226 assert(tokenIs!"("); 227 return skipParens(token, T!")").kind == kind; 228 } 229 230 /// Returns the token kind behind the closing bracket. 231 TOK tokenAfterBracket(TOK closing) 232 { 233 assert(token.kind.Any!("[", "{")); 234 return skipParens(token, closing).kind; 235 } 236 237 /// Skips to the token behind the closing parenthesis token. 238 /// Takes nesting into account. 239 /// Params: 240 /// peek_token = Opening token to start from. 241 /// closing = Matching closing token kind. 242 /// Returns: The token searched for, or the EOF token. 243 Token* skipParens(Token* peek_token, TOK closing) 244 { 245 assert(peek_token !is null); 246 size_t level = 1; 247 TOK opening = peek_token.kind; 248 while ((peek_token = peekAfter(peek_token)).kind != T!"EOF") 249 if (peek_token.kind == opening) 250 ++level; 251 else 252 if (peek_token.kind == closing && --level == 0) { 253 peek_token = peekAfter(peek_token); // Closing token found. 254 break; 255 } 256 return peek_token; 257 } 258 259 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 260 | Declaration parsing methods | 261 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ 262 263 /// $(BNF ModuleDecl := module ModuleType? Identifier ("." Identifier)* ";" 264 ////ModuleType := "(" safe | system ")") 265 Declaration parseModuleDecl() 266 { 267 auto begin = token; 268 skip!"module"; 269 ModuleFQN moduleFQN; 270 Token* typeId; 271 version(D2) 272 { 273 if (consumed!"(") 274 { 275 typeId = requireIdentifier(MID.ExpectedModuleType); 276 if (typeId && !typeId.ident.In(Ident.safe, Ident.system)) 277 error(typeId, MID.ExpectedModuleType); 278 require2!")"; 279 } 280 } // version(D2) 281 do 282 moduleFQN ~= requireIdentifier(MID.ExpectedModuleIdentifier); 283 while (consumed!"."); 284 require2!";"; 285 return set(new ModuleDecl(typeId, moduleFQN), begin); 286 } 287 288 /// Parses DeclarationDefinitions until the end of file is hit. 289 /// $(BNF DeclDefs := DeclDef*) 290 Declaration[] parseDeclarationDefinitions() 291 { 292 Declaration[] decls; 293 while (!tokenIs!"EOF") 294 decls ~= parseDeclarationDefinition(); 295 return decls; 296 } 297 298 /// Parse the body of a template, class, interface, struct or union. 299 /// $(BNF DeclDefsBlock := "{" DeclDefs? "}") 300 CompoundDecl parseDeclarationDefinitionsBody() 301 { 302 // Save attributes. 303 auto linkageType = this.linkageType; 304 auto protection = this.protection; 305 auto storageClass = this.storageClass; 306 // Clear attributes. 307 this.linkageType = LinkageType.None; 308 this.protection = Protection.None; 309 this.storageClass = StorageClass.None; 310 311 // Parse body. 312 auto decls = new CompoundDecl; 313 auto brace = requireOpening!"{"; 314 while (!token.kind.Any!("}", "EOF")) 315 decls ~= parseDeclarationDefinition(); 316 requireClosing!"}"(brace); 317 set(decls, brace); 318 319 // Restore original values. 320 this.linkageType = linkageType; 321 this.protection = protection; 322 this.storageClass = storageClass; 323 324 return decls; 325 } 326 327 /// Parses a DeclarationDefinition. 328 /// 329 /// $(BNF DeclDef := Attributes | AliasThisDecl | AliasDecl | TypedefDecl | 330 //// StaticCtorDecl | StaticDtorDecl | StaticIfDecl | StaticAssertDecl | 331 //// ImportDecl | EnumDecl | ClassDecl | InterfaceDecl | StructDecl | 332 //// UnionDecl | ConstructorDecl | DestructorDecl | InvariantDecl | 333 //// UnittestDecl | DebugDecl | VersionDecl | TemplateDecl | NewDecl | 334 //// DeleteDecl | MixinDecl | EmptyDecl | VariablesOrFunction 335 ////TypedefDecl := typedef VariablesDecl) 336 Declaration parseDeclarationDefinition() 337 out(decl) 338 { assert(isNodeSet(decl)); } 339 body 340 { 341 auto begin = token; 342 Declaration decl; 343 switch (token.kind) 344 { 345 version(D2) 346 { // T!"shared", T!"immutable", T!"inout" 347 case T!"__gshared", T!"ref", T!"pure", T!"nothrow", T!"@": 348 goto case; 349 } 350 case T!"align", T!"pragma", 351 // Protection attributes 352 T!"export", T!"private", T!"package", T!"protected", T!"public", 353 // Storage classes 354 //T!"static", T!"const", 355 T!"extern", T!"deprecated", T!"override", T!"abstract", 356 T!"synchronized", T!"auto", T!"scope", T!"final": 357 case_parseAttributes: 358 return parseAttributes(); 359 case T!"alias": 360 decl = parseAliasDecl(); 361 break; 362 case T!"typedef": 363 nT(); 364 auto td = new TypedefDecl(parseAttributes(&decl)); 365 td.vardecl = decl; 366 if (!decl.Is!(VariablesDecl)) 367 error(decl.begin, MID.TypedefExpectsVariable, decl.toText()); 368 decl = td; 369 break; 370 case T!"static": 371 switch (peekNext()) 372 { 373 case T!"import": goto case_Import; 374 case T!"this": decl = parseStaticCtorDecl(); break; 375 case T!"~": decl = parseStaticDtorDecl(); break; 376 case T!"if": decl = parseStaticIfDecl(); break; 377 case T!"assert": decl = parseStaticAssertDecl(); break; 378 default: goto case_parseAttributes; 379 } 380 break; 381 case T!"import": 382 case_Import: 383 auto importDecl = parseImportDecl(); 384 imports ~= importDecl; 385 // Handle specially. StorageClass mustn't be set. 386 importDecl.setProtection(this.protection); 387 return set(importDecl, begin); 388 case T!"enum": 389 version(D2) 390 if (isEnumManifest()) 391 goto case_parseAttributes; 392 decl = parseEnumDecl(); 393 break; 394 case T!"class": 395 decl = parseClassDecl(); 396 break; 397 case T!"interface": 398 decl = parseInterfaceDecl(); 399 break; 400 case T!"struct", T!"union": 401 decl = parseStructOrUnionDecl(); 402 break; 403 case T!"this": 404 if (nextIs!"(") 405 decl = parseConstructorDecl(); 406 else 407 goto case_Declaration; 408 break; 409 case T!"~": 410 decl = parseDestructorDecl(); 411 break; 412 version(D2) 413 { 414 case T!"const", T!"immutable", T!"inout", T!"shared": 415 if (nextIs!"(") 416 goto case_Declaration; 417 goto case_parseAttributes; 418 } // version(D2) 419 else 420 { // D1 421 case T!"const": 422 goto case_parseAttributes; 423 } 424 case T!"invariant": 425 decl = parseInvariantDecl(); // invariant "(" ")" 426 break; 427 case T!"unittest": 428 decl = parseUnittestDecl(); 429 break; 430 case T!"debug": 431 decl = parseDebugDecl(); 432 break; 433 case T!"version": 434 decl = parseVersionDecl(); 435 break; 436 case T!"template": 437 decl = parseTemplateDecl(); 438 break; 439 case T!"new": 440 decl = parseNewDecl(); 441 break; 442 case T!"delete": 443 decl = parseDeleteDecl(); 444 break; 445 case T!"mixin": 446 decl = parseMixin!(MixinDecl, Declaration)(); 447 break; 448 case T!";": 449 nT(); 450 decl = new EmptyDecl(); 451 break; 452 // Declaration 453 version(D2) 454 { 455 case T!"super"/*, T!"this"*/: 456 goto case_Declaration; 457 } 458 case T!"Identifier", T!".", T!"typeof": 459 case_Declaration: 460 return parseVariablesOrFunction(this.storageClass, this.protection, 461 this.linkageType); 462 default: 463 if (token.isIntegralType) 464 goto case_Declaration; 465 else if (tokenIs!"module") 466 { 467 decl = parseModuleDecl(); 468 error(begin, MID.ModuleDeclarationNotFirst); 469 return decl; 470 } 471 472 decl = new IllegalDecl(); 473 // Skip to next valid token. 474 do 475 nT(); 476 while (!token.isDeclDefStart() && !token.kind.Any!("}", "EOF")); 477 auto text = begin.textSpan(this.prevToken); 478 error(begin, MID.IllegalDeclaration, text); 479 } 480 decl.setProtection(this.protection); 481 decl.setStorageClass(this.storageClass); 482 assert(!isNodeSet(decl)); 483 set(decl, begin); 484 return decl; 485 } 486 487 /// Parses a DeclarationsBlock. 488 /// $(BNF DeclsBlock := ":" DeclDefs | "{" DeclDefs? "}" | DeclDef) 489 Declaration parseDeclarationsBlock() 490 { 491 Declaration d; 492 switch (token.kind) 493 { 494 case T!"{": 495 auto brace = consume(); 496 auto decls = new CompoundDecl; 497 while (!token.kind.Any!("}", "EOF")) 498 decls ~= parseDeclarationDefinition(); 499 requireClosing!"}"(brace); 500 d = set(decls, brace); 501 break; 502 case T!":": 503 auto colon = consume(); 504 auto begin2 = token; 505 auto decls = new CompoundDecl; 506 while (!token.kind.Any!("}", "EOF")) 507 decls ~= parseDeclarationDefinition(); 508 set(decls, begin2); 509 d = set(new ColonBlockDecl(decls), colon); 510 break; 511 case T!";": 512 error(MID.ExpectedNonEmptyDeclaration, token); 513 goto default; 514 default: 515 d = parseDeclarationDefinition(); 516 } 517 assert(isNodeSet(d)); 518 return d; 519 } 520 521 /// $(BNF 522 ////AliasDecl := alias Attributes 523 ////AliasThisDecl := alias Identifier this ";" 524 ////AliasesDecl := alias AliasName "=" Type ("," AliasName "=" Type)* ";" 525 ////AliasName := this | Identifier) 526 Declaration parseAliasDecl() 527 { 528 skip!"alias"; 529 version (D2) 530 { 531 if (tokenIs!"Identifier" && nextIs!"this") 532 { 533 auto ident = consume(); 534 skip!"this"; 535 require2!";"; 536 return new AliasThisDecl(ident); 537 } 538 else 539 if (token.kind.Any!("this", "Identifier") && nextIs!"=") 540 { 541 Token*[] idents; 542 TypeNode[] types; 543 goto LenterLoop; 544 545 while (consumed!",") 546 { 547 if (!token.kind.Any!("this", "Identifier")) 548 error(token, MID.ExpectedAliasName, token.text); 549 LenterLoop: 550 idents ~= token; 551 nT(); 552 require2!"="; 553 types ~= parseType(); 554 } 555 556 require2!";"; 557 return new AliasesDecl(idents, types); 558 } 559 } // version(D2) 560 561 Declaration decl; 562 auto ad = new AliasDecl(parseAttributes(&decl)); 563 ad.vardecl = decl; 564 if (auto var = decl.Is!(VariablesDecl)) 565 { 566 foreach (init; var.inits) 567 if (init) 568 error(init.begin.prevNWS(), MID.AliasHasInitializer); 569 } 570 else 571 error(decl.begin, MID.AliasExpectsVariable, decl.toText()); 572 return ad; 573 } 574 575 /// Parses either a VariablesDecl or a FunctionDecl. 576 /// 577 /// $(BNF 578 ////VariablesOrFunctionDecl := 579 //// AutoDecl | VariablesDecl | FunctionDecl 580 ////AutoDecl := AutoVariables | AutoFunction 581 ////AutoVariables := Name "=" Initializer MoreVariables* ";" 582 ////AutoFunction := Name TemplateParameterList? ParameterList FunctionBody 583 ////VariablesDecl := 584 //// BasicTypes Name DeclaratorSuffix? ("=" Initializer)? MoreVariables* ";" 585 ////MoreVariables := "," Name ("=" Initializer)? 586 ////FunctionDecl := 587 //// BasicTypes Name TemplateParameterList? ParameterList FunctionBody 588 ////Name := Identifier) 589 /// Params: 590 /// stcs = Previously parsed storage classes. 591 /// protection = Previously parsed protection attribute. 592 /// linkType = Previously parsed linkage type. 593 /// testAutoDeclaration = Whether to check for an AutoDecl. 594 Declaration parseVariablesOrFunction( 595 StorageClass stcs = StorageClass.None, 596 Protection protection = Protection.None, 597 LinkageType linkType = LinkageType.None, 598 bool testAutoDeclaration = false) 599 { 600 auto begin = token; 601 Type type; // Variable or function type. 602 Token* name; // Name of the variable or the function. 603 604 Parameters params; // Function parameters. 605 TemplateParameters tparams; // Function template parameters. 606 Expression constraint; // Function template constraint. 607 608 // Check for AutoDecl. 609 if (testAutoDeclaration && tokenIs!"Identifier") 610 { 611 auto next_kind = peekNext(); 612 if (next_kind == T!"=") 613 { // AutoVariables 614 name = consume(); 615 goto LparseVariables; 616 } 617 else version(D2) if (next_kind == T!"(") 618 { // Check for AutoFunction. 619 auto peek_token = peekAfter(token); // Skip the Identifier. 620 next_kind = skipParens(peek_token, T!")").kind; // Token after "("...")" 621 if (next_kind == T!"(") 622 { // TemplateParameterList ParameterList 623 name = consume(); 624 assert(tokenIs!"("); 625 goto LparseTPList; // Continue parsing templatized AutoFunction. 626 } 627 else 628 if (next_kind.Any!("{", FunctionPostfix, "in", "out", "body")) 629 { // ParameterList ("{" | FunctionPostfix | in | out | body) 630 name = consume(); 631 assert(tokenIs!"("); 632 goto LparseBeforeParams; // Continue parsing AutoFunction. 633 } 634 } // version(D2) 635 } 636 637 // VariableType or ReturnType 638 type = parseBasicTypes(); 639 640 if (nextIs!"(") 641 { // ReturnType FunctionName "(" ParameterList ")" FunctionBody 642 name = requireIdentifier(MID.ExpectedFunctionName); 643 if (!tokenIs!"(") 644 nT(); // Skip non-identifier token. 645 646 LparseBeforeTParams: 647 assert(tokenIs!"("); 648 if (tokenAfterParenIs(T!"(")) 649 LparseTPList: // "(" TemplateParameterList ")" 650 tparams = parseTemplateParameterList(); 651 652 LparseBeforeParams: // "(" ParameterList ")" 653 params = parseParameterList(); 654 655 LparseAfterParams: 656 StorageClass postfix_stcs; // const | immutable | @property | ... 657 version(D2) 658 { 659 params.postSTCs = postfix_stcs = parseFunctionPostfix(); 660 if (tparams) // if "(" ConstraintExpr ")" 661 constraint = parseOptionalConstraint(); 662 } // version(D2) 663 664 // FunctionBody 665 auto funcBody = parseFunctionBody(); 666 auto fd = new FunctionDecl(type, name, params, funcBody, linkType); 667 Declaration decl = fd; 668 if (tparams) 669 { 670 decl = 671 putInsideTemplateDeclaration(begin, name, fd, tparams, constraint); 672 decl.setStorageClass(stcs); 673 decl.setProtection(protection); 674 } 675 fd.setStorageClass(stcs | postfix_stcs); // Combine prefix/postfix stcs. 676 fd.setProtection(protection); 677 return set(decl, begin); 678 } 679 else 680 { // Type VariableName DeclaratorSuffix 681 name = requireIdentifier(MID.ExpectedVariableName); 682 type = parseDeclaratorSuffix(type); 683 } 684 685 LparseVariables: 686 // It's a variables declaration. 687 Token*[] names = [name]; // One identifier has been parsed already. 688 Expression[] values; 689 goto LenterLoop; // Enter the loop and check for an initializer. 690 while (consumed!",") 691 { 692 names ~= requireIdentifier(MID.ExpectedVariableName); 693 LenterLoop: 694 values ~= consumed!"=" ? parseInitializer() : null; 695 } 696 require2!";"; 697 auto d = new VariablesDecl(type, names, values, linkType); 698 d.setStorageClass(stcs); 699 d.setProtection(protection); 700 return set(d, begin); 701 } 702 703 /// Parses a variable initializer. 704 /// $(BNF Initializer := VoidInitializer | NonVoidInitializer 705 ////VoidInitializer := void 706 ////NonVoidInitializer := 707 //// ArrayInitializer | StructInitializer | AssignExpr 708 ////ArrayInitializer := "[" ArrayInitElements? "]" 709 ////ArrayInitElements := ArrayInitElement ("," ArrayInitElement)* ","? 710 ////ArrayInitElement := (AssignExpr ":")? NonVoidInitializer 711 ////StructInitializer := "{" StructInitElements? "}" 712 ////StructInitElements := StructInitElement ("," StructInitElement)* ","? 713 ////StructInitElement := (MemberName ":")? NonVoidInitializer 714 ////MemberName := Identifier) 715 Expression parseInitializer() 716 { 717 if (tokenIs!"void" && peekNext().Any!(",", ";")) 718 return set(new VoidInitExpr(), consume()); 719 return parseNonVoidInitializer(); 720 } 721 722 /// Parses a NonVoidInitializer. 723 /// $(BNF NonVoidInitializer := 724 //// ArrayInitializer | StructInitializer | AssignExpr) 725 Expression parseNonVoidInitializer() 726 { 727 auto begin = token; 728 Expression init; 729 switch (token.kind) 730 { 731 case T!"[": 732 if (!tokenAfterBracket(T!"]").Any!(",", "]", "}", ";")) 733 goto default; // Parse as an AssignExpr. 734 // ArrayInitializer := "[" ArrayInitElements? "]" 735 Expression[] keys, values; 736 737 skip!"["; 738 while (!tokenIs!"]") 739 { 740 Expression key; 741 auto value = parseNonVoidInitializer(); 742 if (consumed!":") 743 (key = value), // Switch roles. 744 assert(!(key.Is!(ArrayInitExpr) || key.Is!(StructInitExpr))), 745 value = parseNonVoidInitializer(); // Parse actual value. 746 keys ~= key; 747 values ~= value; 748 if (!consumed!",") 749 break; 750 } 751 requireClosing!"]"(begin); 752 init = new ArrayInitExpr(keys, values); 753 break; 754 case T!"{": 755 if (!tokenAfterBracket(T!"}").Any!(",", "]", "}", ";")) 756 goto default; // Parse as an AssignExpr. 757 // StructInitializer := "{" StructInitElements? "}" 758 Token*[] idents; 759 Expression[] values; 760 761 skip!"{"; 762 while (!tokenIs!"}") 763 { // Peek for colon to see if this is a member identifier. 764 Token* ident; 765 if (tokenIs!"Identifier" && nextIs!":") 766 (ident = token), 767 skip!"Identifier", skip!":"; 768 idents ~= ident; 769 values ~= parseNonVoidInitializer(); 770 if (!consumed!",") 771 break; 772 } 773 requireClosing!"}"(begin); 774 init = new StructInitExpr(idents, values); 775 break; 776 default: 777 return parseAssignExpr(); 778 } 779 set(init, begin); 780 return init; 781 } 782 783 /// Parses the body of a function. 784 FuncBodyStmt parseFunctionBody() 785 { 786 auto begin = token; 787 Statement funcBody, inBody, outBody; 788 Token* outIdent; 789 790 // Save the attributes. 791 auto saved_stcs = this.storageClass; 792 auto saved_prot = this.protection; 793 auto saved_link = this.linkageType; 794 // Clear attributes. 795 this.storageClass = StorageClass.None; 796 this.protection = Protection.None; 797 this.linkageType = LinkageType.None; 798 799 Loop: 800 while (1) 801 switch (token.kind) 802 { 803 case T!"{": 804 funcBody = parseStatements(); 805 break Loop; 806 case T!";": 807 nT(); 808 break Loop; 809 case T!"in": 810 if (inBody) 811 error(MID.InContract); 812 nT(); 813 inBody = parseStatements(); 814 break; 815 case T!"out": 816 if (outBody) 817 error(MID.OutContract); 818 nT(); 819 if (consumed!"(") 820 (outIdent = requireIdentifier(MID.ExpectedAnIdentifier)), 821 require2!")"; 822 outBody = parseStatements(); 823 break; 824 case T!"body": 825 // if (!outBody || !inBody) // TODO: 826 // error2(MID.ExpectedInOutBody, token); 827 nT(); 828 goto case T!"{"; 829 default: 830 version (D2) 831 { 832 if (inBody || outBody) 833 // In D2, having in or out contracts without a body is valid. 834 break Loop; 835 } // version (D2) 836 error2(MID.ExpectedFunctionBody, token); 837 break Loop; 838 } 839 840 // Restore the original attributes. 841 this.storageClass = saved_stcs; 842 this.protection = saved_prot; 843 this.linkageType = saved_link; 844 845 auto func = new FuncBodyStmt(funcBody, inBody, outBody, outIdent); 846 return set(func, begin); 847 } 848 849 /// $(BNF FunctionPostfix := 850 //// (const|immutable|inout|nothrow|shared|pure| "@" Identifier)*) 851 StorageClass parseFunctionPostfix() 852 { 853 version(D2) 854 { 855 StorageClass stcs, stc; 856 while (1) 857 { 858 switch (token.kind) 859 { 860 case T!"const": stc = StorageClass.Const; break; 861 case T!"immutable": stc = StorageClass.Immutable; break; 862 case T!"inout": stc = StorageClass.Inout; break; 863 case T!"nothrow": stc = StorageClass.Nothrow; break; 864 case T!"shared": stc = StorageClass.Shared; break; 865 case T!"pure": stc = StorageClass.Pure; break; 866 case T!"@": stc = parseAtAttribute(); break; 867 default: 868 return stcs; 869 } 870 if (stcs & stc) 871 error2(MID.RedundantStorageClass, token); 872 stcs |= stc; 873 nT(); 874 } 875 return stcs; 876 } // version(D2) 877 assert(0); 878 } 879 880 /// A tuple of all the possible postfix tokens. 881 alias FunctionPostfix = Tuple!("const", "immutable", "inout", "nothrow", 882 "shared", "pure", "@"); 883 884 /// $(BNF ExternLinkageType := extern "(" LinkageType ")" 885 ///LinkageType := "C" | "C" "++" | "D" | "Windows" | "Pascal" | "System") 886 LinkageType parseExternLinkageType() 887 { 888 LinkageType linkageType; 889 890 skip!"extern", skip!"("; 891 892 if (consumed!")") 893 { // extern "(" ")" 894 error(MID.MissingLinkageType); 895 return linkageType; 896 } 897 898 if (auto idtok = requireIdentifier(MID.ExpectedLinkageIdentifier)) 899 switch (idtok.ident.idKind) 900 { 901 case IDK.C: linkageType = consumed!"++" ? 902 LinkageType.Cpp : 903 LinkageType.C; break; 904 case IDK.D: linkageType = LinkageType.D; break; 905 case IDK.Windows: linkageType = LinkageType.Windows; break; 906 case IDK.Pascal: linkageType = LinkageType.Pascal; break; 907 case IDK.System: linkageType = LinkageType.System; break; 908 default: 909 error2(MID.UnrecognizedLinkageType, idtok); 910 } 911 require2!")"; 912 return linkageType; 913 } 914 915 /// Reports an error if a linkage type has already been parsed. 916 void checkLinkageType(ref LinkageType prev_lt, LinkageType lt, Token* begin) 917 { 918 if (prev_lt == LinkageType.None) 919 prev_lt = lt; 920 else 921 error(begin, MID.RedundantLinkageType, begin.textSpan(prevToken)); 922 } 923 924 /// Returns a StorageClass when the next token is not a "(". 925 StorageClass getSTC() 926 { 927 if (nextIs!"(") 928 return StorageClass.None; 929 auto k = token.kind; 930 return k == T!"const" ? StorageClass.Const : 931 k == T!"immutable" ? StorageClass.Immutable : 932 k == T!"inout" ? StorageClass.Inout : 933 StorageClass.Shared; 934 } 935 936 /// Parses one or more attributes and a Declaration at the end. 937 /// 938 /// $(BNF 939 ////Attributes := 940 //// (StorageAttribute | AlignAttribute | PragmaAttribute | ProtAttribute)* 941 //// DeclsBlock 942 ////StorageAttribute := extern | ExternLinkageType | override | abstract | 943 //// auto | synchronized | static | final | const | immutable | enum | scope 944 ////AlignAttribute := align ("(" Integer ")")? 945 ////PragmaAttribute := pragma "(" Identifier ("," ExpressionList)? ")" 946 ////ProtAttribute := private | public | package | protected | export) 947 /// Params: 948 /// pDecl = Set to the non-attribute Declaration if non-null. 949 Declaration parseAttributes(Declaration* pDecl = null) 950 { 951 StorageClass stcs, // Set to StorageClasses parsed in the loop. 952 stc; // Current StorageClass in the loop. 953 LinkageType linkageType; // Currently parsed LinkageType. 954 Protection protection, // Set to the Protection parsed in the loop. 955 prot; // Current Protection in the loop. 956 uint alignSize; // Set to the AlignSize parsed in the loop. 957 bool testAutoDecl; // Test for: auto Identifier "=" Expression 958 959 // Allocate dummy declarations. 960 scope emptyDecl = new EmptyDecl(); 961 // Function as the head of the attribute chain. 962 scope AttributeDecl headAttr = new StorageClassDecl(STC.None, emptyDecl); 963 964 AttributeDecl currentAttr = headAttr, prevAttr = headAttr; 965 966 // Parse the attributes. 967 Loop: 968 while (1) 969 { 970 auto begin = token; 971 switch (token.kind) 972 { 973 case T!"extern": 974 if (nextIs!"(") 975 { 976 checkLinkageType(linkageType, parseExternLinkageType(), begin); 977 currentAttr = new LinkageDecl(linkageType, emptyDecl); 978 testAutoDecl = false; 979 break; 980 } 981 stc = StorageClass.Extern; goto Lcommon; 982 case T!"override": stc = StorageClass.Override; goto Lcommon; 983 case T!"deprecated": stc = StorageClass.Deprecated; goto Lcommon; 984 case T!"abstract": stc = StorageClass.Abstract; goto Lcommon; 985 case T!"synchronized": stc = StorageClass.Synchronized; goto Lcommon; 986 case T!"static": 987 // Avoid parsing static import, static this etc. 988 if (peekNext().Any!("import", "this", "~", "if", "assert")) 989 break Loop; 990 stc = StorageClass.Static; goto Lcommon; 991 case T!"final": stc = StorageClass.Final; goto Lcommon; 992 version(D2) 993 { 994 case T!"const", T!"immutable", T!"inout", T!"shared": 995 if ((stc = getSTC()) == 0) 996 break Loop; 997 goto Lcommon; 998 case T!"enum": 999 if (!isEnumManifest()) 1000 break Loop; 1001 stc = StorageClass.Manifest; goto Lcommon; 1002 case T!"ref": stc = StorageClass.Ref; goto Lcommon; 1003 case T!"pure": stc = StorageClass.Pure; goto Lcommon; 1004 case T!"nothrow": stc = StorageClass.Nothrow; goto Lcommon; 1005 case T!"__gshared": stc = StorageClass.Gshared; goto Lcommon; 1006 case T!"@": stc = parseAtAttribute(); goto Lcommon; 1007 } // version(D2) 1008 else 1009 { // D1 1010 case T!"const": stc = StorageClass.Const; goto Lcommon; 1011 } 1012 case T!"auto": stc = StorageClass.Auto; goto Lcommon; 1013 case T!"scope": stc = StorageClass.Scope; goto Lcommon; 1014 Lcommon: 1015 if (stcs & stc) // Issue error if redundant. 1016 error2(MID.RedundantStorageClass, token); 1017 stcs |= stc; 1018 nT(); // Skip the storage class token. 1019 currentAttr = new StorageClassDecl(stc, emptyDecl); 1020 testAutoDecl = true; 1021 break; 1022 // Protection attributes: 1023 case T!"private": prot = Protection.Private; goto Lprot; 1024 case T!"package": prot = Protection.Package; goto Lprot; 1025 case T!"protected": prot = Protection.Protected; goto Lprot; 1026 case T!"public": prot = Protection.Public; goto Lprot; 1027 case T!"export": prot = Protection.Export; goto Lprot; 1028 Lprot: 1029 if (protection != Protection.None) 1030 error2(MID.RedundantProtection, token); 1031 protection = prot; 1032 nT(); 1033 currentAttr = new ProtectionDecl(prot, emptyDecl); 1034 testAutoDecl = false; 1035 break; 1036 case T!"align": 1037 // align ("(" Integer ")")? 1038 Token* sizetok; 1039 alignSize = parseAlignAttribute(sizetok); 1040 // TODO: error msg for redundant align attributes. 1041 currentAttr = new AlignDecl(sizetok, emptyDecl); 1042 testAutoDecl = false; 1043 break; 1044 case T!"pragma": 1045 // Pragma := pragma "(" Identifier ("," ExpressionList)? ")" 1046 nT(); 1047 auto paren = requireOpening!"("; 1048 auto ident = requireIdentifier(MID.ExpectedPragmaIdentifier); 1049 auto args = consumed!"," ? parseExpressionList() : null; 1050 requireClosing!")"(paren); 1051 currentAttr = new PragmaDecl(ident, args, emptyDecl); 1052 testAutoDecl = false; 1053 break; 1054 default: 1055 break Loop; 1056 } 1057 // NB: the 'end' member is not set to the end token of 1058 // the declaration, which is parsed below. 1059 // If necessary, this could be fixed by traversing 1060 // the attributes at the end and calling set() there. 1061 set(currentAttr, begin); 1062 // Correct the child node and continue parsing attributes. 1063 prevAttr.setDecls(currentAttr); 1064 prevAttr = currentAttr; // Current becomes previous. 1065 } 1066 1067 // Parse the declaration. 1068 Declaration decl; 1069 if (!linkageType) 1070 linkageType = this.linkageType; 1071 // Save attributes. 1072 auto outer_storageClass = this.storageClass; 1073 auto outer_linkageType = this.linkageType; 1074 auto outer_protection = this.protection; 1075 auto outer_alignSize = this.alignSize; 1076 // Set parsed values. 1077 stcs |= outer_storageClass; // Combine with outer stcs. 1078 this.storageClass = stcs; 1079 this.linkageType = linkageType; 1080 this.protection = protection; 1081 this.alignSize = alignSize; 1082 if (testAutoDecl && tokenIs!"Identifier") // "auto" Identifier "=" 1083 decl = // This could be a normal Declaration or an AutoDeclaration 1084 parseVariablesOrFunction(stcs, protection, linkageType, true); 1085 else 1086 { 1087 if (prevAttr.Is!PragmaDecl && tokenIs!";") 1088 decl = parseDeclarationDefinition(); // Allow semicolon after pragma(). 1089 else // Parse a block. 1090 decl = parseDeclarationsBlock(); 1091 } 1092 // Restore outer values. 1093 this.storageClass = outer_storageClass; 1094 this.linkageType = outer_linkageType; 1095 this.protection = outer_protection; 1096 this.alignSize = outer_alignSize; 1097 if (pDecl) 1098 *pDecl = decl; 1099 1100 assert(decl !is null && isNodeSet(decl)); 1101 // Attach the declaration to the previously parsed attribute. 1102 prevAttr.setDecls(decl); 1103 // Return the first attribute declaration. 1104 return headAttr.decls; 1105 } 1106 1107 /// $(BNF AlignAttribute := align ("(" Integer ")")?) 1108 uint parseAlignAttribute(out Token* sizetok) 1109 { 1110 skip!"align"; 1111 uint size; 1112 if (consumed!"(") 1113 { 1114 if (tokenIs!"Int32") 1115 (sizetok = token), (size = token.int_), skip!"Int32"; 1116 else 1117 expected!"Int32"; 1118 require2!")"; 1119 } 1120 return size; 1121 } 1122 1123 /// $(BNF AtAttribute := "@" Identifier) 1124 StorageClass parseAtAttribute() 1125 { 1126 skip!"@"; 1127 StorageClass stc; 1128 if (tokenIs!"Identifier") 1129 switch (token.ident.idKind) 1130 { 1131 case IDK.disable: stc = StorageClass.Disable; break; 1132 case IDK.property: stc = StorageClass.Property; break; 1133 case IDK.safe: stc = StorageClass.Safe; break; 1134 case IDK.system: stc = StorageClass.System; break; 1135 case IDK.trusted: stc = StorageClass.Trusted; break; 1136 default: 1137 error2(MID.UnrecognizedAttribute, token); 1138 } 1139 else 1140 error2(MID.ExpectedAttributeId, token); 1141 // Return without skipping the identifier. 1142 return stc; 1143 } 1144 1145 /// $(BNF ImportDecl := static? import 1146 //// ImportModule ("," ImportModule)* 1147 //// (":" ImportBind ("," ImportBind)*)? 1148 //// ";" 1149 ////ImportModule := (AliasName "=")? ModuleName 1150 ////ImportBind := (AliasName "=")? BindName 1151 ////ModuleName := Identifier ("." Identifier)* 1152 ////AliasName := Identifier 1153 ////BindName := Identifier) 1154 ImportDecl parseImportDecl() 1155 { 1156 bool isStatic = consumed!"static"; 1157 skip!"import"; 1158 1159 ModuleFQN[] moduleFQNs; 1160 Token*[] moduleAliases; 1161 Token*[] bindNames; 1162 Token*[] bindAliases; 1163 1164 do 1165 { 1166 ModuleFQN moduleFQN; 1167 Token* moduleAlias; 1168 // AliasName = ModuleName 1169 if (nextIs!"=") 1170 { 1171 moduleAlias = requireIdentifier(MID.ExpectedAliasModuleName); 1172 skip!"="; 1173 } 1174 // Identifier ("." Identifier)* 1175 do 1176 moduleFQN ~= requireIdentifier(MID.ExpectedModuleIdentifier); 1177 while (consumed!"."); 1178 // Push identifiers. 1179 moduleFQNs ~= moduleFQN; 1180 moduleAliases ~= moduleAlias; 1181 } while (consumed!","); 1182 1183 if (consumed!":") 1184 { // ImportBind := (BindAlias "=")? BindName 1185 // ":" ImportBind ("," ImportBind)* 1186 do 1187 { 1188 Token* bindAlias; 1189 // BindAlias = BindName 1190 if (nextIs!"=") 1191 { 1192 bindAlias = requireIdentifier(MID.ExpectedAliasImportName); 1193 skip!"="; 1194 } 1195 // Push identifiers. 1196 bindNames ~= requireIdentifier(MID.ExpectedImportName); 1197 bindAliases ~= bindAlias; 1198 } while (consumed!","); 1199 } 1200 require2!";"; 1201 1202 return new ImportDecl(moduleFQNs, moduleAliases, bindNames, 1203 bindAliases, isStatic); 1204 } 1205 1206 /// Returns true if this is an enum manifest or 1207 /// false if it's a normal enum declaration. 1208 bool isEnumManifest() 1209 { 1210 version(D2) 1211 { 1212 assert(tokenIs!"enum"); 1213 auto next = peekAfter(token); 1214 auto kind = next.kind; 1215 if (kind.Any!(":", "{")) 1216 return false; // Anonymous enum. 1217 else 1218 if (kind == T!"Identifier" && peekAfter(next).kind.Any!(":", "{", ";")) 1219 return false; // Named enum. 1220 return true; // Manifest enum. 1221 } 1222 assert(0); 1223 } 1224 1225 /// $(BNF 1226 ////EnumDecl := 1227 //// enum Name? (":" BasicType)? EnumBody | 1228 //// enum Name ";" 1229 ////EnumBody := "{" EnumMembers "}" 1230 ////EnumMembers := EnumMember ("," EnumMember)* ","? 1231 ////EnumMembers2 := Type? EnumMember ("," Type? EnumMember)* ","? # D2.0 1232 ////EnumMember := Name ("=" AssignExpr)?) 1233 Declaration parseEnumDecl() 1234 { 1235 skip!"enum"; 1236 1237 EnumMemberDecl[] members; 1238 1239 auto enumName = optionalIdentifier(); 1240 auto baseType = consumed!":" ? parseBasicType() : null; 1241 1242 if (!enumName || !consumed!";") 1243 if (auto brace = consumedToken!"{") 1244 { 1245 while (!tokenIs!"}") 1246 { 1247 auto begin = token; 1248 Type type; // Optional member type. 1249 1250 version(D2) 1251 if (!peekNext().Any!("=", ",", "}")) 1252 type = parseType(); 1253 1254 auto name = requireIdentifier(MID.ExpectedEnumMember); 1255 // "=" AssignExpr 1256 auto value = consumed!"=" ? parseAssignExpr() : null; 1257 auto member = new EnumMemberDecl(type, name, value); 1258 members ~= set(member, begin); 1259 1260 if (!consumed!",") 1261 break; 1262 } 1263 requireClosing!"}"(brace); 1264 } 1265 else 1266 error2(MID.ExpectedEnumBody, token); 1267 1268 return new EnumDecl(enumName, baseType, members); 1269 } 1270 1271 /// Wraps a declaration inside a template declaration. 1272 /// Params: 1273 /// begin = Begin token of decl. 1274 /// name = Name of decl. 1275 /// decl = The declaration to be wrapped. 1276 /// tparams = The template parameters. 1277 /// constraint = The constraint expression. 1278 TemplateDecl putInsideTemplateDeclaration( 1279 Token* begin, 1280 Token* name, 1281 Declaration decl, 1282 TemplateParameters tparams, 1283 Expression constraint) 1284 { 1285 set(decl, begin); 1286 auto cd = new CompoundDecl; 1287 cd ~= decl; 1288 set(cd, begin); 1289 decl.setStorageClass(this.storageClass); 1290 decl.setProtection(this.protection); 1291 return new TemplateDecl(name, tparams, constraint, cd); 1292 } 1293 1294 /// $(BNF ClassDecl := 1295 //// class Name TemplateParameterList? (":" BaseClasses) ClassBody | 1296 //// class Name ";" 1297 ////ClassBody := DeclDefsBlock) 1298 Declaration parseClassDecl() 1299 { 1300 auto begin = token; 1301 skip!"class"; 1302 1303 TemplateParameters tparams; 1304 Expression constraint; 1305 CompoundDecl decls; 1306 1307 auto name = requireIdentifier(MID.ExpectedClassName); 1308 1309 if (tokenIs!"(") 1310 { 1311 tparams = parseTemplateParameterList(); 1312 version(D2) constraint = parseOptionalConstraint(); 1313 } 1314 1315 auto bases = consumed!":" ? parseBaseClasses() : null; 1316 1317 version(D2) 1318 if (bases.length && tokenIs!"if") 1319 { 1320 if (constraint) 1321 error(MID.RedundantConstraint); 1322 constraint = parseOptionalConstraint(); 1323 } 1324 1325 if (bases.length || !consumed!";") 1326 if (tokenIs!"{") 1327 decls = parseDeclarationDefinitionsBody(); 1328 else 1329 error2(MID.ExpectedClassBody, token); 1330 1331 Declaration d = new ClassDecl(name, /+tparams, +/bases, decls); 1332 if (tparams) 1333 d = putInsideTemplateDeclaration(begin, name, d, tparams, constraint); 1334 return d; 1335 } 1336 1337 /// $(BNF BaseClasses := BaseClass ("," BaseClass)* 1338 ////BaseClass := Protection? BasicType 1339 ////Protection := private | public | protected | package) 1340 BaseClassType[] parseBaseClasses() 1341 { 1342 BaseClassType[] bases; 1343 do 1344 { 1345 Protection prot; 1346 switch (token.kind) 1347 { 1348 case T!"Identifier", T!".", T!"typeof": goto LparseBasicType; 1349 case T!"private": prot = Protection.Private; break; 1350 case T!"protected": prot = Protection.Protected; break; 1351 case T!"package": prot = Protection.Package; break; 1352 case T!"public": prot = Protection.Public; break; 1353 default: 1354 error2(MID.ExpectedBaseClasses, token); 1355 return bases; 1356 } 1357 nT(); // Skip protection attribute. 1358 LparseBasicType: 1359 auto begin = token; 1360 auto type = parseBasicType(); 1361 bases ~= set(new BaseClassType(prot, type), begin); 1362 } while (consumed!","); 1363 return bases; 1364 } 1365 1366 /// $(BNF InterfaceDecl := 1367 //// interface Name TemplateParameterList? (":" BaseClasses) InterfaceBody | 1368 //// interface Name ";" 1369 ////InterfaceBody := DeclDefsBlock) 1370 Declaration parseInterfaceDecl() 1371 { 1372 auto begin = token; 1373 skip!"interface"; 1374 1375 TemplateParameters tparams; 1376 Expression constraint; 1377 CompoundDecl decls; 1378 1379 auto name = requireIdentifier(MID.ExpectedInterfaceName); 1380 1381 if (tokenIs!"(") 1382 { 1383 tparams = parseTemplateParameterList(); 1384 version(D2) constraint = parseOptionalConstraint(); 1385 } 1386 1387 auto bases = consumed!":" ? parseBaseClasses() : null; 1388 1389 version(D2) 1390 if (bases.length && tokenIs!"if") 1391 { 1392 if (constraint) 1393 error(MID.RedundantConstraint); 1394 constraint = parseOptionalConstraint(); 1395 } 1396 1397 if (bases.length || !consumed!";") 1398 if (tokenIs!"{") 1399 decls = parseDeclarationDefinitionsBody(); 1400 else 1401 error2(MID.ExpectedInterfaceBody, token); 1402 1403 Declaration d = new InterfaceDecl(name, bases, decls); 1404 if (tparams) 1405 d = putInsideTemplateDeclaration(begin, name, d, tparams, constraint); 1406 return d; 1407 } 1408 1409 /// $(BNF StructDecl := 1410 //// struct Name? TemplateParameterList? StructBody | 1411 //// struct Name ";" 1412 ////StructBody := DeclDefsBlock 1413 ////UnionDecl := 1414 //// union Name? TemplateParameterList? UnionBody | 1415 //// union Name ";" 1416 ////UnionBody := DeclDefsBlock) 1417 Declaration parseStructOrUnionDecl() 1418 { 1419 assert(token.kind.Any!("struct", "union")); 1420 auto begin = token; 1421 nT(); 1422 1423 TemplateParameters tparams; 1424 Expression constraint; 1425 CompoundDecl decls; 1426 1427 auto name = optionalIdentifier(); 1428 1429 if (name && tokenIs!"(") 1430 { 1431 tparams = parseTemplateParameterList(); 1432 version(D2) constraint = parseOptionalConstraint(); 1433 } 1434 1435 if (!name || !consumed!";") 1436 if (tokenIs!"{") 1437 decls = parseDeclarationDefinitionsBody(); 1438 else 1439 error2(begin.kind == T!"struct" ? 1440 MID.ExpectedStructBody : MID.ExpectedUnionBody, token); 1441 1442 Declaration d; 1443 if (begin.kind == T!"struct") 1444 { 1445 auto sd = new StructDecl(name, /+tparams, +/decls); 1446 sd.setAlignSize(this.alignSize); 1447 d = sd; 1448 } 1449 else 1450 d = new UnionDecl(name, /+tparams, +/decls); 1451 1452 if (tparams) 1453 d = putInsideTemplateDeclaration(begin, name, d, tparams, constraint); 1454 return d; 1455 } 1456 1457 /// $(BNF ConstructorDecl := this ParameterList FunctionBody) 1458 Declaration parseConstructorDecl() 1459 { 1460 version(D2) 1461 { 1462 auto begin = token; 1463 TemplateParameters tparams; 1464 Expression constraint; 1465 skip!"this"; 1466 if (tokenIs!"(" && tokenAfterParenIs(T!"(")) 1467 tparams = parseTemplateParameterList(); // "(" TemplateParameterList ")" 1468 Parameters parameters; 1469 if (!nextIs!"this") 1470 parameters = parseParameterList(); // "(" ParameterList ")" 1471 else // PostBlit := this "(" this ")" 1472 { 1473 auto paren = requireOpening!"("; 1474 parameters = new Parameters(); 1475 auto this_ = consume(); 1476 auto thisParam = new Parameter(STC.None, null, null, this_, null); 1477 parameters ~= set(thisParam, this_); 1478 requireClosing!")"(paren); 1479 set(parameters, paren); 1480 } 1481 parameters.postSTCs = parseFunctionPostfix(); 1482 // FIXME: |= to storageClass?? Won't this affect other decls? 1483 this.storageClass |= parameters.postSTCs; // Combine with current stcs. 1484 if (tparams) // if "(" ConstraintExpr ")" 1485 constraint = parseOptionalConstraint(); 1486 auto funcBody = parseFunctionBody(); 1487 Declaration d = new ConstructorDecl(parameters, funcBody); 1488 if (tparams) 1489 d = putInsideTemplateDeclaration(begin, begin, d, tparams, constraint); 1490 return d; 1491 } // version(D2) 1492 else 1493 { // D1 1494 skip!"this"; 1495 auto parameters = parseParameterList(); 1496 auto funcBody = parseFunctionBody(); 1497 return new ConstructorDecl(parameters, funcBody); 1498 } 1499 } 1500 1501 /// $(BNF DestructorDecl := "~" this "(" ")" FunctionBody) 1502 Declaration parseDestructorDecl() 1503 { 1504 skip!"~"; 1505 require2!"this"; 1506 require2!"("; 1507 require2!")"; 1508 auto funcBody = parseFunctionBody(); 1509 return new DestructorDecl(funcBody); 1510 } 1511 1512 /// $(BNF StaticCtorDecl := static this "(" ")" FunctionBody) 1513 Declaration parseStaticCtorDecl() 1514 { 1515 skip!"static"; 1516 skip!"this"; 1517 require2!"("; 1518 require2!")"; 1519 auto funcBody = parseFunctionBody(); 1520 return new StaticCtorDecl(funcBody); 1521 } 1522 1523 /// $(BNF 1524 ////StaticDtorDecl := static "~" this "(" ")" FunctionBody) 1525 Declaration parseStaticDtorDecl() 1526 { 1527 skip!"static"; 1528 skip!"~"; 1529 require2!"this"; 1530 require2!"("; 1531 require2!")"; 1532 auto funcBody = parseFunctionBody(); 1533 return new StaticDtorDecl(funcBody); 1534 } 1535 1536 /// $(BNF InvariantDecl := invariant ("(" ")")? FunctionBody) 1537 Declaration parseInvariantDecl() 1538 { 1539 skip!"invariant"; 1540 if (consumed!"(") // Optional "(" ")" 1541 require2!")"; 1542 auto funcBody = parseFunctionBody(); 1543 return new InvariantDecl(funcBody); 1544 } 1545 1546 /// $(BNF UnittestDecl := unittest FunctionBody) 1547 Declaration parseUnittestDecl() 1548 { 1549 skip!"unittest"; 1550 if (!tokenIs!"{") 1551 error2(MID.ExpectedUnittestBody, token); 1552 auto funcBody = parseFunctionBody(); 1553 return new UnittestDecl(funcBody); 1554 } 1555 1556 /// Parses an identifier or an integer. Reports an error otherwise. 1557 /// $(BNF IdentOrInt := Identifier | Integer) 1558 Token* parseIdentOrInt() 1559 { 1560 if (token.kind.Any!("Identifier", "Int32")) 1561 return consume(); 1562 error2(MID.ExpectedIdentOrInt, token); 1563 return null; 1564 } 1565 1566 /// $(BNF VersionCondition := unittest #*D2.0*# | IdentOrInt) 1567 Token* parseVersionCondition() 1568 { 1569 version(D2) 1570 if (token.kind.Any!("unittest", "assert")) 1571 return consume(); 1572 return parseIdentOrInt(); 1573 } 1574 1575 /// $(BNF DebugDecl := 1576 //// debug "=" IdentOrInt ";" | 1577 //// debug DebugCondition? DeclsBlock (else DeclsBlock)? 1578 ////DebugCondition := "(" IdentOrInt ")") 1579 Declaration parseDebugDecl() 1580 { 1581 skip!"debug"; 1582 Token* spec, cond; 1583 Declaration decls, elseDecls; 1584 if (consumed!"=") 1585 { // debug "=" (Integer | Identifier) ";" 1586 spec = parseIdentOrInt(); 1587 require2!";"; 1588 } 1589 else 1590 { 1591 if (auto paren = consumedToken!"(") 1592 { // "(" Condition ")" 1593 cond = parseIdentOrInt(); 1594 requireClosing!")"(paren); 1595 } 1596 decls = parseDeclarationsBlock(); // DeclsBlock 1597 if (consumed!"else") // else DeclsBlock 1598 elseDecls = parseDeclarationsBlock(); 1599 } 1600 return new DebugDecl(spec, cond, decls, elseDecls); 1601 } 1602 1603 /// $(BNF VersionDecl := 1604 //// version "=" IdentOrInt ";" | 1605 //// version VCondition DeclsBlock (else DeclsBlock)? 1606 ////VCondition := "(" VersionCondition ")") 1607 Declaration parseVersionDecl() 1608 { 1609 skip!"version"; 1610 Token* spec, cond; 1611 Declaration decls, elseDecls; 1612 if (consumed!"=") 1613 { // version = (Integer | Identifier) ";" 1614 spec = parseIdentOrInt(); 1615 require2!";"; 1616 } 1617 else 1618 { // "(" Condition ")" 1619 auto paren = requireOpening!"("; 1620 cond = parseVersionCondition(); 1621 requireClosing!")"(paren); 1622 decls = parseDeclarationsBlock(); // DeclsBlock 1623 if (consumed!"else") // else DeclsBlock 1624 elseDecls = parseDeclarationsBlock(); 1625 } 1626 return new VersionDecl(spec, cond, decls, elseDecls); 1627 } 1628 1629 /// $(BNF StaticIfDecl := 1630 //// static if "(" AssignExpr ")" DeclsBlock (else DeclsBlock)?) 1631 Declaration parseStaticIfDecl() 1632 { 1633 skip!"static"; 1634 skip!"if"; 1635 auto paren = requireOpening!"("; 1636 auto condition = parseAssignExpr(); 1637 requireClosing!")"(paren); 1638 auto ifDecls = parseDeclarationsBlock(); 1639 auto elseDecls = consumed!"else" ? parseDeclarationsBlock() : null; 1640 return new StaticIfDecl(condition, ifDecls, elseDecls); 1641 } 1642 1643 /// $(BNF StaticAssertDecl := 1644 //// static assert "(" AssignExpr ("," Message)? ")" ";" 1645 ////Message := AssignExpr) 1646 Declaration parseStaticAssertDecl() 1647 { 1648 skip!"static"; 1649 skip!"assert"; 1650 auto paren = requireOpening!"("; 1651 auto condition = parseAssignExpr(); 1652 auto message = consumed!"," ? parseAssignExpr() : null; 1653 requireClosing!")"(paren); 1654 require2!";"; 1655 return new StaticAssertDecl(condition, message); 1656 } 1657 1658 /// $(BNF TemplateDecl := 1659 //// template Name TemplateParameterList Constraint? DeclDefsBlock) 1660 TemplateDecl parseTemplateDecl() 1661 { 1662 skip!"template"; 1663 auto name = requireIdentifier(MID.ExpectedTemplateName); 1664 auto tparams = parseTemplateParameterList(); 1665 auto constraint = parseOptionalConstraint(); 1666 auto decls = parseDeclarationDefinitionsBody(); 1667 return new TemplateDecl(name, tparams, constraint, decls); 1668 } 1669 1670 /// $(BNF NewDecl := new ParameterList FunctionBody) 1671 Declaration parseNewDecl() 1672 { 1673 skip!"new"; 1674 auto parameters = parseParameterList(); 1675 auto funcBody = parseFunctionBody(); 1676 return new NewDecl(parameters, funcBody); 1677 } 1678 1679 /// $(BNF DeleteDecl := delete ParameterList FunctionBody) 1680 Declaration parseDeleteDecl() 1681 { 1682 skip!"delete"; 1683 auto parameters = parseParameterList(); 1684 auto funcBody = parseFunctionBody(); 1685 return new DeleteDecl(parameters, funcBody); 1686 } 1687 1688 /// Parses a MixinDecl or MixinStmt. 1689 /// $(BNF 1690 ////MixinDecl := (MixinExpr | MixinTemplate | MixinTemplateId) ";" 1691 ////MixinExpr := mixin "(" AssignExpr ")" 1692 ////MixinTemplate := mixin TemplateDecl # D2 1693 ////MixinTemplateId := mixin TemplateIdentifier 1694 //// ("!" "(" TemplateArguments ")")? MixinIdentifier?) 1695 RetT parseMixin(Class, RetT = Class)() 1696 { 1697 static assert(is(Class == MixinDecl) || is(Class == MixinStmt)); 1698 skip!"mixin"; 1699 1700 static if (is(Class == MixinDecl)) 1701 { 1702 if (auto paren = consumedToken!"(") 1703 { 1704 auto e = parseAssignExpr(); 1705 requireClosing!")"(paren); 1706 require2!";"; 1707 return new MixinDecl(e); 1708 } 1709 else version(D2) if (tokenIs!"template") 1710 { 1711 auto d = parseTemplateDecl(); 1712 d.isMixin = true; 1713 return d; 1714 } // version(D2) 1715 } 1716 1717 auto e = parseIdentifiersExpr(); 1718 auto mixinIdent = optionalIdentifier(); 1719 require2!";"; 1720 1721 return new Class(e, mixinIdent); 1722 } 1723 1724 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1725 | Statement parsing methods | 1726 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ 1727 1728 /// $(BNF Statements := "{" Statement* "}") 1729 CompoundStmt parseStatements() 1730 { 1731 auto brace = requireOpening!"{"; 1732 auto statements = new CompoundStmt(); 1733 while (!token.kind.Any!("}", "EOF")) 1734 statements ~= parseStatement(); 1735 requireClosing!"}"(brace); 1736 return set(statements, brace); 1737 } 1738 1739 /// Parses a Statement. 1740 Statement parseStatement() 1741 { 1742 auto begin = token; 1743 Statement s; 1744 Declaration d; 1745 1746 if (token.isIntegralType) 1747 { 1748 d = parseVariablesOrFunction(); 1749 goto LreturnDeclarationStmt; 1750 } 1751 1752 switch (token.kind) 1753 { 1754 case T!"align": 1755 Token* sizetok; 1756 uint size = parseAlignAttribute(sizetok); 1757 // Restrict align attribute to structs in parsing phase. 1758 StructDecl structDecl; 1759 if (tokenIs!"struct") 1760 { 1761 auto begin2 = token; 1762 structDecl = parseStructOrUnionDecl().to!(StructDecl); 1763 structDecl.setAlignSize(size); 1764 set(structDecl, begin2); 1765 } 1766 else 1767 expected!"struct"; 1768 1769 d = structDecl ? cast(Declaration)structDecl : new CompoundDecl; 1770 d = new AlignDecl(sizetok, d); 1771 goto LreturnDeclarationStmt; 1772 1773 case T!"extern", T!"const", T!"auto": 1774 //T!"final", T!"scope", T!"static": 1775 goto case_parseAttribute; 1776 version(D2) 1777 { 1778 case T!"immutable", T!"inout", T!"pure", T!"shared", T!"__gshared", 1779 T!"ref", T!"nothrow", T!"@": 1780 goto case_parseAttribute; 1781 } 1782 1783 case T!"Identifier": 1784 if (nextIs!":") 1785 { 1786 skip!"Identifier"; skip!":"; 1787 s = new LabeledStmt(begin, parseNoScopeOrEmptyStmt()); 1788 break; 1789 } 1790 goto case T!"."; 1791 version(D2) 1792 { 1793 case T!"this", T!"super": 1794 goto case T!"."; 1795 } 1796 case T!".", T!"typeof": 1797 bool success; 1798 d = tryToParse({ return parseVariablesOrFunction(); }, success); 1799 if (success) 1800 goto LreturnDeclarationStmt; // Declaration 1801 else 1802 goto case_parseExpressionStmt; // Expression 1803 case T!"if": s = parseIfStmt(); break; 1804 case T!"while": s = parseWhileStmt(); break; 1805 case T!"do": s = parseDoWhileStmt(); break; 1806 case T!"for": s = parseForStmt(); break; 1807 case T!"foreach", 1808 T!"foreach_reverse": s = parseForeachStmt(); break; 1809 case T!"switch": s = parseSwitchStmt(); break; 1810 case T!"case": s = parseCaseStmt(); break; 1811 case T!"default": s = parseDefaultStmt(); break; 1812 case T!"continue": s = parseContinueStmt(); break; 1813 case T!"break": s = parseBreakStmt(); break; 1814 case T!"return": s = parseReturnStmt(); break; 1815 case T!"goto": s = parseGotoStmt(); break; 1816 case T!"with": s = parseWithStmt(); break; 1817 case T!"synchronized": s = parseSynchronizedStmt(); break; 1818 case T!"try": s = parseTryStmt(); break; 1819 case T!"throw": s = parseThrowStmt(); break; 1820 case T!"volatile": s = parseVolatileStmt(); break; 1821 case T!"asm": s = parseAsmBlockStmt(); break; 1822 case T!"pragma": s = parsePragmaStmt(); break; 1823 case T!"debug": s = parseDebugStmt(); break; 1824 case T!"version": s = parseVersionStmt(); break; 1825 case T!"{": s = parseScopeStmt(); break; 1826 case T!";": nT(); s = new EmptyStmt(); break; 1827 case_T_Scope: s = parseScopeGuardStmt(); break; 1828 case_T_Mixin: s = parseMixin!(MixinStmt)(); break; 1829 case_parseAttribute: s = parseAttributeStmt(); break; 1830 case T!"scope": 1831 if (!nextIs!"(") 1832 goto case_parseAttribute; 1833 goto case_T_Scope; 1834 case T!"mixin": 1835 if (nextIs!"(") 1836 goto case_parseExpressionStmt; // Parse as expression. 1837 goto case_T_Mixin; 1838 case T!"final": 1839 version(D2) 1840 { 1841 if (nextIs!"switch") 1842 goto case T!"switch"; 1843 } 1844 goto case_parseAttribute; 1845 case T!"static": 1846 switch (peekNext()) 1847 { 1848 case T!"if": s = parseStaticIfStmt(); break; 1849 case T!"assert": s = parseStaticAssertStmt(); break; 1850 default: goto case_parseAttribute; 1851 } 1852 break; 1853 // DeclDef 1854 case T!"alias", T!"typedef": 1855 d = parseDeclarationDefinition(); 1856 goto LreturnDeclarationStmt; 1857 case T!"enum": 1858 version(D2) 1859 if (isEnumManifest()) 1860 goto case_parseAttribute; 1861 d = parseEnumDecl(); 1862 goto LreturnDeclarationStmt; 1863 case T!"class": 1864 d = parseClassDecl(); 1865 goto LreturnDeclarationStmt; 1866 case T!"import": 1867 version(D2) 1868 { 1869 if (!nextIs!"(") 1870 { 1871 d = parseImportDecl(); 1872 goto LreturnDeclarationStmt; 1873 } 1874 } 1875 goto case_parseExpressionStmt; 1876 case T!"interface": 1877 d = parseInterfaceDecl(); 1878 goto LreturnDeclarationStmt; 1879 case T!"struct", T!"union": 1880 d = parseStructOrUnionDecl(); 1881 // goto LreturnDeclarationStmt; 1882 LreturnDeclarationStmt: 1883 set(d, begin); 1884 s = new DeclarationStmt(d); 1885 break; 1886 // Parse an ExpressionStmt: 1887 // Tokens that start a PrimaryExpr. 1888 // case T!"Identifier", T!".", T!"typeof": 1889 version(D1) 1890 { 1891 case T!"this": 1892 case T!"super": 1893 } 1894 case T!"null": 1895 case T!"true", T!"false": 1896 // case T!"$": 1897 case T!"Int32", T!"Int64", T!"UInt32", T!"UInt64": 1898 case T!"Float32", T!"Float64", T!"Float80", 1899 T!"IFloat32", T!"IFloat64", T!"IFloat80": 1900 case T!"Character": 1901 case T!"String": 1902 case T!"[": 1903 // case T!"{": 1904 case T!"function", T!"delegate": 1905 case T!"assert": 1906 // case T!"mixin": 1907 case T!"typeid": 1908 case T!"is": 1909 case T!"(": 1910 version(D2) 1911 { 1912 case T!"__traits": 1913 } 1914 // Tokens that can start a UnaryExpr: 1915 case T!"&", T!"++", T!"--", T!"*", T!"-", 1916 T!"+", T!"!", T!"~", T!"new", T!"delete", T!"cast": 1917 case_parseExpressionStmt: 1918 s = new ExpressionStmt(parseExpression()); 1919 require2!";"; 1920 break; 1921 default: 1922 if (token.isSpecialToken) 1923 goto case_parseExpressionStmt; 1924 1925 if (!tokenIs!"$") 1926 // Assert that this isn't a valid expression. 1927 assert(delegate bool(){ 1928 bool success; 1929 auto expression = tryToParse(&parseExpression, success); 1930 return success; 1931 }() == false, "Didn't expect valid expression." 1932 ); 1933 1934 // Report error: it's an illegal statement. 1935 s = new IllegalStmt(); 1936 // Skip to next valid token. 1937 do 1938 nT(); 1939 while (!token.isStatementStart() && !token.kind.Any!("}", "EOF")); 1940 auto text = begin.textSpan(this.prevToken); 1941 error(begin, MID.IllegalStatement, text); 1942 } 1943 assert(s !is null); 1944 set(s, begin); 1945 return s; 1946 } 1947 1948 /// Parses a ScopeStmt. 1949 /// $(BNF ScopeStmt := NoScopeStmt) 1950 Statement parseScopeStmt() 1951 { 1952 auto s = parseNoScopeStmt(); 1953 return set(new ScopeStmt(s), s.begin); 1954 } 1955 1956 /// $(BNF 1957 ////NoScopeStmt := NonEmptyStmt | BlockStmt 1958 ////BlockStmt := Statements) 1959 Statement parseNoScopeStmt() 1960 { 1961 if (tokenIs!"{") 1962 return parseStatements(); 1963 else 1964 { 1965 if (tokenIs!";") 1966 error(MID.ExpectedNonEmptyStatement, token); 1967 return parseStatement(); 1968 } 1969 } 1970 1971 /// $(BNF NoScopeOrEmptyStmt := ";" | NoScopeStmt) 1972 Statement parseNoScopeOrEmptyStmt() 1973 { 1974 if (auto semicolon = consumedToken!";") 1975 return set(new EmptyStmt(), semicolon); 1976 else 1977 return parseNoScopeStmt(); 1978 } 1979 1980 /// $(BNF AttributeStmt := Attributes+ 1981 //// (VariableOrFunctionDecl | DeclDef) 1982 ////Attributes := extern | ExternLinkageType | auto | static | 1983 //// final | const | immutable | enum | scope) 1984 Statement parseAttributeStmt() 1985 { 1986 StorageClass stcs, stc; 1987 LinkageType linkageType; 1988 bool testAutoDecl; 1989 1990 // Allocate dummy declarations. 1991 scope emptyDecl = new EmptyDecl(); 1992 // Function as the head of the attribute chain. 1993 scope AttributeDecl headAttr = 1994 new StorageClassDecl(StorageClass.None, emptyDecl); 1995 1996 AttributeDecl currentAttr, prevAttr = headAttr; 1997 1998 // Parse the attributes. 1999 Loop: 2000 while (1) 2001 { 2002 auto begin = token; 2003 switch (token.kind) 2004 { 2005 case T!"extern": 2006 if (nextIs!"(") 2007 { 2008 checkLinkageType(linkageType, parseExternLinkageType(), begin); 2009 currentAttr = new LinkageDecl(linkageType, emptyDecl); 2010 testAutoDecl = false; 2011 break; 2012 } 2013 stc = StorageClass.Extern; goto Lcommon; 2014 case T!"static": stc = StorageClass.Static; goto Lcommon; 2015 case T!"final": stc = StorageClass.Final; goto Lcommon; 2016 version(D2) 2017 { 2018 case T!"const", T!"immutable", T!"inout", T!"shared": 2019 if ((stc = getSTC()) == 0) 2020 break Loop; 2021 goto Lcommon; 2022 case T!"enum": 2023 if (!isEnumManifest()) 2024 break Loop; 2025 stc = StorageClass.Manifest; goto Lcommon; 2026 case T!"ref": stc = StorageClass.Ref; goto Lcommon; 2027 case T!"pure": stc = StorageClass.Pure; goto Lcommon; 2028 case T!"nothrow": stc = StorageClass.Nothrow; goto Lcommon; 2029 case T!"__gshared": stc = StorageClass.Gshared; goto Lcommon; 2030 case T!"@": stc = parseAtAttribute(); goto Lcommon; 2031 } // version(D2) 2032 else 2033 { // D1 2034 case T!"const": stc = StorageClass.Const; goto Lcommon; 2035 } 2036 case T!"auto": stc = StorageClass.Auto; goto Lcommon; 2037 case T!"scope": stc = StorageClass.Scope; goto Lcommon; 2038 Lcommon: 2039 if (stcs & stc) // Issue error if redundant. 2040 error2(MID.RedundantStorageClass, token); 2041 stcs |= stc; 2042 nT(); // Skip the storage class token. 2043 currentAttr = new StorageClassDecl(stc, emptyDecl); 2044 testAutoDecl = true; 2045 break; 2046 default: 2047 break Loop; 2048 } 2049 set(currentAttr, begin); 2050 // Correct the child node and continue parsing attributes. 2051 prevAttr.setDecls(currentAttr); 2052 prevAttr = currentAttr; // Current becomes previous. 2053 } 2054 2055 // Parse the declaration. 2056 Declaration decl; 2057 assert(this.storageClass == StorageClass.None); 2058 assert(this.protection == Protection.None); 2059 assert(this.linkageType == LinkageType.None); 2060 if (token.kind.Any!("class", "interface", "struct", "union", "alias", 2061 "typedef", "enum")) 2062 { 2063 // Set current values. 2064 this.storageClass = stcs; 2065 this.linkageType = linkageType; 2066 // Parse a declaration. 2067 decl = parseDeclarationDefinition(); 2068 // Clear values. 2069 this.storageClass = StorageClass.None; 2070 this.linkageType = LinkageType.None; 2071 } 2072 else 2073 decl = 2074 parseVariablesOrFunction(stcs, protection, linkageType, testAutoDecl); 2075 assert(decl !is null && isNodeSet(decl)); 2076 // Attach the declaration to the previously parsed attribute. 2077 prevAttr.setDecls(decl); 2078 // Return the first attribute declaration. Wrap it in a Statement. 2079 return new DeclarationStmt(headAttr.decls); 2080 } 2081 2082 /// $(BNF IfStmt := if "(" Condition ")" ScopeStmt (else ScopeStmt)? 2083 ////Condition := AutoDecl | VariableDecl | Expression) 2084 Statement parseIfStmt() 2085 { 2086 skip!"if"; 2087 auto paren = requireOpening!"("; 2088 2089 Declaration variable; 2090 Expression condition; 2091 Type type; 2092 Token* name; 2093 auto begin = token; // For start of AutoDecl or normal Declaration. 2094 bool success; 2095 2096 tryToParse({ 2097 if (consumed!"auto") // auto Identifier = Expression 2098 name = requireIdentifier(MID.ExpectedVariableName); 2099 else // Declarator "=" Expression 2100 type = parseDeclarator(name); 2101 require!"="; 2102 return type; 2103 }, success); 2104 2105 if (success) 2106 { 2107 auto init = parseExpression(); 2108 variable = new VariablesDecl(type, [name], [init]); 2109 set(variable, begin); 2110 } 2111 else // Normal Expression. 2112 condition = parseExpression(); 2113 2114 requireClosing!")"(paren); 2115 auto ifBody = parseScopeStmt(); 2116 auto elseBody = consumed!"else" ? parseScopeStmt() : null; 2117 return new IfStmt(variable, condition, ifBody, elseBody); 2118 } 2119 2120 /// $(BNF WhileStmt := while "(" Expression ")" ScopeStmt) 2121 Statement parseWhileStmt() 2122 { 2123 skip!"while"; 2124 auto paren = requireOpening!"("; 2125 auto condition = parseExpression(); 2126 requireClosing!")"(paren); 2127 return new WhileStmt(condition, parseScopeStmt()); 2128 } 2129 2130 /// $(BNF DoWhileStmt := do ScopeStmt while "(" Expression ")") 2131 Statement parseDoWhileStmt() 2132 { 2133 skip!"do"; 2134 auto doBody = parseScopeStmt(); 2135 require!"while"; 2136 auto paren = requireOpening!"("; 2137 auto condition = parseExpression(); 2138 requireClosing!")"(paren); 2139 version(D2) 2140 require2!";"; 2141 return new DoWhileStmt(condition, doBody); 2142 } 2143 2144 /// $(BNF ForStmt := 2145 //// for "(" (NoScopeStmt | ";") Expression? ";" Expression? ")" 2146 //// ScopeStmt) 2147 Statement parseForStmt() 2148 { 2149 skip!"for"; 2150 auto paren = requireOpening!"("; 2151 auto init = !consumed!";" ? parseNoScopeStmt() : null; 2152 auto condition = !tokenIs!";" ? parseExpression() : null; 2153 require2!";"; 2154 auto increment = !tokenIs!")" ? parseExpression() : null; 2155 requireClosing!")"(paren); 2156 auto forBody = parseScopeStmt(); 2157 return new ForStmt(init, condition, increment, forBody); 2158 } 2159 2160 /// $(BNF ForeachStmt := 2161 //// Foreach "(" ForeachVarList ";" Aggregate ")" 2162 //// ScopeStmt 2163 ////Foreach := foreach | foreach_reverse 2164 ////ForeachVarList := ForeachVar ("," ForeachVar)* 2165 ////ForeachVar := ref? (Identifier | Declarator) 2166 ////RangeExpr2 := Expression ".." Expression # D2 2167 ////Aggregate := RangeExpr2 | Expression) 2168 Statement parseForeachStmt() 2169 { 2170 assert(token.kind.Any!("foreach", "foreach_reverse")); 2171 auto kind = consume().kind; 2172 auto params = new Parameters; 2173 auto paren = requireOpening!"("; 2174 auto paramsBegin = token; 2175 do 2176 { 2177 auto paramBegin = token; 2178 StorageClass stcs, stc; 2179 Type type; 2180 Token* name, stctok; 2181 2182 Lswitch: 2183 switch (token.kind) 2184 { 2185 version(D2) 2186 { 2187 case T!"const", T!"immutable", T!"inout", T!"shared": 2188 if ((stc = getSTC()) == 0) 2189 goto default; 2190 goto Lcommon; 2191 case T!"ref": 2192 stc = StorageClass.Ref; 2193 Lcommon: 2194 if (stcs & stc) 2195 error2(MID.RedundantStorageClass, token); 2196 stcs |= stc; 2197 stctok = token; 2198 nT(); 2199 goto Lswitch; 2200 } 2201 version(D1) 2202 { 2203 case T!"inout", T!"ref": 2204 stcs = StorageClass.Ref; 2205 stctok = token; 2206 nT(); 2207 goto case T!"Identifier"; 2208 } 2209 case T!"Identifier": 2210 if (peekNext().Any!(",", ";", ")")) 2211 { // (ref|const|...)? Identifier 2212 name = requireIdentifier(MID.ExpectedVariableName); 2213 break; 2214 } 2215 goto default; 2216 default: // (ref|const|...)? Declarator 2217 type = parseDeclarator(name); 2218 } 2219 2220 params ~= set(new Parameter(stcs, stctok, type, name, null), paramBegin); 2221 } while (consumed!","); 2222 set(params, paramsBegin); 2223 2224 require2!";"; 2225 auto e = parseExpression(); 2226 2227 version(D2) 2228 if (auto op = consumedToken!"..") // Expression ".." Expression 2229 e = set(new RangeExpr(e, parseExpression(), op), e.begin); 2230 2231 requireClosing!")"(paren); 2232 auto forBody = parseScopeStmt(); 2233 return new ForeachStmt(kind, params, e, forBody); 2234 } 2235 2236 /// $(BNF SwitchStmt := final? switch "(" Expression ")" ScopeStmt) 2237 Statement parseSwitchStmt() 2238 { 2239 bool isFinal = consumed!"final"; 2240 skip!"switch"; 2241 auto paren = requireOpening!"("; 2242 auto condition = parseExpression(); 2243 requireClosing!")"(paren); 2244 auto switchBody = parseScopeStmt(); 2245 return new SwitchStmt(condition, switchBody, isFinal); 2246 } 2247 2248 /// Helper function for parsing the body of a default or case statement. 2249 /// $(BNF CaseOrDefaultBody := ScopeStmt*) 2250 Statement parseCaseOrDefaultBody() 2251 { 2252 // This function is similar to parseNoScopeStmt() 2253 auto begin = token; 2254 auto s = new CompoundStmt(); 2255 while (!token.kind.Any!("case", "default", "}", "EOF")) 2256 s ~= parseStatement(); 2257 if (begin is token) // Nothing consumed. 2258 begin = this.prevToken; 2259 set(s, begin); 2260 return set(new ScopeStmt(s), begin); 2261 } 2262 2263 /// $(BNF CaseStmt := case ExpressionList ":" CaseOrDefaultBody | 2264 //// case AssignExpr ":" ".." case AssignExpr ":" CaseOrDefaultBody) 2265 Statement parseCaseStmt() 2266 { 2267 skip!"case"; 2268 auto values = parseExpressionList(); 2269 require2!":"; 2270 version(D2) 2271 if (consumed!"..") 2272 { 2273 if (values.length > 1) 2274 error(values[1].begin, MID.CaseRangeStartExpression); 2275 require!"case"; 2276 Expression left = values[0], right = parseAssignExpr(); 2277 require2!":"; 2278 auto caseBody = parseCaseOrDefaultBody(); 2279 return new CaseRangeStmt(left, right, caseBody); 2280 } // version(D2) 2281 auto caseBody = parseCaseOrDefaultBody(); 2282 return new CaseStmt(values, caseBody); 2283 } 2284 2285 /// $(BNF DefaultStmt := default ":" CaseOrDefaultBody) 2286 Statement parseDefaultStmt() 2287 { 2288 skip!"default"; 2289 require2!":"; 2290 auto defaultBody = parseCaseOrDefaultBody(); 2291 return new DefaultStmt(defaultBody); 2292 } 2293 2294 /// $(BNF ContinueStmt := continue Identifier? ";") 2295 Statement parseContinueStmt() 2296 { 2297 skip!"continue"; 2298 auto ident = optionalIdentifier(); 2299 require2!";"; 2300 return new ContinueStmt(ident); 2301 } 2302 2303 /// $(BNF BreakStmt := break Identifier? ";") 2304 Statement parseBreakStmt() 2305 { 2306 skip!"break"; 2307 auto ident = optionalIdentifier(); 2308 require2!";"; 2309 return new BreakStmt(ident); 2310 } 2311 2312 /// $(BNF ReturnStmt := return Expression? ";") 2313 Statement parseReturnStmt() 2314 { 2315 skip!"return"; 2316 auto expr = !tokenIs!";" ? parseExpression() : null; 2317 require2!";"; 2318 return new ReturnStmt(expr); 2319 } 2320 2321 /// $(BNF 2322 ////GotoStmt := goto (case Expression? | default | Identifier) ";") 2323 Statement parseGotoStmt() 2324 { 2325 skip!"goto"; 2326 auto ident = token; 2327 Expression caseExpr; 2328 if (consumed!"case") 2329 { 2330 if (!tokenIs!";") 2331 caseExpr = parseExpression(); 2332 } 2333 else if (!consumed!"default") 2334 ident = requireIdentifier(MID.ExpectedAnIdentifier); 2335 require2!";"; 2336 return new GotoStmt(ident, caseExpr); 2337 } 2338 2339 /// $(BNF WithStmt := with "(" Expression ")" ScopeStmt) 2340 Statement parseWithStmt() 2341 { 2342 skip!"with"; 2343 auto paren = requireOpening!"("; 2344 auto expr = parseExpression(); 2345 requireClosing!")"(paren); 2346 return new WithStmt(expr, parseScopeStmt()); 2347 } 2348 2349 /// $(BNF SynchronizedStmt := synchronized ("(" Expression ")")? ScopeStmt) 2350 Statement parseSynchronizedStmt() 2351 { 2352 skip!"synchronized"; 2353 Expression expr; 2354 if (auto paren = consumedToken!"(") 2355 { 2356 expr = parseExpression(); 2357 requireClosing!")"(paren); 2358 } 2359 return new SynchronizedStmt(expr, parseScopeStmt()); 2360 } 2361 2362 /// $(BNF TryStmt := try ScopeStmt CatchStmt* LastCatchStmt? FinallyStmt? 2363 ////CatchStmt := catch "(" BasicType Identifier ")" NoScopeStmt 2364 ////LastCatchStmt := catch NoScopeStmt 2365 ////FinallyStmt := finally NoScopeStmt) 2366 Statement parseTryStmt() 2367 { 2368 auto begin = token; 2369 skip!"try"; 2370 2371 auto tryBody = parseScopeStmt(); 2372 CatchStmt[] catchBodies; 2373 FinallyStmt finBody; 2374 2375 while (consumed!"catch") 2376 { 2377 auto catchBegin = prevToken; 2378 Parameter param; 2379 if (auto paren = consumedToken!"(") 2380 { 2381 auto paramBegin = token; 2382 Token* name; 2383 auto type = parseDeclaratorOptId(name); 2384 param = new Parameter(StorageClass.None, null, type, name, null); 2385 set(param, paramBegin); 2386 requireClosing!")"(paren); 2387 } 2388 catchBodies ~= set(new CatchStmt(param, parseNoScopeStmt()), catchBegin); 2389 if (param is null) 2390 break; // This is a LastCatch 2391 } 2392 2393 if (auto t = consumedToken!"finally") 2394 finBody = set(new FinallyStmt(parseNoScopeStmt()), t); 2395 2396 if (catchBodies is null && finBody is null) 2397 error(begin, MID.MissingCatchOrFinally); 2398 2399 return new TryStmt(tryBody, catchBodies, finBody); 2400 } 2401 2402 /// $(BNF ThrowStmt := throw Expression ";") 2403 Statement parseThrowStmt() 2404 { 2405 skip!"throw"; 2406 auto expr = parseExpression(); 2407 require2!";"; 2408 return new ThrowStmt(expr); 2409 } 2410 2411 /// $(BNF ScopeGuardStmt := scope "(" ScopeCondition ")" ScopeGuardBody 2412 ////ScopeCondition := "exit" | "success" | "failure" 2413 ////ScopeGuardBody := ScopeStmt | NoScopeStmt) 2414 Statement parseScopeGuardStmt() 2415 { 2416 skip!"scope"; 2417 assert(tokenIs!"("); 2418 auto paren = consume(); 2419 auto condition = requireIdentifier(MID.ExpectedScopeIdentifier); 2420 if (condition && 2421 !condition.ident.In(Ident.exit, Ident.success, Ident.failure)) 2422 error2(MID.InvalidScopeIdentifier, condition); 2423 requireClosing!")"(paren); 2424 auto scopeBody = tokenIs!"{" ? parseScopeStmt() : parseNoScopeStmt(); 2425 return new ScopeGuardStmt(condition, scopeBody); 2426 } 2427 2428 /// $(BNF VolatileStmt := volatile (ScopeStmt | NoScopeStmt)) 2429 Statement parseVolatileStmt() 2430 { 2431 skip!"volatile"; 2432 auto volatileBody = tokenIs!"{" ? parseScopeStmt() : parseNoScopeStmt(); 2433 return new VolatileStmt(volatileBody); 2434 } 2435 2436 /// $(BNF PragmaStmt := 2437 //// pragma "(" Identifier ("," ExpressionList)? ")" NoScopeStmt) 2438 Statement parsePragmaStmt() 2439 { 2440 skip!"pragma"; 2441 auto paren = requireOpening!"("; 2442 auto name = requireIdentifier(MID.ExpectedPragmaIdentifier); 2443 auto args = consumed!"," ? parseExpressionList() : null; 2444 requireClosing!")"(paren); 2445 auto pragmaBody = parseNoScopeOrEmptyStmt(); 2446 return new PragmaStmt(name, args, pragmaBody); 2447 } 2448 2449 /// $(BNF StaticIfStmt := 2450 //// static if "(" Expression ")" NoScopeStmt (else NoScopeStmt)?) 2451 Statement parseStaticIfStmt() 2452 { 2453 skip!"static"; 2454 skip!"if"; 2455 auto paren = requireOpening!"("; 2456 auto condition = parseExpression(); 2457 requireClosing!")"(paren); 2458 auto ifBody = parseNoScopeStmt(); 2459 auto elseBody = consumed!"else" ? parseNoScopeStmt() : null; 2460 return new StaticIfStmt(condition, ifBody, elseBody); 2461 } 2462 2463 /// $(BNF StaticAssertStmt := 2464 //// static assert "(" AssignExpr ("," Message)? ")" ";" 2465 ////Message := AssignExpr) 2466 Statement parseStaticAssertStmt() 2467 { 2468 skip!"static"; 2469 skip!"assert"; 2470 auto paren = requireOpening!"("; 2471 auto condition = parseAssignExpr(); 2472 auto message = consumed!"," ? parseAssignExpr() : null; 2473 requireClosing!")"(paren); 2474 require2!";"; 2475 return new StaticAssertStmt(condition, message); 2476 } 2477 2478 /// $(BNF DebugStmt := 2479 //// debug DebugCondition? NoScopeStmt (else NoScopeStmt)?) 2480 Statement parseDebugStmt() 2481 { 2482 skip!"debug"; 2483 Token* cond; 2484 if (auto paren = consumedToken!"(") 2485 { // ( Condition ) 2486 cond = parseIdentOrInt(); 2487 requireClosing!")"(paren); 2488 } 2489 auto debugBody = parseNoScopeStmt(); 2490 auto elseBody = consumed!"else" ? parseNoScopeStmt() : null; 2491 return new DebugStmt(cond, debugBody, elseBody); 2492 } 2493 2494 /// $(BNF VersionStmt := 2495 //// version VCondition NoScopeStmt (else NoScopeStmt)?) 2496 Statement parseVersionStmt() 2497 { 2498 skip!"version"; 2499 auto paren = requireOpening!"("; 2500 auto cond = parseVersionCondition(); 2501 requireClosing!")"(paren); 2502 auto versionBody = parseNoScopeStmt(); 2503 auto elseBody = consumed!"else" ? parseNoScopeStmt() : null; 2504 return new VersionStmt(cond, versionBody, elseBody); 2505 } 2506 2507 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2508 | Assembler parsing methods | 2509 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ 2510 2511 /// Parses an AsmBlockStmt. 2512 /// $(BNF AsmBlockStmt := asm "{" AsmStmt* "}") 2513 Statement parseAsmBlockStmt() 2514 { 2515 skip!"asm"; 2516 auto brace = requireOpening!"{"; 2517 auto ss = new CompoundStmt; 2518 while (!token.kind.Any!("}", "EOF")) 2519 ss ~= parseAsmStmt(); 2520 requireClosing!"}"(brace); 2521 return new AsmBlockStmt(set(ss, brace)); 2522 } 2523 2524 /// $(BNF 2525 ////AsmStmt := 2526 //// OpcodeStmt | LabeledStmt | AsmAlignStmt | EmptyStmt 2527 ////OpcodeStmt := Opcode Operands? ";" 2528 ////Opcode := Identifier 2529 ////Operands := AsmExpr ("," AsmExpr)* 2530 ////LabeledStmt := Identifier ":" AsmStmt 2531 ////AsmAlignStmt := align Integer ";" 2532 ////EmptyStmt := ";") 2533 Statement parseAsmStmt() 2534 { 2535 auto begin = token; 2536 Statement s; 2537 alias ident = begin; 2538 switch (token.kind) 2539 { 2540 case T!"in", T!"int", T!"out": // Keywords that are valid opcodes. 2541 nT(); 2542 goto LparseOperands; 2543 case T!"Identifier": 2544 nT(); 2545 if (consumed!":") 2546 { // Identifier ":" AsmStmt 2547 s = new LabeledStmt(ident, parseAsmStmt()); 2548 break; 2549 } 2550 2551 // JumpOpcode (short | (near | far) ptr)? 2552 if (Ident.isJumpOpcode(ident.ident.idKind)) 2553 if (tokenIs!"short") 2554 nT(); 2555 else if (tokenIs!"Identifier" && token.ident.In(Ident.near, Ident.far)) 2556 { 2557 nT(); 2558 if (tokenIs!"Identifier" && token.ident is Ident.ptr) 2559 skip!"Identifier"; 2560 else 2561 error2(MID.ExpectedButFound, "ptr", token); 2562 } 2563 2564 // TODO: Handle opcodes db, ds, di, dl, df, dd, de. 2565 // They accept string operands. 2566 2567 LparseOperands: 2568 // Opcode Operands? ";" 2569 Expression[] es; 2570 if (!tokenIs!";") 2571 do 2572 es ~= parseAsmExpr(); 2573 while (consumed!","); 2574 require2!";"; 2575 s = new AsmStmt(ident, es); 2576 break; 2577 case T!"align": 2578 // align Integer ";" 2579 nT(); 2580 auto number = token; 2581 if (!consumed!"Int32") 2582 error2(MID.ExpectedIntegerAfterAlign, token); 2583 require2!";"; 2584 s = new AsmAlignStmt(number); 2585 break; 2586 case T!";": 2587 s = new EmptyStmt(); 2588 nT(); 2589 break; 2590 default: 2591 s = new IllegalAsmStmt(); 2592 // Skip to next valid token. 2593 do 2594 nT(); 2595 while (!token.isAsmStatementStart() && !token.kind.Any!("}", "EOF")); 2596 auto text = begin.textSpan(this.prevToken); 2597 error(begin, MID.IllegalAsmStatement, text); 2598 } 2599 set(s, begin); 2600 return s; 2601 } 2602 2603 /// $(BNF AsmExpr := AsmCondExpr 2604 ////AsmCondExpr := AsmBinaryExpr ("?" AsmExpr ":" AsmExpr)?) 2605 Expression parseAsmExpr() 2606 { 2607 auto begin = token; 2608 auto e = parseAsmBinaryExpr(); 2609 if (auto qtok = consumedToken!"?") 2610 { 2611 auto iftrue = parseAsmExpr(); 2612 auto ctok = token; // ":" 2613 require!":"; 2614 auto iffalse = parseAsmExpr(); 2615 e = new CondExpr(e, iftrue, iffalse, qtok, ctok); 2616 set(e, begin); 2617 } 2618 // TODO: create AsmExpr that contains e? 2619 return e; 2620 } 2621 2622 /// $(BNF AsmBinaryExpr := AsmOrOrExpr 2623 ////AsmOrOrExpr := AsmAndAndExpr ("||" AsmAndAndExpr)* 2624 ////AsmAndAndExpr := AsmOrExpr ("&&" AsmOrExpr)* 2625 ////AsmOrExpr := AsmXorExpr ("|" AsmXorExpr)* 2626 ////AsmXorExpr := AsmAndExpr ("^" AsmAndExpr)* 2627 ////AsmAndExpr := AsmCmpExpr ("&" AsmCmpExpr)* 2628 ////AsmCmpExpr := AsmShiftExpr (AsmCmpOp AsmShiftExpr)* 2629 ////AsmCmpOp := "==" | "!=" | "<" | "<=" | ">" | ">=" 2630 ////AsmShiftExpr := AsmAddExpr (AsmShiftOp AsmAddExpr)* 2631 ////AsmShiftOp := "<<" | ">>" | ">>>" 2632 ////AsmAddExpr := AsmMulExpr (AsmAddOp AsmMulExpr)* 2633 ////AsmAddOp := "+" | "-" 2634 ////AsmMulExpr := AsmPostExpr (AsmMulOp AsmPostExpr)* 2635 ////AsmMulOp := "*" | "/" | "%" 2636 ////) 2637 /// Params: 2638 /// prevPrec = The precedence of the previous operator. 2639 Expression parseAsmBinaryExpr(PREC prevPrec = PREC.None) 2640 { 2641 auto begin = token; 2642 auto e = parseAsmPostExpr(); // Parse the left-hand side. 2643 2644 NewBinaryExpr makeBinaryExpr = void; 2645 while (1) 2646 { 2647 auto operator = token; 2648 auto opPrec = parseBinaryOp(makeBinaryExpr, prevPrec); 2649 if (opPrec <= prevPrec) // Continue as long as the operators 2650 break; // have higher precedence. 2651 if (prevToken.kind.Any!(/*"!", */"is", "in", "!<>=", "!<>", "!<=", "!<", 2652 "!>=", "!>", "<>=", "<>", "~", "^^")) 2653 // Use textSpan() for operators like "!is" and "!in". 2654 error(operator, MID.IllegalAsmBinaryOp, operator.textSpan(prevToken)); 2655 auto rhs = parseAsmBinaryExpr(opPrec); // Parse the right-hand side. 2656 e = makeBinaryExpr(e, rhs, operator); 2657 set(e, begin); 2658 } 2659 return e; 2660 } 2661 2662 /// $(BNF AsmPostExpr := AsmUnaryExpr ("[" AsmExpr "]")*) 2663 Expression parseAsmPostExpr() 2664 { 2665 Token* begin = token, bracket = void; 2666 auto e = parseAsmUnaryExpr(); 2667 while ((bracket = consumedToken!"[") !is null) 2668 { 2669 e = new AsmPostBracketExpr(e, parseAsmExpr()); 2670 requireClosing!"]"(bracket); 2671 set(e, begin); 2672 } 2673 return e; 2674 } 2675 2676 /// $(BNF 2677 ////AsmUnaryExpr := 2678 //// AsmPrimaryExpr | AsmTypeExpr | AsmOffsetExpr | AsmSegExpr | 2679 //// SignExpr | NotExpr | ComplementExpr 2680 ////AsmTypeExpr := TypePrefix "ptr" AsmExpr 2681 ////TypePrefix := "byte" | "shor" | "int" | "float" | "double" | "real" 2682 //// "near" | "far" | "word" | "dword" | "qword" 2683 ////AsmOffsetExpr := "offset" AsmExpr 2684 ////AsmSegExpr := "seg" AsmExpr 2685 ////SignExpr := ("+" | "-") AsmUnaryExpr 2686 ////NotExpr := "!" AsmUnaryExpr 2687 ////ComplementExpr := "~" AsmUnaryExpr 2688 ////) 2689 Expression parseAsmUnaryExpr() 2690 { 2691 auto begin = token; 2692 Expression e; 2693 switch (token.kind) 2694 { 2695 case T!"byte", T!"short", T!"int", T!"float", T!"double", T!"real": 2696 goto LAsmTypePrefix; 2697 case T!"Identifier": 2698 switch (token.ident.idKind) 2699 { 2700 case IDK.near, IDK.far,/* "byte", "short", "int",*/ 2701 IDK.word, IDK.dword, IDK.qword/*, "float", "double", "real"*/: 2702 LAsmTypePrefix: 2703 nT(); 2704 if (tokenIs!"Identifier" && token.ident is Ident.ptr) 2705 skip!"Identifier"; 2706 else 2707 error2(MID.ExpectedButFound, "ptr", token); 2708 e = new AsmTypeExpr(begin, parseAsmExpr()); 2709 break; 2710 case IDK.offsetof: 2711 nT(); 2712 e = new AsmOffsetExpr(parseAsmExpr()); 2713 break; 2714 case IDK.seg: 2715 nT(); 2716 e = new AsmSegExpr(parseAsmExpr()); 2717 break; 2718 default: 2719 goto LparseAsmPrimaryExpr; 2720 } 2721 break; 2722 case T!"-", T!"+": 2723 nT(); 2724 e = new SignExpr(parseAsmUnaryExpr()); 2725 break; 2726 case T!"!": 2727 nT(); 2728 e = new NotExpr(parseAsmUnaryExpr()); 2729 break; 2730 case T!"~": 2731 nT(); 2732 e = new CompExpr(parseAsmUnaryExpr()); 2733 break; 2734 default: 2735 LparseAsmPrimaryExpr: 2736 e = parseAsmPrimaryExpr(); 2737 return e; 2738 } 2739 set(e, begin); 2740 return e; 2741 } 2742 2743 /// $(BNF AsmPrimaryExpr := 2744 //// IntExpr | FloatExpr | DollarExpr | 2745 //// AsmBracketExpr |AsmLocalSizeExpr | AsmRegisterExpr | 2746 //// IdentifiersExpr 2747 ////IntExpr := IntegerLiteral 2748 ////FloatExpr := FloatLiteral 2749 ////DollarExpr := "$" 2750 ////AsmBracketExpr := "[" AsmExpr "]" 2751 ////AsmLocalSizeExpr := "__LOCAL_SIZE" 2752 ////AsmRegisterExpr := ...) 2753 Expression parseAsmPrimaryExpr() 2754 { 2755 auto begin = token; 2756 Expression e; 2757 switch (token.kind) 2758 { 2759 case T!"Int32", T!"Int64", T!"UInt32", T!"UInt64": 2760 e = new IntExpr(token); 2761 nT(); 2762 break; 2763 case T!"Float32", T!"Float64", T!"Float80", 2764 T!"IFloat32", T!"IFloat64", T!"IFloat80": 2765 e = new FloatExpr(token); 2766 nT(); 2767 break; 2768 case T!"$": 2769 e = new DollarExpr(); 2770 nT(); 2771 break; 2772 case T!"[": 2773 // [ AsmExpr ] 2774 auto bracket = consume(); 2775 e = parseAsmExpr(); 2776 requireClosing!"]"(bracket); 2777 e = new AsmBracketExpr(e); 2778 break; 2779 case T!"Identifier": 2780 auto register = token; 2781 switch (register.ident.idKind) 2782 { 2783 // __LOCAL_SIZE 2784 case IDK.__LOCAL_SIZE: 2785 nT(); 2786 e = new AsmLocalSizeExpr(); 2787 break; 2788 // Register 2789 case IDK.ST: 2790 nT(); 2791 Expression number; // (1) - (7) 2792 if (auto paren = consumedToken!"(") 2793 (number = parseAsmExpr()), 2794 requireClosing!")"(paren); 2795 e = new AsmRegisterExpr(register, number); 2796 break; 2797 case IDK.ES, IDK.CS, IDK.SS, IDK.DS, IDK.GS, IDK.FS: 2798 nT(); // Segment := XX (":" AsmExpr)? 2799 auto number = consumed!":" ? parseAsmExpr() : null; 2800 e = new AsmRegisterExpr(register, number); 2801 break; 2802 case IDK.AL, IDK.AH, IDK.AX, IDK.EAX, 2803 IDK.BL, IDK.BH, IDK.BX, IDK.EBX, 2804 IDK.CL, IDK.CH, IDK.CX, IDK.ECX, 2805 IDK.DL, IDK.DH, IDK.DX, IDK.EDX, 2806 IDK.BP, IDK.EBP, IDK.SP, IDK.ESP, 2807 IDK.DI, IDK.EDI, IDK.SI, IDK.ESI, 2808 IDK.CR0, IDK.CR2, IDK.CR3, IDK.CR4, 2809 IDK.DR0, IDK.DR1, IDK.DR2, IDK.DR3, IDK.DR6, IDK.DR7, 2810 IDK.TR3, IDK.TR4, IDK.TR5, IDK.TR6, IDK.TR7, 2811 IDK.MM0, IDK.MM1, IDK.MM2, IDK.MM3, 2812 IDK.MM4, IDK.MM5, IDK.MM6, IDK.MM7, 2813 IDK.XMM0, IDK.XMM1, IDK.XMM2, IDK.XMM3, 2814 IDK.XMM4, IDK.XMM5, IDK.XMM6, IDK.XMM7: 2815 nT(); 2816 e = new AsmRegisterExpr(register); 2817 break; 2818 default: 2819 e = parseIdentifiersExpr(); 2820 } // end of switch 2821 break; 2822 case T!".": 2823 e = parseIdentifiersExpr(); 2824 break; 2825 default: 2826 error2(MID.ExpectedButFound, "Expression", token); 2827 nT(); 2828 e = new IllegalExpr(); 2829 } 2830 set(e, begin); 2831 return e; 2832 } 2833 2834 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2835 | Expression parsing methods | 2836 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ 2837 2838 2839 /// Instantiates a function that returns a new binary expression. 2840 static Expression newBinaryExpr(E)(Expression l, Expression r, Token* op) 2841 { 2842 return new E(l, r, op); 2843 } 2844 /// The function signature of newBinaryExpr. 2845 alias NewBinaryExpr = Expression function(Expression, Expression, Token*); 2846 2847 /// The root method for parsing an Expression. 2848 /// $(BNF Expression := CommaExpr 2849 ////CommaExpr := AssignExpr ("," AssignExpr)*) 2850 Expression parseExpression() 2851 { 2852 Token* begin = token, comma = void; 2853 auto e = parseAssignExpr(); 2854 while ((comma = consumedToken!",") !is null) 2855 e = set(new CommaExpr(e, parseAssignExpr(), comma), begin); 2856 return e; 2857 } 2858 2859 /// $(BNF AssignExpr := CondExpr (AssignOp AssignExpr)* 2860 ////AssignOp := "=" | "<<=" | ">>=" | ">>>=" | "|=" | "&=" | 2861 //// "+=" | "-=" | "/=" | "*=" | "%=" | "^=" | "~=" | "^^=") 2862 Expression parseAssignExpr() 2863 { 2864 auto begin = token; 2865 auto e = parseCondExpr(); 2866 auto optok = token; 2867 NewBinaryExpr f = void; 2868 switch (optok.kind) 2869 { 2870 case T!"=": f = &newBinaryExpr!(AssignExpr); goto Lcommon; 2871 case T!"<<=": f = &newBinaryExpr!(LShiftAssignExpr); goto Lcommon; 2872 case T!">>=": f = &newBinaryExpr!(RShiftAssignExpr); goto Lcommon; 2873 case T!">>>=": f = &newBinaryExpr!(URShiftAssignExpr); goto Lcommon; 2874 case T!"|=": f = &newBinaryExpr!(OrAssignExpr); goto Lcommon; 2875 case T!"&=": f = &newBinaryExpr!(AndAssignExpr); goto Lcommon; 2876 case T!"+=": f = &newBinaryExpr!(PlusAssignExpr); goto Lcommon; 2877 case T!"-=": f = &newBinaryExpr!(MinusAssignExpr); goto Lcommon; 2878 case T!"/=": f = &newBinaryExpr!(DivAssignExpr); goto Lcommon; 2879 case T!"*=": f = &newBinaryExpr!(MulAssignExpr); goto Lcommon; 2880 case T!"%=": f = &newBinaryExpr!(ModAssignExpr); goto Lcommon; 2881 case T!"^=": f = &newBinaryExpr!(XorAssignExpr); goto Lcommon; 2882 case T!"~=": f = &newBinaryExpr!(CatAssignExpr); goto Lcommon; 2883 version(D2) 2884 { 2885 case T!"^^=": f = &newBinaryExpr!(PowAssignExpr); goto Lcommon; 2886 } 2887 Lcommon: 2888 nT(); 2889 // Parse the right-hand side and create the expression. 2890 e = f(e, parseAssignExpr(), optok); 2891 set(e, begin); 2892 break; 2893 default: 2894 } 2895 return e; 2896 } 2897 2898 /// $(BNF CondExpr := BinaryExpr ("?" Expression ":" CondExpr)?) 2899 Expression parseCondExpr() 2900 { 2901 auto begin = token; 2902 auto e = parseBinaryExpr(); 2903 if (auto qtok = consumedToken!"?") 2904 { 2905 auto iftrue = parseExpression(); 2906 auto ctok = token; // ":" 2907 require!":"; 2908 auto iffalse = parseCondExpr(); 2909 e = new CondExpr(e, iftrue, iffalse, qtok, ctok); 2910 set(e, begin); 2911 } 2912 return e; 2913 } 2914 2915 /// Enumeration of binary operator precedence values. 2916 enum PREC 2917 { 2918 None, /// No precedence. 2919 OOr, /// || 2920 AAnd, /// && 2921 Or, /// | 2922 Xor, /// ^ 2923 And, /// & 2924 Cmp, /// in !in is !is == != < > <= >= etc. 2925 Shift, /// << >> >>> 2926 Plus, /// + - ~ 2927 Mul, /// * / % 2928 Pow, /// ^^ 2929 } 2930 2931 /// Consumes the tokens of a binary operator. 2932 /// Params: 2933 /// fn = Receives a function that creates the binary Expression. 2934 /// prevPrec = The precedence value of the previous operator. 2935 /// Returns: The precedence value of the binary operator. 2936 /// The higher the value the stronger the operator binds. 2937 PREC parseBinaryOp(out NewBinaryExpr fn, PREC prevPrec) 2938 { 2939 PREC p; 2940 NewBinaryExpr f; 2941 switch (token.kind) 2942 { 2943 case T!"!": 2944 auto next = peekNext(); 2945 if (next == T!"is") // "!" is 2946 goto case T!"is"; 2947 else version(D2) if (next == T!"in") // "!" in 2948 goto case T!"in"; 2949 break; // Not a binary operator. 2950 case T!"||": p = PREC.OOr; f = &newBinaryExpr!(OrOrExpr); break; 2951 case T!"&&": p = PREC.AAnd; f = &newBinaryExpr!(AndAndExpr); break; 2952 case T!"|": p = PREC.Or; f = &newBinaryExpr!(OrExpr); break; 2953 case T!"^": p = PREC.Xor; f = &newBinaryExpr!(XorExpr); break; 2954 case T!"&": p = PREC.And; f = &newBinaryExpr!(AndExpr); break; 2955 case T!"is": p = PREC.Cmp; f = &newBinaryExpr!(IdentityExpr); break; 2956 case T!"in": p = PREC.Cmp; f = &newBinaryExpr!(InExpr); break; 2957 case T!"!=", 2958 T!"==": p = PREC.Cmp; f = &newBinaryExpr!(EqualExpr); break; 2959 case T!"<=", T!"<", T!">=", T!">", T!"!<>=", T!"!<>", T!"!<=", T!"!<", 2960 T!"!>=", T!"!>", T!"<>=", T!"<>": 2961 p = PREC.Cmp; f = &newBinaryExpr!(RelExpr); break; 2962 case T!"<<": p = PREC.Shift; f = &newBinaryExpr!(LShiftExpr); break; 2963 case T!">>": p = PREC.Shift; f = &newBinaryExpr!(RShiftExpr); break; 2964 case T!">>>": p = PREC.Shift; f = &newBinaryExpr!(URShiftExpr); break; 2965 case T!"+": p = PREC.Plus; f = &newBinaryExpr!(PlusExpr); break; 2966 case T!"-": p = PREC.Plus; f = &newBinaryExpr!(MinusExpr); break; 2967 case T!"~": p = PREC.Plus; f = &newBinaryExpr!(CatExpr); break; 2968 case T!"*": p = PREC.Mul; f = &newBinaryExpr!(MulExpr); break; 2969 case T!"/": p = PREC.Mul; f = &newBinaryExpr!(DivExpr); break; 2970 case T!"%": p = PREC.Mul; f = &newBinaryExpr!(ModExpr); break; 2971 version(D2) 2972 { 2973 case T!"^^": p = PREC.Pow; f = &newBinaryExpr!(PowExpr); break; 2974 } 2975 default: 2976 } 2977 if (p == prevPrec && p == PREC.Cmp) 2978 error(token, MID.CannotChainComparisonOps); // E.g.: a == b == c 2979 // Consume if we have a binary operator 2980 // and the precedence is greater than prevPrec. 2981 if (p > prevPrec) 2982 { 2983 assert(f !is null && p != PREC.None); 2984 fn = f; 2985 if (tokenIs!"!") 2986 nT(); // Consume "!" part. 2987 nT(); // Consume the binary operator. 2988 } 2989 return p; 2990 } 2991 2992 /// Parses a binary operator expression. 2993 /// 2994 /// $(BNF BinaryExpr := OrOrExpr 2995 ////OrOrExpr := AndAndExpr ("||" AndAndExpr)* 2996 ////AndAndExpr := OrExpr ("&&" OrExpr)* 2997 ////OrExpr := XorExpr ("|" XorExpr)* 2998 ////XorExpr := AndExpr ("^" AndExpr)* 2999 ////AndExpr := CmpExpr ("&" CmpExpr)* 3000 ////CmpExpr := ShiftExpr (CmpOp ShiftExpr)? 3001 ////CmpOp := "is" | "!" "is" | "in" | "==" | "!=" | "<" | "<=" | ">" | 3002 //// ">=" | "!<>=" | "!<>" | "!<=" | "!<" | 3003 //// "!>=" | "!>" | "<>=" | "<>" 3004 ////ShiftExpr := AddExpr (ShiftOp AddExpr)* 3005 ////ShiftOp := "<<" | ">>" | ">>>" 3006 ////AddExpr := MulExpr (AddOp MulExpr)* 3007 ////AddOp := "+" | "-" | "~" 3008 ////MulExpr := PostExpr (MulOp PostExpr)* 3009 ////MulExpr2 := PowExpr (MulOp PowExpr)* # D2 3010 ////MulOp := "*" | "/" | "%" 3011 ////PowExpr := PostExpr ("^^" PostExpr)* # D2 3012 ////) 3013 /// Params: 3014 /// prevPrec = The precedence of the previous operator. 3015 /// Note: Uses the "precedence climbing" method as described here: 3016 /// $(LINK http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm#climbing) 3017 Expression parseBinaryExpr(PREC prevPrec = PREC.None) 3018 { 3019 auto begin = token; 3020 auto e = parsePostExpr(); // Parse the left-hand side. 3021 3022 NewBinaryExpr makeBinaryExpr = void; 3023 while (1) 3024 { 3025 auto operator = token; 3026 auto opPrec = parseBinaryOp(makeBinaryExpr, prevPrec); 3027 if (opPrec <= prevPrec) // Continue as long as the operators 3028 break; // have higher precedence. 3029 auto rhs = parseBinaryExpr(opPrec); // Parse the right-hand side. 3030 e = makeBinaryExpr(e, rhs, operator); 3031 set(e, begin); 3032 } 3033 return e; 3034 } 3035 3036 /// $(BNF PostExpr := UnaryExpr 3037 //// (PostIdExpr | IncOrDecExpr | CallExpr | SliceExpr | IndexExpr)* 3038 ////PostIdExpr := "." (NewExpr | IdentifierExpr) 3039 ////IncOrDecExpr := ("++" | "--") 3040 ////CallExpr := "(" Arguments? ")" 3041 ////RangeExpr := AssignExpr ".." AssignExpr 3042 ////SliceExpr := "[" RangeExpr? "]") 3043 ////IndexExpr := "[" ExpressionList "]") 3044 Expression parsePostExpr() 3045 { 3046 auto begin = token; 3047 auto e = parseUnaryExpr(); 3048 while (1) 3049 { 3050 switch (token.kind) 3051 { 3052 case T!".": 3053 nT(); 3054 e = tokenIs!"new" ? parseNewExpr(e) : parseIdentifierExpr(e); 3055 continue; 3056 case T!"++": 3057 e = new PostIncrExpr(e); 3058 break; 3059 case T!"--": 3060 e = new PostDecrExpr(e); 3061 break; 3062 case T!"(": 3063 e = new CallExpr(e, parseArguments()); 3064 goto Lset; 3065 case T!"[": 3066 auto bracket = token; 3067 nT(); 3068 // "[" "]" is the empty SliceExpr 3069 if (tokenIs!"]") 3070 { 3071 e = new SliceExpr(e, null); 3072 break; 3073 } 3074 auto e2 = parseAssignExpr(); 3075 // "[" AssignExpr ".." AssignExpr "]" 3076 if (auto op = consumedToken!"..") 3077 { 3078 auto r = set(new RangeExpr(e2, parseAssignExpr(), op), e2.begin); 3079 e = new SliceExpr(e, r); 3080 } 3081 else 3082 { // "[" ExpressionList "]" 3083 auto index = [e2]; 3084 if (consumed!",") 3085 index ~= parseExpressionList2(T!"]"); 3086 e = new IndexExpr(e, index); 3087 } 3088 requireClosing!"]"(bracket); 3089 goto Lset; 3090 default: 3091 return e; 3092 } 3093 nT(); 3094 Lset: // Jumped here to skip nT(). 3095 set(e, begin); 3096 } 3097 assert(0); 3098 } 3099 3100 /// $(BNF UnaryExpr := PrimaryExpr | 3101 //// NewExpr | AddressExpr | PreIncrExpr | 3102 //// PreDecrExpr | DerefExpr | SignExpr | 3103 //// NotExpr | CompExpr | DeleteExpr | 3104 //// CastExpr | TypeDotIdExpr 3105 ////AddressExpr := "&" UnaryExpr 3106 ////PreIncrExpr := "++" UnaryExpr 3107 ////PreDecrExpr := "--" UnaryExpr 3108 ////DerefExpr := "*" UnaryExpr 3109 ////SignExpr := ("-" | "+") UnaryExpr 3110 ////NotExpr := "!" UnaryExpr 3111 ////CompExpr := "~" UnaryExpr 3112 ////DeleteExpr := delete UnaryExpr 3113 ////CastExpr := cast "(" Type? ")" UnaryExpr 3114 ////TypeDotIdExpr := "(" Type ")" "." Identifier 3115 ////TypeExpr := Modifier Type) 3116 Expression parseUnaryExpr() 3117 { 3118 auto begin = token; 3119 Expression e; 3120 switch (token.kind) 3121 { 3122 case T!"&": 3123 nT(); 3124 e = new AddressExpr(parseUnaryExpr()); 3125 break; 3126 case T!"++": 3127 nT(); 3128 e = new PreIncrExpr(parseUnaryExpr()); 3129 break; 3130 case T!"--": 3131 nT(); 3132 e = new PreDecrExpr(parseUnaryExpr()); 3133 break; 3134 case T!"*": 3135 nT(); 3136 e = new DerefExpr(parseUnaryExpr()); 3137 break; 3138 case T!"-", 3139 T!"+": 3140 nT(); 3141 e = new SignExpr(parseUnaryExpr()); 3142 break; 3143 case T!"!": 3144 nT(); 3145 e = new NotExpr(parseUnaryExpr()); 3146 break; 3147 case T!"~": 3148 nT(); 3149 e = new CompExpr(parseUnaryExpr()); 3150 break; 3151 case T!"new": 3152 e = parseNewExpr(); 3153 return e; 3154 case T!"delete": 3155 nT(); 3156 e = new DeleteExpr(parseUnaryExpr()); 3157 break; 3158 case T!"cast": 3159 nT(); 3160 auto paren = requireOpening!"("; 3161 Type type; 3162 switch (token.kind) 3163 { 3164 version(D2) 3165 { 3166 case T!")": // Mutable cast: cast "(" ")" 3167 break; 3168 case T!"const", T!"immutable", T!"inout", T!"shared": 3169 if (!nextIs!")") 3170 goto default; // ModParenType 3171 auto mod = consume(); 3172 type = set(new ModifierType(mod), mod); 3173 break; 3174 } // version(D2) 3175 default: 3176 type = parseType(); 3177 } 3178 requireClosing!")"(paren); 3179 e = new CastExpr(parseUnaryExpr(), type); 3180 break; 3181 case T!"(": 3182 if (!tokenAfterParenIs(T!".")) 3183 goto default; 3184 // "(" Type ")" "." Identifier 3185 bool success; 3186 auto type = tryToParse({ 3187 skip!"("; 3188 auto type = parseType(); // Type 3189 require!")"; 3190 require!"."; 3191 return type; 3192 }, success); 3193 if (!success) 3194 goto default; 3195 auto ident = requireIdentifier(MID.ExpectedIdAfterTypeDot); 3196 e = new TypeDotIdExpr(type, ident); 3197 break; 3198 version(D2) 3199 { 3200 case T!"immutable", T!"const", T!"shared", T!"inout": 3201 e = new TypeExpr(parseType()); 3202 break; 3203 } 3204 default: 3205 e = parsePrimaryExpr(); 3206 return e; 3207 } 3208 assert(e !is null); 3209 set(e, begin); 3210 return e; 3211 } 3212 3213 /// $(BNF IdentifiersExpr := 3214 //// ModuleScopeExpr? IdentifierExpr ("." IdentifierExpr)* 3215 ////ModuleScopeExpr := ".") 3216 Expression parseIdentifiersExpr() 3217 { 3218 Expression e; 3219 if (tokenIs!".") 3220 e = set(new ModuleScopeExpr(), token, token); 3221 else 3222 e = parseIdentifierExpr(); 3223 while (consumed!".") 3224 e = parseIdentifierExpr(e); 3225 return e; 3226 } 3227 3228 /// $(BNF IdentifierExpr := Identifier | TemplateInstance 3229 ////TemplateInstance := Identifier "!" TemplateArgumentsOneOrMore) 3230 Expression parseIdentifierExpr(Expression next = null) 3231 { 3232 auto begin = token; 3233 auto ident = requireIdentifier(MID.ExpectedAnIdentifier); 3234 Expression e; 3235 // Peek to avoid parsing: "id !is Exp" or "id !in Exp" 3236 if (tokenIs!"!" && !peekNext().Any!("is", "in")) 3237 { 3238 skip!"!"; 3239 // Identifier "!" "(" TemplateArguments? ")" 3240 // Identifier "!" TemplateArgumentSingle 3241 auto tparams = parseOneOrMoreTemplateArguments(); 3242 e = new TmplInstanceExpr(ident, tparams, next); 3243 } 3244 else // Identifier 3245 e = new IdentifierExpr(ident, next); 3246 return set(e, begin); 3247 } 3248 3249 /// $(BNF LambdaBody := AssignExpr) 3250 Expression parseLambdaExprBody() 3251 { 3252 skip!"=>"; 3253 return parseAssignExpr(); 3254 } 3255 3256 /// $(BNF LambdaExpr := LambdaParams "=>" LambdaBody 3257 ////LambdaParams := Identifier | ParameterList ParamsPostfix) 3258 Expression parseSingleParamLambdaExpr() 3259 { 3260 auto begin = token; 3261 skip!"Identifier"; 3262 auto params = set(new Parameters(), begin); 3263 auto param = new Parameter(StorageClass.None, null, null, begin, null); 3264 params ~= set(param, begin); 3265 auto fstmt = parseLambdaExprBody(); 3266 return set(new LambdaExpr(params, fstmt), begin); 3267 } 3268 3269 /// $(BNF PrimaryExpr := IdentifierExpr | ModuleScopeExpr | 3270 //// LambdaExpr | TypeofExpr | ThisExpr | SuperExpr | 3271 //// NullExpr | BoolExpr | DollarExpr | IntExpr | FloatExpr | 3272 //// CharExpr | StringExpr | ArrayLiteralExpr | AArrayLiteralExpr | 3273 //// FuncLiteralExpr | AssertExpr | MixinExpr | ImportExpr | 3274 //// TypeidExpr | IsExpr | ParenExpr | TraitsExpr | TypeDotIdExpr | 3275 //// SpecialTokenExpr 3276 ////TypeofExpr := TypeofType 3277 ////ThisExpr := this 3278 ////SuperExpr := super 3279 ////NullExpr := null 3280 ////BoolExpr := true | false 3281 ////DollarExpr := "$" 3282 ////IntExpr := IntegerLiteral 3283 ////FloatExpr := FloatLiteral 3284 ////CharExpr := CharacterLiteral 3285 ////StringExpr := StringLiteral+ 3286 ////StringLiteral := NormalStringLiteral | EscapeStringLiteral | 3287 //// RawStringLiteral | HexStringLiteral | DelimitedStringLiteral | 3288 //// TokenStringLiteral 3289 ////ArrayLiteralExpr := "[" ExpressionList2 "]" 3290 ////AArrayLiteralExpr := "[" KeyValue ("," KeyValue)* ","? "]" 3291 ////KeyValue := (AssignExpr ":" AssignExpr) 3292 ////FuncLiteralExpr := (function | delegate)? 3293 //// (ReturnType? ParameterList FunctionPostfix?)? "{" Statements "}" 3294 ////AssertExpr := assert "(" AssignExpr ("," AssignExpr)? ")" 3295 ////MixinExpr := mixin "(" AssignExpr ")" 3296 ////ImportExpr := import "(" AssignExpr ")" 3297 ////TypeidExpr := typeid "(" Type ")" 3298 ////IsExpr := is "(" Declarator (Specialization TemplateParameterList2)? ")" 3299 ////Specialization := ((":" | "==") (SpecToken | Type)) 3300 ////SpecToken := typedef | struct | union | class | interface | enum | 3301 //// function | delegate | super | return | 3302 //// const | immutable | inout | shared 3303 ////ParenExpr := "(" Expression ")" 3304 ////TraitsExpr := __traits "(" Identifier ("," TemplateArguments)? ")" 3305 ////TypeDotIdExpr := "(" Type ")" "." Identifier 3306 ////SpecialTokenExpr := SpecialToken) 3307 Expression parsePrimaryExpr() 3308 { 3309 auto begin = token; 3310 Expression e; 3311 switch (token.kind) 3312 { 3313 case T!"Identifier": 3314 e = nextIs!"=>" ? parseSingleParamLambdaExpr() : parseIdentifierExpr(); 3315 return e; 3316 case T!"typeof": 3317 e = new TypeofExpr(parseTypeofType()); 3318 break; 3319 case T!".": 3320 e = set(new ModuleScopeExpr(), begin, begin); 3321 nT(); 3322 // parseIdentifiersExpr() isn't used; see case T!"." in parsePostExpr(). 3323 e = parseIdentifierExpr(e); 3324 return e; 3325 case T!"this": 3326 e = new ThisExpr(); 3327 goto LnT_and_return; 3328 case T!"super": 3329 e = new SuperExpr(); 3330 goto LnT_and_return; 3331 case T!"null": 3332 e = new NullExpr(); 3333 goto LnT_and_return; 3334 case T!"true", T!"false": 3335 e = new BoolExpr(token); 3336 goto LnT_and_return; 3337 case T!"$": 3338 e = new DollarExpr(); 3339 goto LnT_and_return; 3340 case T!"Int32", T!"Int64", T!"UInt32", T!"UInt64": 3341 e = new IntExpr(token); 3342 goto LnT_and_return; 3343 case T!"Float32", T!"Float64", T!"Float80", 3344 T!"IFloat32", T!"IFloat64", T!"IFloat80": 3345 e = new FloatExpr(token); 3346 goto LnT_and_return; 3347 case T!"Character": 3348 e = new CharExpr(token); 3349 goto LnT_and_return; 3350 LnT_and_return: 3351 nT(); 3352 assert(begin is prevToken); 3353 set(e, begin, begin); 3354 return e; 3355 case T!"String": 3356 auto str = token.strval.str; 3357 char postfix = token.strval.pf; 3358 nT(); 3359 if (auto t = consumedToken!"String") 3360 { // Concatenate adjacent string literals. 3361 auto buffer = lexer.getBuffer(); 3362 buffer ~= cast(cstring)str; 3363 do 3364 { 3365 if (auto pf = t.strval.pf) // If the string has a postfix char. 3366 { 3367 if (pf != postfix) 3368 error(t, MID.StringPostfixMismatch); 3369 postfix = pf; 3370 } 3371 buffer ~= cast(cstring)t.strval.str; 3372 } while((t = consumedToken!"String") !is null); 3373 str = cast(cbinstr)buffer[].dup; // Copy final string. 3374 lexer.setBuffer(buffer); 3375 } 3376 3377 if (postfix) 3378 { // Check for UTF8 errors and if needed convert to UTF16 or UTF32. 3379 cbinstr function(cstring) conversionFunction = 3380 (postfix == 'c') ? x => cast(cbinstr)x : 3381 (postfix == 'w') ? x => cast(cbinstr)dil.Unicode.toUTF16(x) : 3382 x => cast(cbinstr)dil.Unicode.toUTF32(x); 3383 if (!hasInvalidUTF8(str, begin)) 3384 str = conversionFunction(cast(cstring)str); 3385 } 3386 3387 // Did the value change due to conversion or multiple string literals? 3388 if (begin.strval.str !is str) 3389 str = lexer.lookupString(str); // Insert into table if so. 3390 3391 e = new StringExpr(str, postfix); 3392 break; 3393 case T!"[": 3394 nT(); 3395 Expression[] exprs; 3396 if (!tokenIs!"]") 3397 exprs = [parseAssignExpr()]; 3398 if (consumed!":") 3399 { // "[" AssignExpr ":" 3400 Expression[] values; 3401 while (1) 3402 { 3403 values ~= parseAssignExpr(); 3404 if (!consumed!"," || tokenIs!"]") 3405 break; 3406 exprs ~= parseAssignExpr(); // Keys 3407 require!":"; 3408 } 3409 e = new AArrayLiteralExpr(exprs, values); 3410 } 3411 else 3412 { // "[" "]" | "[" AssignExpr 3413 if (consumed!",") // "," ExpressionList2 3414 exprs ~= parseExpressionList2(T!"]"); 3415 e = new ArrayLiteralExpr(exprs); 3416 } 3417 requireClosing!"]"(begin); 3418 break; 3419 case T!"{": 3420 // DelegateLiteral := { Statements } 3421 e = new FuncLiteralExpr(parseFunctionBody()); 3422 break; 3423 case T!"function", T!"delegate": 3424 // FunctionLiteral := ("function" | "delegate") 3425 // ReturnType? "(" ArgumentList ")" FunctionPostfix? FunctionBody 3426 nT(); // Skip function or delegate keyword. 3427 Type returnType; 3428 Parameters parameters; 3429 if (!tokenIs!"{") 3430 { 3431 if (!tokenIs!"(") // Optional return type 3432 returnType = parseBasicTypes(); 3433 parameters = parseParameterList(); 3434 version(D2) 3435 parameters.postSTCs = parseFunctionPostfix(); 3436 } 3437 auto funcBody = consumed!"=>" ? parseAssignExpr() : parseFunctionBody(); 3438 e = new FuncLiteralExpr(begin, returnType, parameters, funcBody); 3439 break; 3440 case T!"assert": 3441 nT(); 3442 require2!"("; 3443 e = parseAssignExpr(); 3444 auto msg = consumed!"," ? parseAssignExpr() : null; 3445 require2!")"; 3446 e = new AssertExpr(e, msg); 3447 break; 3448 case T!"mixin": 3449 nT(); 3450 require2!"("; 3451 e = new MixinExpr(parseAssignExpr()); 3452 require2!")"; 3453 break; 3454 case T!"import": 3455 nT(); 3456 require2!"("; 3457 e = new ImportExpr(parseAssignExpr()); 3458 require2!")"; 3459 break; 3460 case T!"typeid": 3461 nT(); 3462 require2!"("; 3463 e = new TypeidExpr(parseType()); 3464 require2!")"; 3465 break; 3466 case T!"is": 3467 nT(); 3468 auto paren = requireOpening!"("; 3469 3470 Type specType; 3471 Token* ident; // optional Identifier 3472 Token* opTok, specTok; 3473 3474 auto type = parseDeclaratorOptId(ident); 3475 3476 if (token.kind.Any!(":", "==")) 3477 { 3478 opTok = token; 3479 nT(); 3480 switch (token.kind) 3481 { 3482 case T!"typedef", T!"struct", T!"union", T!"class", T!"interface", 3483 T!"enum", T!"function", T!"delegate", T!"super", T!"return", 3484 T!"__argTypes", T!"__parameters": 3485 case_Const_Immutable_Inout_Shared: // D2 3486 specTok = token; 3487 nT(); 3488 break; 3489 version(D2) 3490 { 3491 case T!"const", T!"immutable", T!"inout", T!"shared": 3492 if (peekNext().Any!(")", ",")) 3493 goto case_Const_Immutable_Inout_Shared; 3494 goto default; // It's a type. 3495 } // version(D2) 3496 default: 3497 specType = parseType(); 3498 } 3499 } 3500 3501 TemplateParameters tparams; 3502 // "is" "(" DeclaratorOptId (":" | "==") TypeSpecialization "," 3503 // TemplateParameterList ")" 3504 version(D2) 3505 if (specType && tokenIs!",") 3506 tparams = parseTemplateParameterList2(); 3507 requireClosing!")"(paren); 3508 e = new IsExpr(type, ident, opTok, specTok, specType, tparams); 3509 break; 3510 case T!"(": 3511 auto kind = skipParens(token, T!")").kind; 3512 if (kind.Any!(FunctionPostfix, "{", "=>")) // E.g.: "(" int "a" ")" pure 3513 { 3514 auto parameters = parseParameterList(); // "(" ParameterList ")" 3515 parameters.postSTCs = parseFunctionPostfix(); // Optional attributes. 3516 FuncBodyStmt fstmt; 3517 if (tokenIs!"{") // "(" ... ")" "{" ... 3518 fstmt = parseFunctionBody(); 3519 else if (tokenIs!"=>") // "(" ... ")" "=>" ... 3520 { 3521 e = new LambdaExpr(parameters, parseLambdaExprBody()); 3522 break; 3523 } 3524 else 3525 error(token, MID.ExpectedFunctionBody, token.text); 3526 e = new FuncLiteralExpr(parameters, fstmt); 3527 } 3528 else 3529 { // "(" Expression ")" 3530 auto paren = token; 3531 skip!"("; 3532 e = parseExpression(); 3533 requireClosing!")"(paren); 3534 e = new ParenExpr(e); 3535 } 3536 break; 3537 version(D2) 3538 { 3539 case T!"__traits": 3540 nT(); 3541 auto paren = requireOpening!"("; 3542 auto ident = requireIdentifier(MID.ExpectedAnIdentifier); 3543 auto args = consumed!"," ? parseTemplateArguments2() : null; 3544 requireClosing!")"(paren); 3545 e = new TraitsExpr(ident, args); 3546 break; 3547 } // version(D2) 3548 default: 3549 if (token.isIntegralType) 3550 { // IntegralType . Identifier 3551 auto type = new IntegralType(token.kind); 3552 nT(); 3553 set(type, begin); 3554 require2!"."; 3555 auto ident = requireIdentifier(MID.ExpectedIdAfterTypeDot); 3556 e = new TypeDotIdExpr(type, ident); 3557 } 3558 else if (token.isSpecialToken) 3559 e = new SpecialTokenExpr(consume()); 3560 else 3561 { 3562 error2(MID.ExpectedButFound, "Expression", token); 3563 nT(); 3564 e = new IllegalExpr(); 3565 } 3566 } 3567 set(e, begin); 3568 return e; 3569 } 3570 3571 /// $(BNF NewExpr := NewAnonClassExpr | NewObjectExpr 3572 ////NewAnonClassExpr := 3573 //// new NewArguments? class NewArguments? 3574 //// (SuperClass InterfaceClasses)? ClassBody 3575 ////NewObjectExpr := new NewArguments? Type (NewArguments | NewArray)? 3576 ////NewArguments := "(" ArgumentList ")" 3577 ////NewArray := "[" AssignExpr "]") 3578 /// Params: 3579 /// frame = The frame or 'this' pointer expression. 3580 Expression parseNewExpr(Expression frame = null) 3581 { 3582 auto begin = token; 3583 skip!"new"; 3584 3585 Expression e; 3586 Expression[] ctorArguments; 3587 3588 auto newArguments = tokenIs!"(" ? parseArguments() : null; 3589 3590 if (consumed!"class") 3591 { // NewAnonymousClassExpr 3592 if (tokenIs!"(") 3593 ctorArguments = parseArguments(); 3594 auto bases = !tokenIs!"{" ? parseBaseClasses() : null; 3595 auto decls = parseDeclarationDefinitionsBody(); 3596 e = new NewClassExpr(frame, newArguments, ctorArguments, bases, decls); 3597 } 3598 else 3599 { // NewObjectExpr 3600 auto type = parseType(); 3601 3602 if (type.Is!(ModifierType)) 3603 { // Skip modifier types in the chain and search for an ArrayType. 3604 auto t = type; 3605 while ((t = t.next).Is!(ModifierType)) 3606 {} 3607 if (auto at = t.Is!(ArrayType)) 3608 if (at.isStatic() || at.isAssociative()) 3609 { 3610 at.parent.setNext(at.next); // Link it out. 3611 at.setNext(type); // Make it the head type. 3612 type = at; 3613 } 3614 } 3615 3616 // Don't parse arguments if an array type was parsed previously. 3617 auto arrayType = type.Is!(ArrayType); 3618 if (arrayType && arrayType.isStatic()) 3619 {} 3620 else if (arrayType && arrayType.isAssociative()) 3621 { // Backtrack to parse as a StaticArray. 3622 auto bracket = type.begin; 3623 backtrackTo(bracket); 3624 3625 skip!"["; 3626 auto index = parseExpression(); 3627 requireClosing!"]"(bracket); 3628 type = set(new ArrayType(type.next, index), bracket); 3629 } 3630 else if (tokenIs!"(") // NewArguments 3631 ctorArguments = parseArguments(); 3632 e = new NewExpr(frame, newArguments, type, ctorArguments); 3633 } 3634 return set(e, begin); 3635 } 3636 3637 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3638 | Type parsing methods | 3639 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ 3640 3641 /// Parses a Declarator with an optional Identifier. 3642 /// 3643 /// $(BNF DeclaratorOptId := Type (Identifier DeclaratorSuffix)?) 3644 /// Params: 3645 /// ident = Receives the optional identifier of the declarator. 3646 Type parseDeclaratorOptId(ref Token* ident) 3647 { 3648 auto type = parseType(); 3649 ident = optionalIdentifier(); 3650 if (ident) 3651 type = parseDeclaratorSuffix(type); 3652 return type; 3653 } 3654 3655 /// Parses a Declarator with an Identifier. 3656 /// 3657 /// $(BNF Declarator := Type Identifier DeclaratorSuffix) 3658 /// Params: 3659 /// ident = Receives the identifier of the declarator. 3660 Type parseDeclarator(ref Token* ident) 3661 { 3662 auto type = parseDeclaratorOptId(ident); 3663 if (!ident) 3664 error2(MID.ExpectedDeclaratorIdentifier, token); 3665 return type; 3666 } 3667 3668 /// Parses a full Type. 3669 /// 3670 /// $(BNF Type := ModAttrType | BasicTypes 3671 ////ModAttrType := Modifier Type 3672 ////Modifier := const | immutable | shared | inout) 3673 Type parseType() 3674 { 3675 version(D2) 3676 if (!nextIs!"(" && token.kind.Any!("const", "immutable", "inout", "shared")) 3677 { 3678 auto mod = consume(); 3679 return set(new ModifierType(parseType(), mod, false), mod); 3680 } 3681 return parseBasicTypes(); 3682 } 3683 3684 /// Parses the basic types. 3685 /// 3686 /// $(BNF BasicTypes := BasicType BasicType2) 3687 Type parseBasicTypes() 3688 { 3689 return parseBasicType2(parseBasicType()); 3690 } 3691 3692 /// $(BNF IdentifierType := Identifier | TemplateInstance) 3693 Type parseIdentifierType(Type next = null) 3694 { 3695 auto begin = token; 3696 auto ident = requireIdentifier(MID.ExpectedAnIdentifier); 3697 auto t = consumed!"!" ? 3698 new TmplInstanceType(next, ident, parseOneOrMoreTemplateArguments()) : 3699 new IdentifierType(next, ident); 3700 return set(t, begin); 3701 } 3702 3703 /// $(BNF TypeofType := typeof "(" Expression ")" | TypeofReturn 3704 ////TypeofReturn := typeof "(" return ")") 3705 Type parseTypeofType() 3706 { 3707 auto begin = token; 3708 skip!"typeof"; 3709 auto paren = requireOpening!"("; 3710 version(D1) 3711 auto e = parseExpression(); 3712 else 3713 auto e = consumed!"return" ? null : parseExpression(); 3714 requireClosing!")"(paren); 3715 return set(new TypeofType(e), begin); 3716 } 3717 3718 /// $(BNF QualifiedType := 3719 //// (this | super | TypeofType | ModuleScopeType? IdentifierType) 3720 //// ("." IdentifierType)*) 3721 Type parseQualifiedType() 3722 { 3723 auto begin = token; 3724 Type type; 3725 3726 if (tokenIs!".") 3727 type = set(new ModuleScopeType(), begin, begin); 3728 else if (tokenIs!"typeof") 3729 type = parseTypeofType(); 3730 else if (token.kind.Any!("this", "super")) // D2 3731 type = set(new IdentifierType(null, consume()), begin, begin); 3732 else 3733 type = parseIdentifierType(); 3734 3735 while (consumed!".") 3736 type = parseIdentifierType(type); 3737 3738 return type; 3739 } 3740 3741 /// $(BNF BasicType := IntegralType | QualifiedType | ModParenType 3742 ////ModParenType := Modifier "(" Type ")") 3743 Type parseBasicType() 3744 { 3745 auto begin = token; 3746 Type t; 3747 3748 if (token.isIntegralType) 3749 { 3750 t = new IntegralType(token.kind); 3751 nT(); 3752 } 3753 else 3754 switch (token.kind) 3755 { 3756 version (D2) 3757 { 3758 case T!"this", T!"super": 3759 goto case T!"Identifier"; 3760 } 3761 case T!"Identifier", T!"typeof", T!".": 3762 t = parseQualifiedType(); 3763 return t; 3764 version(D2) 3765 { // Modifier "(" Type ")" 3766 case T!"const", T!"immutable", T!"inout", T!"shared": 3767 auto kind = consume(); 3768 auto paren = requireOpening!"("; 3769 t = parseType(); // Type 3770 requireClosing!")"(paren); 3771 t = new ModifierType(t, kind, true); 3772 break; 3773 } // version(D2) 3774 default: 3775 error2(MID.ExpectedButFound, "BasicType", token); 3776 t = new IllegalType(); 3777 nT(); 3778 } 3779 return set(t, begin); 3780 } 3781 3782 /// $(BNF BasicType2 := 3783 //// (PointerType | ArrayType | FunctionType | DelegateType)* 3784 ////PointerType := "*" 3785 ////FunctionType := function ParameterList 3786 ////DelegateType := delegate ParameterList) 3787 Type parseBasicType2(Type t) 3788 { 3789 while (1) 3790 { 3791 auto begin = token; 3792 switch (token.kind) 3793 { 3794 case T!"*": 3795 t = new PointerType(t); 3796 nT(); 3797 break; 3798 case T!"[": 3799 t = parseArrayType(t); 3800 continue; 3801 case T!"function", T!"delegate": 3802 auto kind = consume().kind; 3803 auto parameters = parseParameterList(); 3804 version(D2) 3805 parameters.postSTCs = parseFunctionPostfix(); 3806 // TODO: add stcs to t. 3807 if (kind == T!"function") 3808 t = new FunctionType(t, parameters); 3809 else 3810 t = new DelegateType(t, parameters); 3811 break; 3812 default: 3813 return t; 3814 } 3815 set(t, begin); 3816 } 3817 assert(0); 3818 } 3819 3820 /// Parses the array types after the declarator (C-style.) E.g.: int a[] 3821 /// 3822 /// $(BNF DeclaratorSuffix := ArrayType*) 3823 /// Returns: lhsType or a suffix type. 3824 /// Params: 3825 /// lhsType = The type on the left-hand side. 3826 Type parseDeclaratorSuffix(Type lhsType) 3827 { // The Type chain should be as follows: 3828 // int[3]* Identifier [][1][2] 3829 // <– <–. ·start·–> -. 3830 // `---------------´ 3831 // Resulting chain: [][1][2]*[3]int 3832 auto result = lhsType; // Return lhsType if nothing else is parsed. 3833 if (tokenIs!"[") 3834 { // The previously parsed ArrayType. 3835 auto prevType = result = parseArrayType(lhsType); 3836 // Continue parsing ArrayTypes. 3837 while (tokenIs!"[") 3838 { 3839 auto arrayType = parseArrayType(lhsType); 3840 prevType.setNext(arrayType); // Make prevType point to this type. 3841 prevType = arrayType; // Current type becomes previous type. 3842 } 3843 } 3844 return result; 3845 } 3846 3847 /// $(BNF ArrayType := "[" (Type | ArrayTypeIndex) "]" 3848 ////ArrayTypeIndex := AssignExpr (".." AssignExpr)?) 3849 Type parseArrayType(Type t) 3850 { 3851 auto begin = token; 3852 skip!"["; 3853 if (consumed!"]") 3854 t = new ArrayType(t); 3855 else 3856 { 3857 bool success; 3858 Type parseAAType() 3859 { 3860 auto type = parseType(); 3861 require!"]"; 3862 return type; 3863 } 3864 auto assocType = tryToParse(&parseAAType, success); 3865 if (success) 3866 t = new ArrayType(t, assocType); 3867 else 3868 { 3869 auto e = parseAssignExpr(); 3870 auto e2 = consumed!".." ? parseAssignExpr() : null; 3871 requireClosing!"]"(begin); 3872 t = new ArrayType(t, e, e2); 3873 } 3874 } 3875 return set(t, begin); 3876 } 3877 3878 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3879 | Parameter parsing methods | 3880 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ 3881 3882 /// Parses a list of AssignExpressions. 3883 /// $(BNF ExpressionList := AssignExpr ("," AssignExpr)*) 3884 Expression[] parseExpressionList() 3885 { 3886 Expression[] expressions; 3887 do 3888 expressions ~= parseAssignExpr(); 3889 while (consumed!","); 3890 return expressions; 3891 } 3892 3893 /// Parses an optional ExpressionList and allows a trailing comma. 3894 /// $(BNF ExpressionList2 := (ExpressionList ","?)? ) 3895 Expression[] parseExpressionList2(TOK closing_tok) 3896 { 3897 Expression[] expressions; 3898 while (token.kind != closing_tok) 3899 { 3900 expressions ~= parseAssignExpr(); 3901 if (!consumed!",") 3902 break; 3903 } 3904 return expressions; 3905 } 3906 3907 /// Parses a list of Arguments. 3908 /// $(BNF Arguments := "(" ExpressionList2 ")") 3909 Expression[] parseArguments() 3910 { 3911 auto paren = token; 3912 skip!"("; 3913 auto args = !tokenIs!")" ? parseExpressionList2(T!")") : null; 3914 requireClosing!")"(paren); 3915 return args; 3916 } 3917 3918 /// Parses a ParameterList. 3919 /// $(BNF ParameterList := "(" Parameters? ")" 3920 ////Parameters := Parameter ("," Parameter)* ","? 3921 ////Parameter := StorageClasses? (Type Name? | Type? Name ) 3922 //// ("=" AssignExpr)?) 3923 Parameters parseParameterList() 3924 { 3925 auto paren = requireOpening!"("; 3926 auto params = new Parameters(); 3927 3928 Expression defValue; // Default value. 3929 3930 while (!tokenIs!")") 3931 { 3932 auto paramBegin = token; 3933 StorageClass stcs, stc; // Storage classes. 3934 Token* stctok; // Token of the last storage class. 3935 Type type; // Type of the parameter. 3936 Token* name; // Name of the parameter. 3937 3938 void pushParameter() 3939 { // Appends a new Parameter to the list. 3940 auto param = new Parameter(stcs, stctok, type, name, defValue); 3941 params ~= set(param, paramBegin); 3942 } 3943 3944 if (consumed!"...") 3945 goto LvariadicParam; // Go to common code and leave the loop. 3946 3947 while (1) 3948 { // Parse storage classes. 3949 switch (token.kind) 3950 { 3951 version(D2) 3952 { 3953 case T!"const", T!"immutable", T!"inout", T!"shared": 3954 if ((stc = getSTC) == 0) 3955 break; 3956 goto Lcommon; 3957 case T!"final": stc = StorageClass.Final; goto Lcommon; 3958 case T!"scope": stc = StorageClass.Scope; goto Lcommon; 3959 case T!"static": stc = StorageClass.Static; goto Lcommon; 3960 case T!"auto": stc = StorageClass.Auto; goto Lcommon; 3961 } // version(D2) 3962 case T!"in": stc = StorageClass.In; goto Lcommon; 3963 case T!"out": stc = StorageClass.Out; goto Lcommon; 3964 version (D1) 3965 { 3966 case T!"inout": goto case T!"ref"; 3967 } 3968 case T!"ref": stc = StorageClass.Ref; goto Lcommon; 3969 case T!"lazy": stc = StorageClass.Lazy; goto Lcommon; 3970 Lcommon: 3971 // Check for redundancy. 3972 if (stcs & stc) 3973 error2(MID.RedundantStorageClass, token); 3974 stcs |= stc; 3975 stctok = token; 3976 nT(); 3977 version(D2) 3978 continue; 3979 else 3980 break; // In D1.0 the grammar only allows one storage class. 3981 default: 3982 } 3983 break; // Break out of inner loop. 3984 } 3985 type = parseDeclaratorOptId(name); 3986 3987 if (consumed!"=") 3988 defValue = parseAssignExpr(); 3989 else if (defValue !is null) // Parsed a defValue previously? 3990 error(name ? name : type.begin, // Position. 3991 MID.ExpectedParamDefValue, 3992 name ? name.text : ""); // Name. 3993 3994 if (consumed!"...") 3995 { 3996 if (stcs & (StorageClass.Ref | StorageClass.Out)) 3997 error(paramBegin, MID.IllegalVariadicParam); 3998 LvariadicParam: 3999 stcs |= StorageClass.Variadic; 4000 pushParameter(); 4001 // TODO: allow trailing comma here? DMD doesn't... 4002 if (!tokenIs!")") 4003 error(token, MID.ParamsAfterVariadic); 4004 break; 4005 } 4006 // Add a non-variadic parameter to the list. 4007 pushParameter(); 4008 4009 if (!consumed!",") 4010 break; 4011 } 4012 requireClosing!")"(paren); 4013 return set(params, paren); 4014 } 4015 4016 /// $(BNF TemplateArgumentsOneOrMore := 4017 //// TemplateArgumentList | TemplateArgumentSingle) 4018 TemplateArguments parseOneOrMoreTemplateArguments() 4019 { 4020 version(D2) 4021 if (!tokenIs!"(") 4022 { // Parse one TArg, but still put it in TemplateArguments. 4023 auto targs = new TemplateArguments; 4024 auto begin = token; 4025 bool success; 4026 // Don't parse a full Type. TODO: restrict further? 4027 auto typeArg = tryToParse(&parseBasicType, success); 4028 // Don't parse a full Expression. TODO: restrict further? 4029 targs ~= success ? typeArg : parsePrimaryExpr(); 4030 return set(targs, begin); 4031 } // version(D2) 4032 return parseTemplateArguments(); 4033 } 4034 4035 /// $(BNF TemplateArgumentList := "(" TemplateArguments? ")") 4036 TemplateArguments parseTemplateArguments() 4037 { 4038 TemplateArguments targs; 4039 auto paren = requireOpening!"("; 4040 targs = !tokenIs!")" ? parseTemplateArguments_() : new TemplateArguments; 4041 requireClosing!")"(paren); 4042 return set(targs, paren); 4043 } 4044 4045 /// $(BNF TemplateArgumentList2 := TemplateArguments (?= "$(RP)")) 4046 TemplateArguments parseTemplateArguments2() 4047 { 4048 version(D2) 4049 { 4050 TemplateArguments targs; 4051 if (!tokenIs!")") 4052 targs = parseTemplateArguments_(); 4053 else 4054 error(token, MID.ExpectedTypeOrExpression); 4055 return targs; 4056 } // version(D2) 4057 else 4058 assert(0); 4059 } 4060 4061 /// Used with method tryToParse(). 4062 /// $(BNF TypeArgument := Type (?= "," | "$(RP)")) 4063 Type parseTypeArgument() 4064 { 4065 assert(trying); 4066 auto type = parseType(); 4067 if (token.kind.Any!(",", ")")) 4068 return type; 4069 fail_tryToParse(); 4070 return null; 4071 } 4072 4073 /// $(BNF TemplateArguments := TemplateArgument ("," TemplateArgument)* 4074 ////TemplateArgument := TypeArgument | AssignExpr) 4075 TemplateArguments parseTemplateArguments_() 4076 { 4077 auto begin = token; 4078 auto targs = new TemplateArguments; 4079 while (!tokenIs!")") 4080 { 4081 bool success; 4082 auto typeArgument = tryToParse(&parseTypeArgument, success); 4083 // TemplateArgument := Type | AssignExpr 4084 targs ~= success ? typeArgument : parseAssignExpr(); 4085 if (!consumed!",") 4086 break; 4087 } 4088 set(targs, begin); 4089 return targs; 4090 } 4091 4092 /// $(BNF Constraint := if "(" ConstraintExpr ")") 4093 Expression parseOptionalConstraint() 4094 { 4095 if (!consumed!"if") 4096 return null; 4097 auto paren = requireOpening!"("; 4098 auto e = parseExpression(); 4099 requireClosing!")"(paren); 4100 return e; 4101 } 4102 4103 /// $(BNF TemplateParameterList := "(" TemplateParameters? ")") 4104 TemplateParameters parseTemplateParameterList() 4105 { 4106 auto tparams = new TemplateParameters; 4107 auto paren = requireOpening!"("; 4108 if (!tokenIs!")") 4109 parseTemplateParameterList_(tparams); 4110 requireClosing!")"(paren); 4111 return set(tparams, paren); 4112 } 4113 4114 /// $(BNF TemplateParameterList2 := "," TemplateParameters "$(RP)") 4115 TemplateParameters parseTemplateParameterList2() 4116 { 4117 version(D2) 4118 { 4119 skip!","; 4120 auto begin = token; 4121 auto tparams = new TemplateParameters; 4122 if (!tokenIs!")") 4123 parseTemplateParameterList_(tparams); 4124 else 4125 error(token, MID.ExpectedTemplateParameters); 4126 return set(tparams, begin); 4127 } // version(D2) 4128 else return null; 4129 } 4130 4131 /// Parses template parameters. 4132 /// $(BNF TemplateParameters := TemplateParam ("," TemplateParam)* 4133 ////TemplateParam := 4134 //// TemplateAliasParam | TemplateTypeParam | TemplateTupleParam | 4135 //// TemplateValueParam | TemplateThisParam 4136 ////TemplateAliasParam := alias Identifier SpecOrDefaultType 4137 ////TemplateTypeParam := Identifier SpecOrDefaultType 4138 ////TemplateTupleParam := Identifier "..." 4139 ////TemplateValueParam := Declarator SpecOrDefaultValue 4140 ////TemplateThisParam := this Identifier SpecOrDefaultType # D2.0 4141 ////SpecOrDefaultType := (":" Type)? ("=" Type)? 4142 ////SpecOrDefaultValue := (":" Value)? ("=" Value)? 4143 ////Value := CondExpr 4144 ////) 4145 void parseTemplateParameterList_(TemplateParameters tparams) 4146 { 4147 while (!tokenIs!")") 4148 { 4149 auto paramBegin = token; 4150 TemplateParam tp; 4151 Token* ident; 4152 Type specType, defType; 4153 4154 void parseSpecAndOrDefaultType() 4155 { 4156 if (consumed!":") // ":" SpecializationType 4157 specType = parseType(); 4158 if (consumed!"=") // "=" DefaultType 4159 defType = parseType(); 4160 } 4161 4162 switch (token.kind) 4163 { 4164 case T!"alias": // TemplateAliasParam := "alias" Identifier 4165 nT(); 4166 ident = requireIdentifier(MID.ExpectedAliasTemplateParam); 4167 Node spec, def; 4168 version(D2) 4169 { 4170 Node parseExpOrType() 4171 { 4172 bool success; 4173 auto typeArgument = tryToParse(&parseTypeArgument, success); 4174 return success ? typeArgument : parseCondExpr(); 4175 } 4176 if (consumed!":") // ":" Specialization 4177 spec = parseExpOrType(); 4178 if (consumed!"=") // "=" Default 4179 def = parseExpOrType(); 4180 } // version(D2) 4181 else 4182 { // D1 4183 parseSpecAndOrDefaultType(); 4184 spec = specType; 4185 def = defType; 4186 } 4187 tp = new TemplateAliasParam(ident, spec, def); 4188 break; 4189 case T!"Identifier": 4190 ident = token; 4191 switch (peekNext()) 4192 { 4193 case T!"...": // TemplateTupleParam := Identifier "..." 4194 skip!"Identifier"; skip!"..."; 4195 if (tokenIs!",") 4196 error(MID.TemplateTupleParameter); 4197 tp = new TemplateTupleParam(ident); 4198 break; 4199 case T!",", T!")", T!":", T!"=": // TemplateTypeParam := Identifier 4200 skip!"Identifier"; 4201 parseSpecAndOrDefaultType(); 4202 tp = new TemplateTypeParam(ident, specType, defType); 4203 break; 4204 default: // TemplateValueParam := Declarator 4205 ident = null; 4206 goto LTemplateValueParam; 4207 } 4208 break; 4209 version(D2) 4210 { 4211 case T!"this": // TemplateThisParam := "this" TemplateTypeParam 4212 nT(); 4213 ident = requireIdentifier(MID.ExpectedNameForThisTempParam); 4214 parseSpecAndOrDefaultType(); 4215 tp = new TemplateThisParam(ident, specType, defType); 4216 break; 4217 } // version(D2) 4218 default: 4219 LTemplateValueParam: 4220 // TemplateValueParam := Declarator 4221 auto valueType = parseDeclarator(ident); 4222 // ":" SpecializationValue 4223 auto specValue = consumed!":" ? parseCondExpr() : null; 4224 // "=" DefaultValue 4225 auto defValue = consumed!"=" ? parseCondExpr() : null; 4226 tp = new TemplateValueParam(valueType, ident, specValue, defValue); 4227 } 4228 4229 // Push template parameter. 4230 tparams ~= set(tp, paramBegin); 4231 4232 if (!consumed!",") 4233 break; 4234 } 4235 } 4236 4237 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4238 | Error handling methods | 4239 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ 4240 4241 /// Returns the string of a token printable to the client. 4242 cstring getPrintable(Token* token) 4243 { // TODO: there are some other tokens that have to be handled, e.g. strings. 4244 return token.kind == T!"EOF" ? "EOF" : token.text; 4245 } 4246 4247 alias expected = require; 4248 4249 /// Requires a token of kind T!str. 4250 void require(string str)() 4251 { 4252 if (!consumed!str) 4253 error2(MID.ExpectedButFound, str, token); 4254 } 4255 4256 /// Requires a token of kind tok. Uses the token end as the error location. 4257 void require2(string str)() 4258 { 4259 if (!consumed!str) 4260 error2_eL(MID.ExpectedButFound, str, token); 4261 } 4262 4263 /// Parses an optional identifier. 4264 /// Returns: null or the identifier. 4265 Token* optionalIdentifier() 4266 { 4267 return tokenIs!"Identifier" ? consume() : null; 4268 } 4269 4270 /// Reports an error if the current token is not an identifier. 4271 /// Params: 4272 /// mid = The error message ID to be used. 4273 /// Returns: The identifier token or null. 4274 Token* requireIdentifier(MID mid) 4275 { 4276 auto idtok = consumedToken!"Identifier"; 4277 if (!idtok) 4278 error(token, mid, token.text); 4279 return idtok; 4280 } 4281 4282 /// Returns the opening bracket or the current token. 4283 Token* requireOpening(string str)() 4284 { 4285 static assert(str.In("{", "(", "["), "invalid bracket"); 4286 if (consumed!str) 4287 return prevToken; 4288 require2!str; 4289 return token; 4290 } 4291 4292 /// Reports an error if the closing counterpart of a token is not found. 4293 void requireClosing(string str)(Token* opening) 4294 { 4295 static assert(str.In("}", ")", "]"), "invalid bracket"); 4296 assert(opening !is null); 4297 if (!consumed!str) 4298 { 4299 auto loc = opening.getErrorLocation(lexer.srcText.filePath); 4300 error(token, MID.ExpectedClosing, 4301 str, opening.text, loc.lineNum, loc.colNum, 4302 getPrintable(token)); 4303 } 4304 } 4305 4306 /// Returns true if the string str has an invalid UTF-8 sequence. 4307 bool hasInvalidUTF8(cbinstr str, Token* begin) 4308 { 4309 auto invalidUTF8Seq = Lexer.findInvalidUTF8Sequence(str); 4310 if (invalidUTF8Seq.length) 4311 error(begin, MID.InvalidUTF8SequenceInString, invalidUTF8Seq); 4312 return invalidUTF8Seq.length != 0; 4313 } 4314 4315 /// Forwards error parameters. 4316 void error(Token* token, MID mid, ...) 4317 { 4318 error(_arguments, _argptr, token, false, mid); 4319 } 4320 /// ditto 4321 void error(MID mid, ...) 4322 { 4323 error(_arguments, _argptr, this.token, false, mid); 4324 } 4325 /// ditto 4326 void error_eL(MID mid, ...) 4327 { 4328 error(_arguments, _argptr, this.prevToken, true, mid); 4329 } 4330 4331 /// ditto 4332 void error2(MID mid, Token* token) 4333 { 4334 error(mid, getPrintable(token)); 4335 } 4336 /// ditto 4337 void error2(MID mid, string arg, Token* token) 4338 { 4339 error(mid, arg, getPrintable(token)); 4340 } 4341 /// ditto 4342 void error2_eL(MID mid, string arg, Token* token) 4343 { 4344 error_eL(mid, arg, getPrintable(token)); 4345 } 4346 4347 /// Creates an error report and appends it to a list. 4348 /// Params: 4349 /// token = Used to get the location of the error. 4350 /// endLoc = Get the position of the token's end or start character? 4351 /// formatMsg = The parser error message. 4352 void error(TypeInfo[] _arguments, va_list _argptr, 4353 Token* token, bool endLoc, cstring formatMsg) 4354 { 4355 if (trying) 4356 { 4357 errorCount++; 4358 return; 4359 } 4360 auto filePath = lexer.srcText.filePath; 4361 auto location = endLoc ? 4362 token.errorLocationOfEnd(filePath) : 4363 token.getErrorLocation(filePath); 4364 auto msg = diag.format(_arguments, _argptr, formatMsg); 4365 auto error = new ParserError(location, msg); 4366 errors ~= error; 4367 diag ~= error; 4368 } 4369 /// ditto 4370 void error(TypeInfo[] _arguments, va_list _argptr, 4371 Token* token, bool endLoc, MID mid) 4372 { 4373 error(_arguments, _argptr, token, endLoc, diag.bundle.msg(mid)); 4374 } 4375 } 4376 4377 /// Returns true if x is in a list of TOK values. 4378 bool Any(Xs...)(TOK x) 4379 { 4380 return In(x, S2T!Xs); 4381 }