1 // Written in the D programming language 2 3 module dparse.parser; 4 5 import dparse.lexer; 6 import dparse.ast; 7 import std.experimental.allocator.mallocator; 8 import std.experimental.allocator; 9 import std.conv; 10 import std.algorithm; 11 import std.array; 12 import std.string : format; 13 14 // Uncomment this if you want ALL THE OUTPUT 15 // Caution: generates 180 megabytes of logging for std.datetime 16 //version = std_parser_verbose; 17 18 enum minimize_memory = true; 19 20 alias ParseAllocator = CAllocatorImpl!(Mallocator); 21 22 /** 23 * Params: 24 * tokens = the tokens parsed by dparse.lexer 25 * fileName = the name of the file being parsed 26 * messageFunction = a function to call on error or warning messages. 27 * The parameters are the file name, line number, column number, 28 * the error or warning message, and a boolean (true means error, false 29 * means warning). 30 * Returns: the parsed module 31 */ 32 Module parseModule(const(Token)[] tokens, string fileName, IAllocator allocator = null, 33 void function(string, size_t, size_t, string, bool) messageFunction = null, 34 uint* errorCount = null, uint* warningCount = null) 35 { 36 auto parser = new Parser(); 37 parser.fileName = fileName; 38 parser.tokens = tokens; 39 parser.messageFunction = messageFunction; 40 parser.allocator = allocator; 41 auto mod = parser.parseModule(); 42 if (warningCount !is null) 43 *warningCount = parser.warningCount; 44 if (errorCount !is null) 45 *errorCount = parser.errorCount; 46 return mod; 47 } 48 49 /** 50 * D Parser. 51 * 52 * It is sometimes useful to sub-class Parser to skip over things that are not 53 * interesting. For example, DCD skips over function bodies when caching symbols 54 * from imported files. 55 */ 56 class Parser 57 { 58 /** 59 * Parses an AddExpression. 60 * 61 * $(GRAMMAR $(RULEDEF addExpression): 62 * $(RULE mulExpression) 63 * | $(RULE addExpression) $(LPAREN)$(LITERAL '+') | $(LITERAL'-') | $(LITERAL'~')$(RPAREN) $(RULE mulExpression) 64 * ;) 65 */ 66 ExpressionNode parseAddExpression() 67 { 68 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 69 return parseLeftAssocBinaryExpression!(AddExpression, MulExpression, 70 tok!"+", tok!"-", tok!"~")(); 71 } 72 73 /** 74 * Parses an AliasDeclaration. 75 * 76 * $(GRAMMAR $(RULEDEF aliasDeclaration): 77 * $(LITERAL 'alias') $(RULE aliasInitializer) $(LPAREN)$(LITERAL ',') $(RULE aliasInitializer)$(RPAREN)* $(LITERAL ';') 78 * | $(LITERAL 'alias') $(RULE storageClass)* $(RULE type) $(LITERAL identifierList) $(LITERAL ';') 79 * ;) 80 */ 81 AliasDeclaration parseAliasDeclaration() 82 { 83 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 84 auto node = allocate!AliasDeclaration; 85 mixin(nullCheck!`expect(tok!"alias")`); 86 node.comment = comment; 87 comment = null; 88 node.line = current.line; 89 90 if (startsWith(tok!"identifier", tok!"=") || startsWith(tok!"identifier", tok!"(")) 91 { 92 AliasInitializer[] initializers; 93 do 94 { 95 auto initializer = parseAliasInitializer(); 96 mixin(nullCheck!`initializer`); 97 initializers ~= initializer; 98 if (currentIs(tok!",")) 99 advance(); 100 else 101 break; 102 } 103 while (moreTokens()); 104 node.initializers = ownArray(initializers); 105 } 106 else 107 { 108 StorageClass[] storageClasses; 109 while (moreTokens() && isStorageClass()) 110 storageClasses ~= parseStorageClass(); 111 if (storageClasses.length > 0) 112 node.storageClasses = ownArray(storageClasses); 113 /* 114 warn("Prefer the new \"'alias' identifier '=' type ';'\" syntax" 115 ~ " to the old \"'alias' type identifier ';'\" syntax"); 116 */ 117 mixin(nullCheck!`node.type = parseType()`); 118 if(startsWith(tok!"identifier", tok!"(")) { 119 // this is the insane 120 // alias int GetterType() @property; 121 // stuff... I just want to skip that shit. 122 mixin(nullCheck!`node.identifierList = parseIdentifierList()`); 123 while(!currentIs(tok!";")) 124 advance; 125 //parseFunctionDeclaration(); 126 127 } else 128 mixin(nullCheck!`node.identifierList = parseIdentifierList()`); 129 } 130 mixin(nullCheck!`expect(tok!";")`); 131 return node; 132 } 133 134 /** 135 * Parses an AliasInitializer. 136 * 137 * $(GRAMMAR $(RULEDEF aliasInitializer): 138 * $(LITERAL Identifier) $(RULE templateParameters)? $(LITERAL '=') $(RULE storageClass)* $(RULE type) 139 * ;) 140 */ 141 AliasInitializer parseAliasInitializer() 142 { 143 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 144 auto node = allocate!AliasInitializer; 145 const i = expect(tok!"identifier"); 146 mixin(nullCheck!`i`); 147 node.name = *i; 148 if (currentIs(tok!"(")) 149 mixin(nullCheck!`node.templateParameters = parseTemplateParameters()`); 150 mixin(nullCheck!`expect(tok!"=")`); 151 StorageClass[] storageClasses; 152 while (moreTokens() && isStorageClass()) 153 storageClasses ~= parseStorageClass(); 154 if (storageClasses.length > 0) 155 node.storageClasses = ownArray(storageClasses); 156 mixin(nullCheck!`node.type = parseType()`); 157 return node; 158 } 159 160 /** 161 * Parses an AliasThisDeclaration. 162 * 163 * $(GRAMMAR $(RULEDEF aliasThisDeclaration): 164 * $(LITERAL 'alias') $(LITERAL Identifier) $(LITERAL 'this') $(LITERAL ';') 165 * ;) 166 */ 167 AliasThisDeclaration parseAliasThisDeclaration() 168 { 169 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 170 auto node = allocate!AliasThisDeclaration; 171 node.comment = comment; 172 comment = null; 173 mixin(nullCheck!`expect(tok!"alias")`); 174 const ident = expect(tok!"identifier"); 175 mixin(nullCheck!`ident`); 176 node.identifier = *ident; 177 mixin(nullCheck!`expect(tok!"this")`); 178 mixin(nullCheck!`expect(tok!";")`); 179 return node; 180 } 181 182 /** 183 * Parses an AlignAttribute. 184 * 185 * $(GRAMMAR $(RULEDEF alignAttribute): 186 * $(LITERAL 'align') ($(LITERAL '$(LPAREN)') $(LITERAL IntegerLiteral) $(LITERAL '$(RPAREN)'))? 187 * ;) 188 */ 189 AlignAttribute parseAlignAttribute() 190 { 191 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 192 auto node = allocate!AlignAttribute; 193 expect(tok!"align"); 194 if (currentIs(tok!"(")) 195 { 196 mixin(nullCheck!`expect(tok!"(")`); 197 const intLit = expect(tok!"intLiteral"); 198 mixin(nullCheck!`intLit`); 199 node.intLiteral = *intLit; 200 mixin(nullCheck!`expect(tok!")")`); 201 } 202 return node; 203 } 204 205 /** 206 * Parses an AndAndExpression. 207 * 208 * $(GRAMMAR $(RULEDEF andAndExpression): 209 * $(RULE orExpression) 210 * | $(RULE andAndExpression) $(LITERAL '&&') $(RULE orExpression) 211 * ;) 212 */ 213 ExpressionNode parseAndAndExpression() 214 { 215 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 216 return parseLeftAssocBinaryExpression!(AndAndExpression, OrExpression, 217 tok!"&&")(); 218 } 219 220 /** 221 * Parses an AndExpression. 222 * 223 * $(GRAMMAR $(RULEDEF andExpression): 224 * $(RULE cmpExpression) 225 * | $(RULE andExpression) $(LITERAL '&') $(RULE cmpExpression) 226 * ;) 227 */ 228 ExpressionNode parseAndExpression() 229 { 230 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 231 return parseLeftAssocBinaryExpression!(AndExpression, CmpExpression, 232 tok!"&")(); 233 } 234 235 /** 236 * Parses an ArgumentList. 237 * 238 * $(GRAMMAR $(RULEDEF argumentList): 239 * $(RULE assignExpression) ($(LITERAL ',') $(RULE assignExpression)?)* 240 * ;) 241 */ 242 ArgumentList parseArgumentList() 243 { 244 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 245 if (!moreTokens) 246 { 247 error("argument list expected instead of EOF"); 248 return null; 249 } 250 size_t startLocation = current().index; 251 auto node = parseCommaSeparatedRule!(ArgumentList, AssignExpression)(true); 252 mixin(nullCheck!`node`); 253 node.startLocation = startLocation; 254 if (moreTokens) node.endLocation = current().index; 255 return node; 256 } 257 258 /** 259 * Parses Arguments. 260 * 261 * $(GRAMMAR $(RULEDEF arguments): 262 * $(LITERAL '$(LPAREN)') $(RULE argumentList)? $(LITERAL '$(RPAREN)') 263 * ;) 264 */ 265 Arguments parseArguments() 266 { 267 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 268 auto node = allocate!Arguments; 269 mixin(nullCheck!`expect(tok!"(")`); 270 if (!currentIs(tok!")")) 271 mixin(nullCheck!`node.argumentList = parseArgumentList()`); 272 mixin(nullCheck!`expect(tok!")")`); 273 return node; 274 } 275 276 /** 277 * Parses an ArrayInitializer. 278 * 279 * $(GRAMMAR $(RULEDEF arrayInitializer): 280 * $(LITERAL '[') $(LITERAL ']') 281 * | $(LITERAL '[') $(RULE arrayMemberInitialization) ($(LITERAL ',') $(RULE arrayMemberInitialization)?)* $(LITERAL ']') 282 * ;) 283 */ 284 ArrayInitializer parseArrayInitializer() 285 { 286 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 287 auto node = allocate!ArrayInitializer; 288 const open = expect(tok!"["); 289 mixin(nullCheck!`open`); 290 node.startLocation = open.index; 291 ArrayMemberInitialization[] arrayMemberInitializations; 292 while (moreTokens()) 293 { 294 if (currentIs(tok!"]")) 295 break; 296 arrayMemberInitializations ~= parseArrayMemberInitialization(); 297 if (currentIs(tok!",")) 298 advance(); 299 else 300 break; 301 } 302 node.arrayMemberInitializations = ownArray(arrayMemberInitializations); 303 const close = expect(tok!"]"); 304 mixin(nullCheck!`close`); 305 node.endLocation = close.index; 306 return node; 307 } 308 309 /** 310 * Parses an ArrayLiteral. 311 * 312 * $(GRAMMAR $(RULEDEF arrayLiteral): 313 * $(LITERAL '[') $(RULE argumentList)? $(LITERAL ']') 314 * ;) 315 */ 316 ArrayLiteral parseArrayLiteral() 317 { 318 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 319 auto node = allocate!ArrayLiteral; 320 mixin(nullCheck!`expect(tok!"[")`); 321 if (!currentIs(tok!"]")) 322 mixin(nullCheck!`node.argumentList = parseArgumentList()`); 323 mixin(nullCheck!`expect(tok!"]")`); 324 return node; 325 } 326 327 /** 328 * Parses an ArrayMemberInitialization. 329 * 330 * $(GRAMMAR $(RULEDEF arrayMemberInitialization): 331 * ($(RULE assignExpression) $(LITERAL ':'))? $(RULE nonVoidInitializer) 332 * ;) 333 */ 334 ArrayMemberInitialization parseArrayMemberInitialization() 335 { 336 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 337 auto node = allocate!ArrayMemberInitialization; 338 switch (current.type) 339 { 340 case tok!"[": 341 auto b = setBookmark(); 342 skipBrackets(); 343 if (currentIs(tok!":")) 344 { 345 mixin(nullCheck!`node.assignExpression = parseAssignExpression()`); 346 advance(); // : 347 mixin(nullCheck!`node.nonVoidInitializer`); 348 break; 349 } 350 else 351 { 352 goToBookmark(b); 353 goto case; 354 } 355 case tok!"{": 356 mixin(nullCheck!`node.nonVoidInitializer = parseNonVoidInitializer()`); 357 break; 358 default: 359 auto assignExpression = parseAssignExpression(); 360 mixin(nullCheck!`assignExpression`); 361 if (currentIs(tok!":")) 362 { 363 node.assignExpression = assignExpression; 364 advance(); 365 mixin(nullCheck!`node.nonVoidInitializer = parseNonVoidInitializer()`); 366 } 367 else 368 { 369 node.nonVoidInitializer = allocate!NonVoidInitializer; 370 node.nonVoidInitializer.assignExpression = assignExpression; 371 } 372 } 373 return node; 374 } 375 376 /** 377 * Parses an AsmAddExp 378 * 379 * $(GRAMMAR $(RULEDEF asmAddExp): 380 * $(RULE asmMulExp) 381 * | $(RULE asmAddExp) ($(LITERAL '+') | $(LITERAL '-')) $(RULE asmMulExp) 382 * ;) 383 */ 384 ExpressionNode parseAsmAddExp() 385 { 386 mixin(traceEnterAndExit!(__FUNCTION__)); 387 return parseLeftAssocBinaryExpression!(AsmAddExp, AsmMulExp, 388 tok!"+", tok!"-")(); 389 } 390 391 /** 392 * Parses an AsmAndExp 393 * 394 * $(GRAMMAR $(RULEDEF asmAndExp): 395 * $(RULE asmEqualExp) 396 * | $(RULE asmAndExp) $(LITERAL '&') $(RULE asmEqualExp) 397 * ;) 398 */ 399 ExpressionNode parseAsmAndExp() 400 { 401 mixin(traceEnterAndExit!(__FUNCTION__)); 402 return parseLeftAssocBinaryExpression!(AsmAndExp, AsmEqualExp, tok!"&"); 403 } 404 405 /** 406 * Parses an AsmBrExp 407 * 408 * $(GRAMMAR $(RULEDEF asmBrExp): 409 * $(RULE asmUnaExp) 410 * | $(RULE asmBrExp)? $(LITERAL '[') $(RULE asmExp) $(LITERAL ']') 411 * ;) 412 */ 413 AsmBrExp parseAsmBrExp() 414 { 415 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 416 AsmBrExp node = allocate!AsmBrExp(); 417 size_t line = current.line; 418 size_t column = current.column; 419 if (currentIs(tok!"[")) 420 { 421 advance(); // [ 422 mixin(nullCheck!`node.asmExp = parseAsmExp()`); 423 mixin(nullCheck!`expect(tok!"]")`); 424 if (currentIs(tok!"[")) 425 goto brLoop; 426 } 427 else 428 { 429 mixin(nullCheck!`node.asmUnaExp = parseAsmUnaExp()`); 430 brLoop: while (currentIs(tok!"[")) 431 { 432 AsmBrExp br = allocate!AsmBrExp(); // huehuehuehue 433 br.asmBrExp = node; 434 br.line = current().line; 435 br.column = current().column; 436 node = br; 437 node.line = line; 438 node.column = column; 439 advance(); // [ 440 mixin(nullCheck!`node.asmExp = parseAsmExp()`); 441 mixin(nullCheck!`expect(tok!"]")`); 442 } 443 } 444 return node; 445 } 446 447 /** 448 * Parses an AsmEqualExp 449 * 450 * $(GRAMMAR $(RULEDEF asmEqualExp): 451 * $(RULE asmRelExp) 452 * | $(RULE asmEqualExp) ('==' | '!=') $(RULE asmRelExp) 453 * ;) 454 */ 455 ExpressionNode parseAsmEqualExp() 456 { 457 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 458 return parseLeftAssocBinaryExpression!(AsmEqualExp, AsmRelExp, tok!"==", tok!"!=")(); 459 } 460 461 /** 462 * Parses an AsmExp 463 * 464 * $(GRAMMAR $(RULEDEF asmExp): 465 * $(RULE asmLogOrExp) ($(LITERAL '?') $(RULE asmExp) $(LITERAL ':') $(RULE asmExp))? 466 * ;) 467 */ 468 ExpressionNode parseAsmExp() 469 { 470 mixin(traceEnterAndExit!(__FUNCTION__)); 471 AsmExp node = allocate!AsmExp; 472 mixin(nullCheck!`node.left = parseAsmLogOrExp()`); 473 if (currentIs(tok!"?")) 474 { 475 advance(); 476 mixin(nullCheck!`(node.middle = parseAsmExp())`); 477 mixin(nullCheck!`expect(tok!":")`); 478 mixin(nullCheck!`(node.right = parseAsmExp())`); 479 } 480 return node; 481 } 482 483 /** 484 * Parses an AsmInstruction 485 * 486 * $(GRAMMAR $(RULEDEF asmInstruction): 487 * $(LITERAL Identifier) 488 * | $(LITERAL 'align') $(LITERAL IntegerLiteral) 489 * | $(LITERAL 'align') $(LITERAL Identifier) 490 * | $(LITERAL Identifier) $(LITERAL ':') $(RULE asmInstruction) 491 * | $(LITERAL Identifier) $(RULE operands) 492 * | $(LITERAL 'in') $(RULE operands) 493 * | $(LITERAL 'out') $(RULE operands) 494 * | $(LITERAL 'int') $(RULE operands) 495 * ;) 496 */ 497 AsmInstruction parseAsmInstruction() 498 { 499 import std.range : assumeSorted; 500 mixin(traceEnterAndExit!(__FUNCTION__)); 501 AsmInstruction node = allocate!AsmInstruction; 502 if (currentIs(tok!"align")) 503 { 504 advance(); // align 505 node.hasAlign = true; 506 if (currentIsOneOf(tok!"intLiteral", tok!"identifier")) 507 node.identifierOrIntegerOrOpcode = advance(); 508 else 509 error("Identifier or integer literal expected."); 510 } 511 else if (currentIsOneOf(tok!"identifier", tok!"in", tok!"out", tok!"int")) 512 { 513 node.identifierOrIntegerOrOpcode = advance(); 514 if (node.identifierOrIntegerOrOpcode == tok!"identifier" && currentIs(tok!":")) 515 { 516 advance(); // : 517 mixin(nullCheck!`node.asmInstruction = parseAsmInstruction()`); 518 } 519 else if (!currentIs(tok!";")) 520 mixin(nullCheck!`node.operands = parseOperands()`); 521 } 522 return node; 523 } 524 525 /** 526 * Parses an AsmLogAndExp 527 * 528 * $(GRAMMAR $(RULEDEF asmLogAndExp): 529 * $(RULE asmOrExp) 530 * $(RULE asmLogAndExp) $(LITERAL '&&') $(RULE asmOrExp) 531 * ;) 532 */ 533 ExpressionNode parseAsmLogAndExp() 534 { 535 mixin(traceEnterAndExit!(__FUNCTION__)); 536 return parseLeftAssocBinaryExpression!(AsmLogAndExp, AsmOrExp, tok!"&&"); 537 } 538 539 /** 540 * Parses an AsmLogOrExp 541 * 542 * $(GRAMMAR $(RULEDEF asmLogOrExp): 543 * $(RULE asmLogAndExp) 544 * | $(RULE asmLogOrExp) '||' $(RULE asmLogAndExp) 545 * ;) 546 */ 547 ExpressionNode parseAsmLogOrExp() 548 { 549 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 550 return parseLeftAssocBinaryExpression!(AsmLogOrExp, AsmLogAndExp, tok!"||")(); 551 } 552 553 /** 554 * Parses an AsmMulExp 555 * 556 * $(GRAMMAR $(RULEDEF asmMulExp): 557 * $(RULE asmBrExp) 558 * | $(RULE asmMulExp) ($(LITERAL '*') | $(LITERAL '/') | $(LITERAL '%')) $(RULE asmBrExp) 559 * ;) 560 */ 561 ExpressionNode parseAsmMulExp() 562 { 563 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 564 return parseLeftAssocBinaryExpression!(AsmMulExp, AsmBrExp, tok!"*", tok!"/", tok!"%")(); 565 } 566 567 /** 568 * Parses an AsmOrExp 569 * 570 * $(GRAMMAR $(RULEDEF asmOrExp): 571 * $(RULE asmXorExp) 572 * | $(RULE asmOrExp) $(LITERAL '|') $(RULE asmXorExp) 573 * ;) 574 */ 575 ExpressionNode parseAsmOrExp() 576 { 577 mixin(traceEnterAndExit!(__FUNCTION__)); 578 return parseLeftAssocBinaryExpression!(AsmOrExp, AsmXorExp, tok!"|")(); 579 } 580 581 /** 582 * Parses an AsmPrimaryExp 583 * 584 * $(GRAMMAR $(RULEDEF asmPrimaryExp): 585 * $(LITERAL IntegerLiteral) 586 * | $(LITERAL FloatLiteral) 587 * | $(LITERAL StringLiteral) 588 * | $(RULE register) 589 * | $(RULE identifierChain) 590 * | $(LITERAL '$') 591 * ;) 592 */ 593 AsmPrimaryExp parseAsmPrimaryExp() 594 { 595 import std.range : assumeSorted; 596 mixin(traceEnterAndExit!(__FUNCTION__)); 597 AsmPrimaryExp node = allocate!AsmPrimaryExp(); 598 switch (current().type) 599 { 600 case tok!"doubleLiteral": 601 case tok!"floatLiteral": 602 case tok!"intLiteral": 603 case tok!"longLiteral": 604 case tok!"stringLiteral": 605 case tok!"$": 606 node.token = advance(); 607 break; 608 case tok!"identifier": 609 if (assumeSorted(REGISTER_NAMES).equalRange(current().text).length > 0) 610 { 611 trace("Found register"); 612 mixin(nullCheck!`(node.register = parseRegister())`); 613 } 614 else 615 mixin(nullCheck!`node.identifierChain = parseIdentifierChain()`); 616 break; 617 default: 618 error("Float literal, integer literal, $, or identifier expected."); 619 return null; 620 } 621 return node; 622 } 623 624 /** 625 * Parses an AsmRelExp 626 * 627 * $(GRAMMAR $(RULEDEF asmRelExp): 628 * $(RULE asmShiftExp) 629 * | $(RULE asmRelExp) (($(LITERAL '<') | $(LITERAL '<=') | $(LITERAL '>') | $(LITERAL '>=')) $(RULE asmShiftExp))? 630 * ;) 631 */ 632 ExpressionNode parseAsmRelExp() 633 { 634 mixin(traceEnterAndExit!(__FUNCTION__)); 635 return parseLeftAssocBinaryExpression!(AsmRelExp, AsmShiftExp, tok!"<", 636 tok!"<=", tok!">", tok!">=")(); 637 } 638 639 /** 640 * Parses an AsmShiftExp 641 * 642 * $(GRAMMAR $(RULEDEF asmShiftExp): 643 * $(RULE asmAddExp) 644 * $(RULE asmShiftExp) ($(LITERAL '<<') | $(LITERAL '>>') | $(LITERAL '>>>')) $(RULE asmAddExp) 645 * ;) 646 */ 647 ExpressionNode parseAsmShiftExp() 648 { 649 mixin(traceEnterAndExit!(__FUNCTION__)); 650 return parseLeftAssocBinaryExpression!(AsmShiftExp, AsmAddExp, tok!"<<", 651 tok!">>", tok!">>>"); 652 } 653 654 /** 655 * Parses an AsmStatement 656 * 657 * $(GRAMMAR $(RULEDEF asmStatement): 658 * $(LITERAL 'asm') $(RULE functionAttributes)? $(LITERAL '{') $(RULE asmInstruction)+ $(LITERAL '}') 659 * ;) 660 */ 661 AsmStatement parseAsmStatement() 662 { 663 mixin(traceEnterAndExit!(__FUNCTION__)); 664 AsmStatement node = allocate!AsmStatement; 665 AsmInstruction[] instructions; 666 advance(); // asm 667 FunctionAttribute[] functionAttributes; 668 while (isAttribute()) 669 { 670 auto attr = parseFunctionAttribute(); 671 if (attr is null) 672 { 673 error("Function attribute or '{' expected"); 674 return null; 675 } 676 functionAttributes ~= attr; 677 } 678 node.functionAttributes = ownArray(functionAttributes); 679 advance(); // { 680 while (moreTokens() && !currentIs(tok!"}")) 681 { 682 AsmInstruction instruction = parseAsmInstruction(); 683 if (instruction is null) 684 return null; 685 if (!expect(tok!";")) 686 return null; 687 instructions ~= instruction; 688 } 689 node.asmInstructions = ownArray(instructions); 690 expect(tok!"}"); 691 return node; 692 } 693 694 /** 695 * Parses an AsmTypePrefix 696 * 697 * Note that in the following grammar definition the first identifier must 698 * be "near", "far", "word", "dword", or "qword". The second identifier must 699 * be "ptr". 700 * 701 * $(GRAMMAR $(RULEDEF asmTypePrefix): 702 * $(LITERAL Identifier) $(LITERAL Identifier)? 703 * | $(LITERAL 'byte') $(LITERAL Identifier)? 704 * | $(LITERAL 'short') $(LITERAL Identifier)? 705 * | $(LITERAL 'int') $(LITERAL Identifier)? 706 * | $(LITERAL 'float') $(LITERAL Identifier)? 707 * | $(LITERAL 'double') $(LITERAL Identifier)? 708 * | $(LITERAL 'real') $(LITERAL Identifier)? 709 * ;) 710 */ 711 AsmTypePrefix parseAsmTypePrefix() 712 { 713 mixin(traceEnterAndExit!(__FUNCTION__)); 714 switch (current().type) 715 { 716 case tok!"identifier": 717 case tok!"byte": 718 case tok!"short": 719 case tok!"int": 720 case tok!"float": 721 case tok!"double": 722 case tok!"real": 723 AsmTypePrefix prefix = allocate!AsmTypePrefix(); 724 prefix.left = advance(); 725 if (prefix.left.type == tok!"identifier") switch (prefix.left.text) 726 { 727 case "near": 728 case "far": 729 case "word": 730 case "dword": 731 case "qword": 732 break; 733 default: 734 error("ASM type prefix expected"); 735 return null; 736 } 737 if (currentIs(tok!"identifier") && current().text == "ptr") 738 prefix.right = advance(); 739 return prefix; 740 default: 741 error("Expected an identifier, 'byte', 'short', 'int', 'float', 'double', or 'real'"); 742 return null; 743 } 744 } 745 746 /** 747 * Parses an AsmUnaExp 748 * 749 * $(GRAMMAR $(RULEDEF asmUnaExp): 750 * $(RULE asmTypePrefix) $(RULE asmExp) 751 * | $(LITERAL Identifier) $(RULE asmExp) 752 * | $(LITERAL '+') $(RULE asmUnaExp) 753 * | $(LITERAL '-') $(RULE asmUnaExp) 754 * | $(LITERAL '!') $(RULE asmUnaExp) 755 * | $(LITERAL '~') $(RULE asmUnaExp) 756 * | $(RULE asmPrimaryExp) 757 * ;) 758 */ 759 AsmUnaExp parseAsmUnaExp() 760 { 761 mixin(traceEnterAndExit!(__FUNCTION__)); 762 AsmUnaExp node = allocate!AsmUnaExp(); 763 switch (current().type) 764 { 765 case tok!"+": 766 case tok!"-": 767 case tok!"!": 768 case tok!"~": 769 node.prefix = advance(); 770 mixin(nullCheck!`node.asmUnaExp = parseAsmUnaExp()`); 771 break; 772 case tok!"byte": 773 case tok!"short": 774 case tok!"int": 775 case tok!"float": 776 case tok!"double": 777 case tok!"real": 778 typePrefix: 779 mixin(nullCheck!`node.asmTypePrefix = parseAsmTypePrefix()`); 780 mixin(nullCheck!`node.asmExp = parseAsmExp()`); 781 break; 782 case tok!"identifier": 783 switch (current().text) 784 { 785 case "offsetof": 786 case "seg": 787 node.prefix = advance(); 788 mixin(nullCheck!`node.asmExp = parseAsmExp()`); 789 break; 790 case "near": 791 case "far": 792 case "word": 793 case "dword": 794 case "qword": 795 goto typePrefix; 796 default: 797 goto outerDefault; 798 } 799 break; 800 outerDefault: 801 default: 802 mixin(nullCheck!`node.asmPrimaryExp = parseAsmPrimaryExp()`); 803 break; 804 } 805 return node; 806 } 807 808 /** 809 * Parses an AsmXorExp 810 * 811 * $(GRAMMAR $(RULEDEF asmXorExp): 812 * $(RULE asmAndExp) 813 * | $(RULE asmXorExp) $(LITERAL '^') $(RULE asmAndExp) 814 * ;) 815 */ 816 ExpressionNode parseAsmXorExp() 817 { 818 mixin(traceEnterAndExit!(__FUNCTION__)); 819 return parseLeftAssocBinaryExpression!(AsmXorExp, AsmAndExp, tok!"^")(); 820 } 821 822 /** 823 * Parses an AssertExpression 824 * 825 * $(GRAMMAR $(RULEDEF assertExpression): 826 * $(LITERAL 'assert') $(LITERAL '$(LPAREN)') $(RULE assignExpression) ($(LITERAL ',') $(RULE assignExpression))? $(LITERAL '$(RPAREN)') 827 * ;) 828 */ 829 AssertExpression parseAssertExpression() 830 { 831 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 832 auto node = allocate!AssertExpression; 833 node.line = current.line; 834 node.column = current.column; 835 advance(); // "assert" 836 mixin(nullCheck!`expect(tok!"(")`); 837 mixin(nullCheck!`node.assertion = parseAssignExpression()`); 838 if (currentIs(tok!",")) 839 { 840 advance(); 841 mixin(nullCheck!`node.message = parseAssignExpression()`); 842 } 843 mixin(nullCheck!`expect(tok!")")`); 844 return node; 845 } 846 847 /** 848 * Parses an AssignExpression 849 * 850 * $(GRAMMAR $(RULEDEF assignExpression): 851 * $(RULE ternaryExpression) ($(RULE assignOperator) $(RULE expression))? 852 * ; 853 *$(RULEDEF assignOperator): 854 * $(LITERAL '=') 855 * | $(LITERAL '>>>=') 856 * | $(LITERAL '>>=') 857 * | $(LITERAL '<<=') 858 * | $(LITERAL '+=') 859 * | $(LITERAL '-=') 860 * | $(LITERAL '*=') 861 * | $(LITERAL '%=') 862 * | $(LITERAL '&=') 863 * | $(LITERAL '/=') 864 * | $(LITERAL '|=') 865 * | $(LITERAL '^^=') 866 * | $(LITERAL '^=') 867 * | $(LITERAL '~=') 868 * ;) 869 */ 870 ExpressionNode parseAssignExpression() 871 { 872 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 873 if (!moreTokens) 874 { 875 error("Assign expression expected instead of EOF"); 876 return null; 877 } 878 auto ternary = parseTernaryExpression(); 879 if (ternary is null) 880 return null; 881 if (currentIsOneOf(tok!"=", tok!">>>=", 882 tok!">>=", tok!"<<=", 883 tok!"+=", tok!"-=", tok!"*=", 884 tok!"%=", tok!"&=", tok!"/=", 885 tok!"|=", tok!"^^=", tok!"^=", 886 tok!"~=")) 887 { 888 auto node = allocate!AssignExpression; 889 node.line = current().line; 890 node.column = current().column; 891 node.ternaryExpression = ternary; 892 node.operator = advance().type; 893 mixin(nullCheck!`node.expression = parseExpression()`); 894 return node; 895 } 896 return ternary; 897 } 898 899 /** 900 * Parses an AssocArrayLiteral 901 * 902 * $(GRAMMAR $(RULEDEF assocArrayLiteral): 903 * $(LITERAL '[') $(RULE keyValuePairs) $(LITERAL ']') 904 * ;) 905 */ 906 AssocArrayLiteral parseAssocArrayLiteral() 907 { 908 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 909 mixin(simpleParse!(AssocArrayLiteral, tok!"[", 910 "keyValuePairs|parseKeyValuePairs", tok!"]")); 911 } 912 913 /** 914 * Parses an AtAttribute 915 * 916 * $(GRAMMAR $(RULEDEF atAttribute): 917 * $(LITERAL '@') $(LITERAL Identifier) 918 * | $(LITERAL '@') $(LITERAL Identifier) $(LITERAL '$(LPAREN)') $(RULE argumentList)? $(LITERAL '$(RPAREN)') 919 * | $(LITERAL '@') $(LITERAL '$(LPAREN)') $(RULE argumentList) $(LITERAL '$(RPAREN)') 920 * ;) 921 */ 922 AtAttribute parseAtAttribute() 923 { 924 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 925 auto node = allocate!AtAttribute; 926 const start = expect(tok!"@"); 927 mixin(nullCheck!`start`); 928 if (!moreTokens) 929 { 930 error(`"(", or identifier expected`); 931 return null; 932 } 933 node.startLocation = start.index; 934 935 if(currentIs(tok!"(")) { 936 advance(); 937 mixin(nullCheck!`node.argumentList = parseArgumentList()`); 938 expect(tok!")"); 939 } else { 940 if(currentIs(tok!"identifier")) { 941 node.argumentList = new ArgumentList; 942 ExpressionNode wtf = parseUnaryExpression(); 943 node.argumentList.items ~= wtf; 944 945 //mixin(nullCheck!`node.argumentList = parseArgumentList()`); 946 } else 947 error("( or identifier expected"); 948 } 949 950 // I don't think any of this following spam is necessary and I know it isn't correct, let's just use this one thing and see how it goes 951 version(none) 952 switch (current.type) 953 { 954 case tok!"identifier": 955 node.identifier = advance(); 956 if (currentIs(tok!"(")) 957 { 958 advance(); // ( 959 if (!currentIs(tok!")")) 960 mixin(nullCheck!`node.argumentList = parseArgumentList()`); 961 expect(tok!")"); 962 } else if(currentIs(tok!("!"))) 963 { 964 advance(); // ! 965 advance(); 966 mixin(nullCheck!`node.argumentList = parseArgumentList()`); 967 expect(tok!")"); 968 969 } 970 break; 971 case tok!"(": 972 advance(); 973 mixin(nullCheck!`node.argumentList = parseArgumentList()`); 974 expect(tok!")"); 975 break; 976 default: 977 error(`"(", or identifier expected`); 978 return null; 979 } 980 if (moreTokens) node.endLocation = current().index; 981 return node; 982 } 983 984 /** 985 * Parses an Attribute 986 * 987 * $(GRAMMAR $(RULEDEF attribute): 988 * | $(RULE pragmaExpression) 989 * | $(RULE alignAttribute) 990 * | $(RULE deprecated) 991 * | $(RULE atAttribute) 992 * | $(RULE linkageAttribute) 993 * | $(LITERAL 'export') 994 * | $(LITERAL 'package') 995 * | $(LITERAL 'private') 996 * | $(LITERAL 'protected') 997 * | $(LITERAL 'public') 998 * | $(LITERAL 'static') 999 * | $(LITERAL 'extern') 1000 * | $(LITERAL 'abstract') 1001 * | $(LITERAL 'final') 1002 * | $(LITERAL 'override') 1003 * | $(LITERAL 'synchronized') 1004 * | $(LITERAL 'auto') 1005 * | $(LITERAL 'scope') 1006 * | $(LITERAL 'const') 1007 * | $(LITERAL 'immutable') 1008 * | $(LITERAL 'inout') 1009 * | $(LITERAL 'shared') 1010 * | $(LITERAL '__gshared') 1011 * | $(LITERAL 'nothrow') 1012 * | $(LITERAL 'pure') 1013 * | $(LITERAL 'ref') 1014 * ;) 1015 */ 1016 Attribute parseAttribute() 1017 { 1018 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1019 auto node = allocate!Attribute; 1020 switch (current.type) 1021 { 1022 case tok!"pragma": 1023 mixin(nullCheck!`node.pragmaExpression = parsePragmaExpression()`); 1024 break; 1025 case tok!"deprecated": 1026 mixin(nullCheck!`node.deprecated_ = parseDeprecated()`); 1027 break; 1028 case tok!"align": 1029 mixin(nullCheck!`node.alignAttribute = parseAlignAttribute()`); 1030 break; 1031 case tok!"@": 1032 mixin(nullCheck!`node.atAttribute = parseAtAttribute()`); 1033 break; 1034 case tok!"extern": 1035 if (peekIs(tok!"(")) 1036 { 1037 mixin(nullCheck!`node.linkageAttribute = parseLinkageAttribute()`); 1038 break; 1039 } 1040 else 1041 goto case; 1042 case tok!"package": 1043 node.attribute = advance(); 1044 if (currentIs(tok!"(")) 1045 { 1046 expect(tok!"("); 1047 mixin(nullCheck!`node.identifierChain = parseIdentifierChain()`); 1048 expect(tok!")"); 1049 } 1050 break; 1051 case tok!"private": 1052 case tok!"protected": 1053 case tok!"public": 1054 case tok!"export": 1055 case tok!"static": 1056 case tok!"abstract": 1057 case tok!"final": 1058 case tok!"override": 1059 case tok!"synchronized": 1060 case tok!"auto": 1061 case tok!"scope": 1062 case tok!"const": 1063 case tok!"immutable": 1064 case tok!"inout": 1065 case tok!"shared": 1066 case tok!"__gshared": 1067 case tok!"nothrow": 1068 case tok!"pure": 1069 case tok!"ref": 1070 node.attribute = advance(); 1071 break; 1072 default: 1073 deallocate(node); 1074 return null; 1075 } 1076 return node; 1077 } 1078 1079 /** 1080 * Parses an AttributeDeclaration 1081 * 1082 * $(GRAMMAR $(RULEDEF attributeDeclaration): 1083 * $(RULE attribute) $(LITERAL ':') 1084 * ;) 1085 */ 1086 AttributeDeclaration parseAttributeDeclaration(Attribute attribute = null) 1087 { 1088 auto node = allocate!AttributeDeclaration; 1089 node.line = current.line; 1090 node.attribute = attribute is null ? parseAttribute() : attribute; 1091 expect(tok!":"); 1092 return node; 1093 } 1094 1095 /** 1096 * Parses an AutoDeclaration 1097 * 1098 * $(GRAMMAR $(RULEDEF autoDeclaration): 1099 * $(RULE storageClass)+ $(LITERAL Identifier) $(LITERAL '=') $(RULE initializer) ($(LITERAL ',') $(LITERAL Identifier) $(LITERAL '=') $(RULE initializer))* $(LITERAL ';') 1100 * ;) 1101 */ 1102 AutoDeclaration parseAutoDeclaration() 1103 { 1104 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1105 auto node = allocate!AutoDeclaration; 1106 node.comment = comment; 1107 comment = null; 1108 StorageClass[] storageClasses; 1109 while (isStorageClass()) 1110 { 1111 auto s = parseStorageClass(); 1112 mixin(nullCheck!`s`); 1113 storageClasses ~= s; 1114 } 1115 node.storageClasses = ownArray(storageClasses); 1116 Token[] identifiers; 1117 Initializer[] initializers; 1118 do 1119 { 1120 const ident = expect(tok!"identifier"); 1121 mixin(nullCheck!`ident`); 1122 identifiers ~= *ident; 1123 mixin(nullCheck!`expect(tok!"=")`); 1124 auto init = parseInitializer(); 1125 mixin(nullCheck!`init`); 1126 initializers ~= init; 1127 if (currentIs(tok!",")) 1128 advance(); 1129 else 1130 break; 1131 } while (moreTokens()); 1132 node.identifiers = ownArray(identifiers); 1133 node.initializers = ownArray(initializers); 1134 auto semicolon = expect(tok!";"); 1135 if(semicolon !is null) 1136 node.comment ~= semicolon.trailingComment; 1137 return node; 1138 } 1139 1140 /** 1141 * Parses a BlockStatement 1142 * 1143 * $(GRAMMAR $(RULEDEF blockStatement): 1144 * $(LITERAL '{') $(RULE declarationsAndStatements)? $(LITERAL '}') 1145 * ;) 1146 */ 1147 BlockStatement parseBlockStatement() 1148 { 1149 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1150 auto node = allocate!BlockStatement; 1151 const openBrace = expect(tok!"{"); 1152 mixin(nullCheck!`openBrace`); 1153 node.startLocation = openBrace.index; 1154 if (!currentIs(tok!"}")) 1155 { 1156 mixin(nullCheck!`node.declarationsAndStatements = parseDeclarationsAndStatements()`); 1157 } 1158 const closeBrace = expect(tok!"}"); 1159 if (closeBrace !is null) 1160 node.endLocation = closeBrace.index; 1161 else 1162 { 1163 //import std.stdio; writeln(node.startLocation); 1164 //assert(0); 1165 trace("Could not find end of block statement."); 1166 node.endLocation = size_t.max; 1167 } 1168 1169 return node; 1170 } 1171 1172 /** 1173 * Parses a BodyStatement 1174 * 1175 * $(GRAMMAR $(RULEDEF bodyStatement): 1176 * $(LITERAL 'body') $(RULE blockStatement) 1177 * ;) 1178 */ 1179 BodyStatement parseBodyStatement() 1180 { 1181 advance(); 1182 hackFunctionBody(); 1183 return new BodyStatement(); 1184 1185 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1186 mixin(simpleParse!(BodyStatement, tok!"identifier", // was tok!"body" 1187 "blockStatement|parseBlockStatement")); 1188 } 1189 1190 BodyStatement parseBodyDoStatement() 1191 { 1192 advance(); 1193 hackFunctionBody(); 1194 return new BodyStatement; 1195 1196 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1197 mixin(simpleParse!(BodyStatement, tok!"do", 1198 "blockStatement|parseBlockStatement")); 1199 } 1200 1201 void hackFunctionBody() { 1202 int braceCount = 1; 1203 assert(currentIs(tok!"{")); 1204 advance(); 1205 while(braceCount > 0) { 1206 if(currentIs(tok!"{")) 1207 braceCount++; 1208 else if(currentIs(tok!"}")) 1209 braceCount--; 1210 advance(); 1211 } 1212 } 1213 1214 /** 1215 * Parses a BreakStatement 1216 * 1217 * $(GRAMMAR $(RULEDEF breakStatement): 1218 * $(LITERAL 'break') $(LITERAL Identifier)? $(LITERAL ';') 1219 * ;) 1220 */ 1221 BreakStatement parseBreakStatement() 1222 { 1223 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1224 expect(tok!"break"); 1225 auto node = allocate!BreakStatement; 1226 switch (current.type) 1227 { 1228 case tok!"identifier": 1229 node.label = advance(); 1230 mixin(nullCheck!`expect(tok!";")`); 1231 break; 1232 case tok!";": 1233 advance(); 1234 break; 1235 default: 1236 error("Identifier or semicolon expected following \"break\""); 1237 return null; 1238 } 1239 return node; 1240 } 1241 1242 /** 1243 * Parses a BaseClass 1244 * 1245 * $(GRAMMAR $(RULEDEF baseClass): 1246 * $(RULE type2) 1247 * ;) 1248 */ 1249 BaseClass parseBaseClass() 1250 { 1251 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1252 auto node = allocate!BaseClass; 1253 if (current.type.isProtection()) 1254 { 1255 warn("Use of base class protection is deprecated."); 1256 advance(); 1257 } 1258 if ((node.type2 = parseType2()) is null) 1259 { 1260 deallocate(node); 1261 return null; 1262 } 1263 return node; 1264 } 1265 1266 /** 1267 * Parses a BaseClassList 1268 * 1269 * $(GRAMMAR $(RULEDEF baseClassList): 1270 * $(RULE baseClass) ($(LITERAL ',') $(RULE baseClass))* 1271 * ;) 1272 */ 1273 BaseClassList parseBaseClassList() 1274 { 1275 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1276 return parseCommaSeparatedRule!(BaseClassList, BaseClass)(); 1277 } 1278 1279 /** 1280 * Parses an BuiltinType 1281 * 1282 * $(GRAMMAR $(RULEDEF builtinType): 1283 * $(LITERAL 'bool') 1284 * | $(LITERAL 'byte') 1285 * | $(LITERAL 'ubyte') 1286 * | $(LITERAL 'short') 1287 * | $(LITERAL 'ushort') 1288 * | $(LITERAL 'int') 1289 * | $(LITERAL 'uint') 1290 * | $(LITERAL 'long') 1291 * | $(LITERAL 'ulong') 1292 * | $(LITERAL 'char') 1293 * | $(LITERAL 'wchar') 1294 * | $(LITERAL 'dchar') 1295 * | $(LITERAL 'float') 1296 * | $(LITERAL 'double') 1297 * | $(LITERAL 'real') 1298 * | $(LITERAL 'ifloat') 1299 * | $(LITERAL 'idouble') 1300 * | $(LITERAL 'ireal') 1301 * | $(LITERAL 'cfloat') 1302 * | $(LITERAL 'cdouble') 1303 * | $(LITERAL 'creal') 1304 * | $(LITERAL 'void') 1305 * ;) 1306 */ 1307 IdType parseBuiltinType() 1308 { 1309 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1310 return advance().type; 1311 } 1312 1313 /** 1314 * Parses a CaseRangeStatement 1315 * 1316 * $(GRAMMAR $(RULEDEF caseRangeStatement): 1317 * $(LITERAL 'case') $(RULE assignExpression) $(LITERAL ':') $(LITERAL '...') $(LITERAL 'case') $(RULE assignExpression) $(LITERAL ':') $(RULE declarationsAndStatements) 1318 * ;) 1319 */ 1320 CaseRangeStatement parseCaseRangeStatement(ExpressionNode low) 1321 { 1322 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1323 auto node = allocate!CaseRangeStatement; 1324 assert (low !is null); 1325 node.low = low; 1326 mixin(nullCheck!`expect(tok!":")`); 1327 mixin(nullCheck!`expect(tok!"..")`); 1328 expect(tok!"case"); 1329 mixin(nullCheck!`node.high = parseAssignExpression()`); 1330 const colon = expect(tok!":"); 1331 if (colon is null) 1332 { 1333 deallocate(node); 1334 return null; 1335 } 1336 node.colonLocation = colon.index; 1337 mixin(nullCheck!`node.declarationsAndStatements = parseDeclarationsAndStatements()`); 1338 return node; 1339 } 1340 1341 /** 1342 * Parses an CaseStatement 1343 * 1344 * $(GRAMMAR $(RULEDEF caseStatement): 1345 * $(LITERAL 'case') $(RULE argumentList) $(LITERAL ':') $(RULE declarationsAndStatements) 1346 * ;) 1347 */ 1348 CaseStatement parseCaseStatement(ArgumentList argumentList = null) 1349 { 1350 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1351 auto node = allocate!CaseStatement; 1352 node.argumentList = argumentList; 1353 const colon = expect(tok!":"); 1354 if (colon is null) 1355 { 1356 deallocate(node); 1357 return null; 1358 } 1359 node.colonLocation = colon.index; 1360 mixin(nullCheck!`node.declarationsAndStatements = parseDeclarationsAndStatements()`); 1361 return node; 1362 } 1363 1364 /** 1365 * Parses a CastExpression 1366 * 1367 * $(GRAMMAR $(RULEDEF castExpression): 1368 * $(LITERAL 'cast') $(LITERAL '$(LPAREN)') ($(RULE type) | $(RULE castQualifier))? $(LITERAL '$(RPAREN)') $(RULE unaryExpression) 1369 * ;) 1370 */ 1371 CastExpression parseCastExpression() 1372 { 1373 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1374 auto node = allocate!CastExpression; 1375 expect(tok!"cast"); 1376 mixin(nullCheck!`expect(tok!"(")`); 1377 if (!currentIs(tok!")")) 1378 { 1379 if (isCastQualifier()) 1380 mixin(nullCheck!`node.castQualifier = parseCastQualifier()`); 1381 else 1382 mixin(nullCheck!`node.type = parseType()`); 1383 } 1384 mixin(nullCheck!`expect(tok!")")`); 1385 mixin(nullCheck!`node.unaryExpression = parseUnaryExpression()`); 1386 return node; 1387 } 1388 1389 /** 1390 * Parses a CastQualifier 1391 * 1392 * $(GRAMMAR $(RULEDEF castQualifier): 1393 * $(LITERAL 'const') 1394 * | $(LITERAL 'const') $(LITERAL 'shared') 1395 * | $(LITERAL 'immutable') 1396 * | $(LITERAL 'inout') 1397 * | $(LITERAL 'inout') $(LITERAL 'shared') 1398 * | $(LITERAL 'shared') 1399 * | $(LITERAL 'shared') $(LITERAL 'const') 1400 * | $(LITERAL 'shared') $(LITERAL 'inout') 1401 * ;) 1402 */ 1403 CastQualifier parseCastQualifier() 1404 { 1405 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1406 auto node = allocate!CastQualifier; 1407 switch (current.type) 1408 { 1409 case tok!"inout": 1410 case tok!"const": 1411 node.first = advance(); 1412 if (currentIs(tok!"shared")) 1413 node.second = advance(); 1414 break; 1415 case tok!"shared": 1416 node.first = advance(); 1417 if (currentIsOneOf(tok!"const", tok!"inout")) 1418 node.second = advance(); 1419 break; 1420 case tok!"immutable": 1421 node.first = advance(); 1422 break; 1423 default: 1424 error("const, immutable, inout, or shared expected"); 1425 return null; 1426 } 1427 return node; 1428 } 1429 1430 /** 1431 * Parses a Catch 1432 * 1433 * $(GRAMMAR $(RULEDEF catch): 1434 * $(LITERAL 'catch') $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL Identifier)? $(LITERAL '$(RPAREN)') $(RULE declarationOrStatement) 1435 * ;) 1436 */ 1437 Catch parseCatch() 1438 { 1439 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1440 auto node = allocate!Catch; 1441 expect(tok!"catch"); 1442 mixin(nullCheck!`expect(tok!"(")`); 1443 mixin(nullCheck!`node.type = parseType()`); 1444 if (currentIs(tok!"identifier")) 1445 node.identifier = advance(); 1446 mixin(nullCheck!`expect(tok!")")`); 1447 mixin(nullCheck!`node.declarationOrStatement = parseDeclarationOrStatement()`); 1448 return node; 1449 } 1450 1451 /** 1452 * Parses a Catches 1453 * 1454 * $(GRAMMAR $(RULEDEF catches): 1455 * $(RULE catch)+ 1456 * | $(RULE catch)* $(RULE lastCatch) 1457 * ;) 1458 */ 1459 Catches parseCatches() 1460 { 1461 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1462 auto node = allocate!Catches; 1463 Catch[] catches; 1464 while (moreTokens()) 1465 { 1466 if (!currentIs(tok!"catch")) 1467 break; 1468 if (peekIs(tok!"(")) 1469 catches ~= parseCatch(); 1470 else 1471 { 1472 node.lastCatch = parseLastCatch(); 1473 break; 1474 } 1475 } 1476 node.catches = ownArray(catches); 1477 return node; 1478 } 1479 1480 /** 1481 * Parses a ClassDeclaration 1482 * 1483 * $(GRAMMAR $(RULEDEF classDeclaration): 1484 * $(LITERAL 'class') $(LITERAL Identifier) $(LITERAL ';') 1485 * | $(LITERAL 'class') $(LITERAL Identifier) ($(LITERAL ':') $(RULE baseClassList))? $(RULE structBody) 1486 * | $(LITERAL 'class') $(LITERAL Identifier) $(RULE templateParameters) $(RULE constraint)? ($(RULE structBody) | $(LITERAL ';')) 1487 * | $(LITERAL 'class') $(LITERAL Identifier) $(RULE templateParameters) $(RULE constraint)? ($(LITERAL ':') $(RULE baseClassList))? $(RULE structBody) 1488 * | $(LITERAL 'class') $(LITERAL Identifier) $(RULE templateParameters) ($(LITERAL ':') $(RULE baseClassList))? $(RULE constraint)? $(RULE structBody) 1489 * ;) 1490 */ 1491 ClassDeclaration parseClassDeclaration() 1492 { 1493 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1494 auto node = allocate!ClassDeclaration; 1495 expect(tok!"class"); 1496 mixin(PARSE_INTERFACE_OR_CLASS); 1497 } 1498 1499 /** 1500 * Parses a CmpExpression 1501 * 1502 * $(GRAMMAR $(RULEDEF cmpExpression): 1503 * $(RULE shiftExpression) 1504 * | $(RULE equalExpression) 1505 * | $(RULE identityExpression) 1506 * | $(RULE relExpression) 1507 * | $(RULE inExpression) 1508 * ;) 1509 */ 1510 ExpressionNode parseCmpExpression() 1511 { 1512 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1513 auto shift = parseShiftExpression(); 1514 if (shift is null) 1515 return null; 1516 if (!moreTokens()) 1517 return shift; 1518 switch (current.type) 1519 { 1520 case tok!"is": 1521 auto node = allocate!CmpExpression; 1522 mixin(nullCheck!`node.identityExpression = parseIdentityExpression(shift)`); 1523 return node; 1524 case tok!"in": 1525 auto node = allocate!CmpExpression; 1526 mixin(nullCheck!`node.inExpression = parseInExpression(shift)`); 1527 return node; 1528 case tok!"!": 1529 auto node = allocate!CmpExpression; 1530 if (peekIs(tok!"is")) 1531 mixin(nullCheck!`node.identityExpression = parseIdentityExpression(shift)`); 1532 else if (peekIs(tok!"in")) 1533 mixin(nullCheck!`node.inExpression = parseInExpression(shift)`); 1534 return node; 1535 case tok!"<": 1536 case tok!"<=": 1537 case tok!">": 1538 case tok!">=": 1539 case tok!"!<>=": 1540 case tok!"!<>": 1541 case tok!"<>": 1542 case tok!"<>=": 1543 case tok!"!>": 1544 case tok!"!>=": 1545 case tok!"!<": 1546 case tok!"!<=": 1547 auto node = allocate!CmpExpression; 1548 mixin(nullCheck!`node.relExpression = parseRelExpression(shift)`); 1549 return node; 1550 case tok!"==": 1551 case tok!"!=": 1552 auto node = allocate!CmpExpression; 1553 mixin(nullCheck!`node.equalExpression = parseEqualExpression(shift)`); 1554 return node; 1555 default: 1556 return shift; 1557 } 1558 } 1559 1560 /** 1561 * Parses a CompileCondition 1562 * 1563 * $(GRAMMAR $(RULEDEF compileCondition): 1564 * $(RULE versionCondition) 1565 * | $(RULE debugCondition) 1566 * | $(RULE staticIfCondition) 1567 * ;) 1568 */ 1569 CompileCondition parseCompileCondition() 1570 { 1571 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1572 auto node = allocate!CompileCondition; 1573 switch (current.type) 1574 { 1575 case tok!"version": 1576 mixin(nullCheck!`node.versionCondition = parseVersionCondition()`); 1577 break; 1578 case tok!"debug": 1579 mixin(nullCheck!`node.debugCondition = parseDebugCondition()`); 1580 break; 1581 case tok!"static": 1582 mixin(nullCheck!`node.staticIfCondition = parseStaticIfCondition()`); 1583 break; 1584 default: 1585 error(`"version", "debug", or "static" expected`); 1586 return null; 1587 } 1588 return node; 1589 } 1590 1591 /** 1592 * Parses a ConditionalDeclaration 1593 * 1594 * $(GRAMMAR $(RULEDEF conditionalDeclaration): 1595 * $(RULE compileCondition) $(RULE declaration) 1596 * | $(RULE compileCondition) $(LITERAL ':') $(RULE declaration)+ 1597 * | $(RULE compileCondition) $(RULE declaration) $(LITERAL 'else') $(RULE declaration) 1598 * ;) 1599 */ 1600 ConditionalDeclaration parseConditionalDeclaration() 1601 { 1602 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1603 auto node = allocate!ConditionalDeclaration; 1604 1605 string supplementalComment = comment; 1606 comment = null; 1607 1608 mixin(nullCheck!`node.compileCondition = parseCompileCondition()`); 1609 1610 Declaration[] trueDeclarations; 1611 if (currentIs(tok!":")) 1612 { 1613 advance(); 1614 while (moreTokens() && !currentIs(tok!"}")) 1615 { 1616 auto b = setBookmark(); 1617 auto d = parseDeclaration(false); 1618 if (d !is null) 1619 { 1620 abandonBookmark(b); 1621 d.setSupplementalComment(supplementalComment); 1622 trueDeclarations ~= d; 1623 } 1624 else 1625 { 1626 goToBookmark(b); 1627 deallocate(node); 1628 return null; 1629 } 1630 } 1631 node.trueDeclarations = ownArray(trueDeclarations); 1632 return node; 1633 } 1634 1635 auto dec = parseDeclaration(suppressMessages > 0); 1636 mixin(nullCheck!`dec`); 1637 1638 dec.setSupplementalComment(supplementalComment); 1639 trueDeclarations ~= dec; 1640 node.trueDeclarations = ownArray(trueDeclarations); 1641 1642 if (currentIs(tok!"else")) 1643 advance(); 1644 else 1645 return node; 1646 1647 if ((node.falseDeclaration = parseDeclaration(suppressMessages > 0)) is null) 1648 { 1649 deallocate(node); 1650 return null; 1651 } 1652 return node; 1653 } 1654 1655 /** 1656 * Parses a ConditionalStatement 1657 * 1658 * $(GRAMMAR $(RULEDEF conditionalStatement): 1659 * $(RULE compileCondition) $(RULE declarationOrStatement) ($(LITERAL 'else') $(RULE declarationOrStatement))? 1660 * ;) 1661 */ 1662 ConditionalStatement parseConditionalStatement() 1663 { 1664 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1665 auto node = allocate!ConditionalStatement; 1666 mixin(nullCheck!`node.compileCondition = parseCompileCondition()`); 1667 mixin(nullCheck!`node.trueStatement = parseDeclarationOrStatement()`); 1668 if (currentIs(tok!"else")) 1669 { 1670 advance(); 1671 mixin(nullCheck!`node.falseStatement = parseDeclarationOrStatement()`); 1672 } 1673 return node; 1674 } 1675 1676 /** 1677 * Parses a Constraint 1678 * 1679 * $(GRAMMAR $(RULEDEF constraint): 1680 * $(LITERAL 'if') $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)') 1681 * ;) 1682 */ 1683 Constraint parseConstraint() 1684 { 1685 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1686 auto node = allocate!Constraint; 1687 mixin(nullCheck!`expect(tok!"if")`); 1688 mixin(nullCheck!`expect(tok!"(")`); 1689 mixin(nullCheck!`node.expression = parseExpression()`); 1690 mixin(nullCheck!`expect(tok!")")`); 1691 return node; 1692 } 1693 1694 /** 1695 * Parses a Constructor 1696 * 1697 * $(GRAMMAR $(RULEDEF constructor): 1698 * $(LITERAL 'this') $(RULE templateParameters)? $(RULE parameters) $(RULE memberFunctionAttribute)* $(RULE constraint)? ($(RULE functionBody) | $(LITERAL ';')) 1699 * ;) 1700 */ 1701 Constructor parseConstructor() 1702 { 1703 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1704 Constructor node = allocate!Constructor; 1705 node.comment = comment; 1706 comment = null; 1707 const t = expect(tok!"this"); 1708 mixin(nullCheck!`t`); 1709 node.location = t.index; 1710 node.line = t.line; 1711 node.column = t.column; 1712 const p = peekPastParens(); 1713 bool isTemplate = false; 1714 if (p !is null && p.type == tok!"(") 1715 { 1716 isTemplate = true; 1717 mixin(nullCheck!`node.templateParameters = parseTemplateParameters()`); 1718 } 1719 mixin(nullCheck!`node.parameters = parseParameters()`); 1720 mixin(nullCheck!`node.parameters`); 1721 1722 MemberFunctionAttribute[] memberFunctionAttributes; 1723 while (moreTokens() && currentIsMemberFunctionAttribute()) 1724 memberFunctionAttributes ~= parseMemberFunctionAttribute(); 1725 node.memberFunctionAttributes = ownArray(memberFunctionAttributes); 1726 1727 if (isTemplate && currentIs(tok!"if")) 1728 mixin(nullCheck!`node.constraint = parseConstraint()`); 1729 1730 if (currentIs(tok!";")) 1731 advance(); 1732 else 1733 { 1734 mixin(nullCheck!`node.functionBody = parseFunctionBody()`); 1735 mixin(nullCheck!`node.functionBody`); 1736 } 1737 1738 return node; 1739 } 1740 1741 /** 1742 * Parses an ContinueStatement 1743 * 1744 * $(GRAMMAR $(RULEDEF continueStatement): 1745 * $(LITERAL 'continue') $(LITERAL Identifier)? $(LITERAL ';') 1746 * ;) 1747 */ 1748 ContinueStatement parseContinueStatement() 1749 { 1750 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1751 if (expect(tok!"continue") is null) return null; 1752 auto node = allocate!ContinueStatement; 1753 switch (current.type) 1754 { 1755 case tok!"identifier": 1756 node.label = advance(); 1757 mixin(nullCheck!`expect(tok!";")`); 1758 break; 1759 case tok!";": 1760 advance(); 1761 break; 1762 default: 1763 error(`Identifier or semicolon expected following "continue"`); 1764 return null; 1765 } 1766 return node; 1767 } 1768 1769 /** 1770 * Parses a DebugCondition 1771 * 1772 * $(GRAMMAR $(RULEDEF debugCondition): 1773 * $(LITERAL 'debug') ($(LITERAL '$(LPAREN)') ($(LITERAL IntegerLiteral) | $(LITERAL Identifier)) $(LITERAL '$(RPAREN)'))? 1774 * ;) 1775 */ 1776 DebugCondition parseDebugCondition() 1777 { 1778 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1779 auto node = allocate!DebugCondition; 1780 1781 const d = expect(tok!"debug"); 1782 mixin(nullCheck!`d`); 1783 node.debugIndex = d.index; 1784 1785 if (currentIs(tok!"(")) 1786 { 1787 advance(); 1788 if (currentIsOneOf(tok!"intLiteral", tok!"identifier")) 1789 node.identifierOrInteger = advance(); 1790 else 1791 { 1792 error(`Integer literal or identifier expected`); 1793 return null; 1794 } 1795 mixin(nullCheck!`expect(tok!")")`); 1796 } 1797 return node; 1798 } 1799 1800 /** 1801 * Parses a DebugSpecification 1802 * 1803 * $(GRAMMAR $(RULEDEF debugSpecification): 1804 * $(LITERAL 'debug') $(LITERAL '=') ($(LITERAL Identifier) | $(LITERAL IntegerLiteral)) $(LITERAL ';') 1805 * ;) 1806 */ 1807 DebugSpecification parseDebugSpecification() 1808 { 1809 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1810 auto node = allocate!DebugSpecification; 1811 mixin(nullCheck!`expect(tok!"debug")`); 1812 mixin(nullCheck!`expect(tok!"=")`); 1813 if (currentIsOneOf(tok!"identifier", tok!"intLiteral")) 1814 node.identifierOrInteger = advance(); 1815 else 1816 { 1817 error("Integer literal or identifier expected"); 1818 return null; 1819 } 1820 mixin(nullCheck!`expect(tok!";")`); 1821 return node; 1822 } 1823 1824 /** 1825 * Parses a Declaration 1826 * 1827 * Params: strict = if true, do not return partial AST nodes on errors. 1828 * 1829 * $(GRAMMAR $(RULEDEF declaration): 1830 * $(RULE attribute)* $(RULE declaration2) 1831 * ; 1832 * $(RULEDEF declaration2): 1833 * $(RULE aliasDeclaration) 1834 * | $(RULE aliasThisDeclaration) 1835 * | $(RULE anonymousEnumDeclaration) 1836 * | $(RULE attributeDeclaration) 1837 * | $(RULE classDeclaration) 1838 * | $(RULE conditionalDeclaration) 1839 * | $(RULE constructor) 1840 * | $(RULE debugSpecification) 1841 * | $(RULE destructor) 1842 * | $(RULE enumDeclaration) 1843 * | $(RULE eponymousTemplateDeclaration) 1844 * | $(RULE functionDeclaration) 1845 * | $(RULE importDeclaration) 1846 * | $(RULE interfaceDeclaration) 1847 * | $(RULE invariant) 1848 * | $(RULE mixinDeclaration) 1849 * | $(RULE mixinTemplateDeclaration) 1850 * | $(RULE pragmaDeclaration) 1851 * | $(RULE sharedStaticConstructor) 1852 * | $(RULE sharedStaticDestructor) 1853 * | $(RULE staticAssertDeclaration) 1854 * | $(RULE staticConstructor) 1855 * | $(RULE staticDestructor) 1856 * | $(RULE structDeclaration) 1857 * | $(RULE templateDeclaration) 1858 * | $(RULE unionDeclaration) 1859 * | $(RULE unittest) 1860 * | $(RULE variableDeclaration) 1861 * | $(RULE versionSpecification) 1862 * | $(LITERAL '{') $(RULE declaration)+ $(LITERAL '}') 1863 * ;) 1864 */ 1865 Declaration parseDeclaration(bool strict = false) 1866 { 1867 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 1868 auto node = allocate!Declaration; 1869 if (!moreTokens) 1870 { 1871 error("declaration expected instead of EOF"); 1872 return null; 1873 } 1874 if (current.comment !is null) 1875 comment = current.comment; 1876 Attribute[] attributes; 1877 do 1878 { 1879 if (!isAttribute()) 1880 break; 1881 auto attr = parseAttribute(); 1882 if (attr is null) 1883 { 1884 error("attribute is null"); 1885 break; 1886 } 1887 if (currentIs(tok!":")) 1888 { 1889 node.attributeDeclaration = parseAttributeDeclaration(attr); 1890 node.attributes = ownArray(attributes); 1891 return node; 1892 } 1893 else 1894 attributes ~= attr; 1895 } while (moreTokens()); 1896 node.attributes = ownArray(attributes); 1897 1898 if (!moreTokens) 1899 { 1900 error("declaration expected instead of EOF"); 1901 deallocate(node); 1902 return null; 1903 } 1904 1905 switch (current.type) 1906 { 1907 case tok!"asm": 1908 case tok!"break": 1909 case tok!"case": 1910 case tok!"continue": 1911 case tok!"default": 1912 case tok!"do": 1913 case tok!"for": 1914 case tok!"foreach": 1915 case tok!"foreach_reverse": 1916 case tok!"goto": 1917 case tok!"if": 1918 case tok!"return": 1919 case tok!"switch": 1920 case tok!"throw": 1921 case tok!"try": 1922 case tok!"while": 1923 case tok!"assert": 1924 goto default; 1925 case tok!";": 1926 // http://d.puremagic.com/issues/show_bug.cgi?id=4559 1927 warn("Empty declaration"); 1928 advance(); 1929 break; 1930 case tok!"{": 1931 advance(); 1932 Declaration[] declarations; 1933 while (moreTokens() && !currentIs(tok!"}")) 1934 { 1935 auto declaration = parseDeclaration(strict); 1936 if (declaration !is null) 1937 declarations ~= declaration; 1938 else if (strict) 1939 { 1940 deallocate(node); 1941 return null; 1942 } 1943 } 1944 node.declarations = ownArray(declarations); 1945 mixin(nullCheck!`expect(tok!"}")`); 1946 break; 1947 case tok!"alias": 1948 if (startsWith(tok!"alias", tok!"identifier", tok!"this")) 1949 mixin(nullCheck!`node.aliasThisDeclaration = parseAliasThisDeclaration()`); 1950 else 1951 mixin(nullCheck!`node.aliasDeclaration = parseAliasDeclaration()`); 1952 break; 1953 case tok!"class": 1954 mixin(nullCheck!`node.classDeclaration = parseClassDeclaration()`); 1955 break; 1956 case tok!"this": 1957 if (strict && peekIs(tok!"(")) 1958 { 1959 // If we are in strict mode, do not parse as a declaration. 1960 // Instead this should be parsed as a function call. 1961 ++index; 1962 const past = peekPastParens(); 1963 --index; 1964 if (past !is null && past.type == tok!";") 1965 { 1966 deallocate(node); 1967 return null; 1968 } 1969 } 1970 if (startsWith(tok!"this", tok!"(", tok!"this", tok!")")) 1971 { 1972 mixin(nullCheck!`node.postblit = parsePostblit()`); 1973 mixin(nullCheck!`node.postblit`); 1974 } 1975 else 1976 { 1977 mixin(nullCheck!`node.constructor = parseConstructor()`); 1978 mixin(nullCheck!`node.constructor`); 1979 } 1980 break; 1981 case tok!"~": 1982 mixin(nullCheck!`node.destructor = parseDestructor()`); 1983 mixin(nullCheck!`node.destructor`); 1984 break; 1985 case tok!"enum": 1986 auto b = setBookmark(); 1987 advance(); // enum 1988 if (currentIsOneOf(tok!":", tok!"{")) 1989 { 1990 goToBookmark(b); 1991 mixin(nullCheck!`node.anonymousEnumDeclaration = parseAnonymousEnumDeclaration()`); 1992 } 1993 else if (currentIs(tok!"identifier")) 1994 { 1995 advance(); 1996 if (currentIs(tok!"(")) 1997 { 1998 skipParens(); // () 1999 if (currentIs(tok!"(")) 2000 skipParens(); 2001 if (!currentIs(tok!"=")) 2002 { 2003 goToBookmark(b); 2004 node.functionDeclaration = parseFunctionDeclaration(null, true, node.attributes); 2005 mixin(nullCheck!`node.functionDeclaration`); 2006 } 2007 else 2008 { 2009 goToBookmark(b); 2010 mixin(nullCheck!`node.eponymousTemplateDeclaration = parseEponymousTemplateDeclaration()`); 2011 } 2012 } 2013 else if (currentIsOneOf(tok!":", tok!"{", tok!";")) 2014 { 2015 goToBookmark(b); 2016 mixin(nullCheck!`node.enumDeclaration = parseEnumDeclaration()`); 2017 } 2018 else 2019 { 2020 immutable bool eq = currentIs(tok!"="); 2021 goToBookmark(b); 2022 mixin(nullCheck!`node.variableDeclaration = parseVariableDeclaration(null, eq, null, true)`); 2023 } 2024 } 2025 else 2026 { 2027 immutable bool s = isStorageClass(); 2028 goToBookmark(b); 2029 mixin(nullCheck!`node.variableDeclaration = parseVariableDeclaration(null, s, null, true)`); 2030 } 2031 break; 2032 case tok!"import": 2033 mixin(nullCheck!`node.importDeclaration = parseImportDeclaration()`); 2034 break; 2035 case tok!"interface": 2036 mixin(nullCheck!`node.interfaceDeclaration = parseInterfaceDeclaration()`); 2037 break; 2038 case tok!"mixin": 2039 if (peekIs(tok!"template")) 2040 mixin(nullCheck!`node.mixinTemplateDeclaration = parseMixinTemplateDeclaration()`); 2041 else 2042 { 2043 auto b = setBookmark(); 2044 advance(); 2045 if (currentIs(tok!"(")) 2046 { 2047 const t = peekPastParens(); 2048 if (t !is null && t.type == tok!";") 2049 { 2050 goToBookmark(b); 2051 mixin(nullCheck!`node.mixinDeclaration = parseMixinDeclaration()`); 2052 } 2053 else 2054 { 2055 goToBookmark(b); 2056 error("Declaration expected for mixin"); 2057 deallocate(node); 2058 return null; 2059 } 2060 } 2061 else 2062 { 2063 goToBookmark(b); 2064 mixin(nullCheck!`node.mixinDeclaration = parseMixinDeclaration()`); 2065 } 2066 } 2067 break; 2068 case tok!"pragma": 2069 mixin(nullCheck!`node.pragmaDeclaration = parsePragmaDeclaration()`); 2070 break; 2071 case tok!"shared": 2072 if (startsWith(tok!"shared", tok!"static", tok!"this")) 2073 mixin(nullCheck!`node.sharedStaticConstructor = parseSharedStaticConstructor()`); 2074 else if (startsWith(tok!"shared", tok!"static", tok!"~")) 2075 mixin(nullCheck!`node.sharedStaticDestructor = parseSharedStaticDestructor()`); 2076 else 2077 goto type; 2078 break; 2079 case tok!"static": 2080 if (peekIs(tok!"this")) 2081 mixin(nullCheck!`node.staticConstructor = parseStaticConstructor()`); 2082 else if (peekIs(tok!"~")) 2083 mixin(nullCheck!`node.staticDestructor = parseStaticDestructor()`); 2084 else if (peekIs(tok!"if")) 2085 mixin(nullCheck!`node.conditionalDeclaration = parseConditionalDeclaration()`); 2086 else if (peekIs(tok!"assert")) 2087 mixin(nullCheck!`node.staticAssertDeclaration = parseStaticAssertDeclaration()`); 2088 else if (peekIs(tok!"foreach")) 2089 mixin(nullCheck!`node.staticForeachDeclaration = parseStaticForeachDeclaration()`); 2090 else 2091 goto type; 2092 break; 2093 case tok!"struct": 2094 mixin(nullCheck!`node.structDeclaration = parseStructDeclaration()`); 2095 break; 2096 case tok!"template": 2097 mixin(nullCheck!`node.templateDeclaration = parseTemplateDeclaration()`); 2098 break; 2099 case tok!"union": 2100 mixin(nullCheck!`node.unionDeclaration = parseUnionDeclaration()`); 2101 break; 2102 case tok!"invariant": 2103 mixin(nullCheck!`node.invariant_ = parseInvariant()`); 2104 break; 2105 case tok!"unittest": 2106 mixin(nullCheck!`node.unittest_ = parseUnittest()`); 2107 break; 2108 case tok!"identifier": 2109 if (node.attributes.length > 0) 2110 { 2111 if (peekIs(tok!"=")) 2112 node.variableDeclaration = parseVariableDeclaration(null, true, node.attributes); 2113 else if (peekIs(tok!"(")) 2114 { 2115 auto b = setBookmark(); 2116 advance(); 2117 const t = peekPastParens(); 2118 goToBookmark(b); 2119 if (t !is null && *t == tok!"=") 2120 node.variableDeclaration = parseVariableDeclaration(null, true, node.attributes); 2121 else 2122 node.functionDeclaration = parseFunctionDeclaration(null, true, node.attributes); 2123 } 2124 else 2125 goto type; 2126 } 2127 else 2128 goto type; 2129 break; 2130 case tok!".": 2131 case tok!"const": 2132 case tok!"immutable": 2133 case tok!"inout": 2134 case tok!"scope": 2135 case tok!"typeof": 2136 case tok!"__vector": 2137 mixin(BUILTIN_TYPE_CASES); 2138 type: 2139 Type type = parseType(); 2140 if (type is null || !currentIs(tok!"identifier")) 2141 { 2142 trace("Returning null on %d".format(__LINE__)); 2143 deallocate(node); 2144 return null; 2145 } 2146 if (peekIs(tok!"(")) 2147 { 2148 auto b = setBookmark(); 2149 advance(); 2150 const t = peekPastParens(); 2151 goToBookmark(b); 2152 if (t is null) 2153 return null; 2154 if (*t != tok!"=") 2155 node.functionDeclaration = parseFunctionDeclaration(type, false, node.attributes); 2156 else 2157 node.variableDeclaration = parseVariableDeclaration(type, false, node.attributes); 2158 } 2159 else 2160 mixin(nullCheck!`node.variableDeclaration = parseVariableDeclaration(type)`); 2161 break; 2162 case tok!"version": 2163 if (peekIs(tok!"(")) 2164 mixin(nullCheck!`node.conditionalDeclaration = parseConditionalDeclaration()`); 2165 else if (peekIs(tok!"=")) 2166 mixin(nullCheck!`node.versionSpecification = parseVersionSpecification()`); 2167 else 2168 { 2169 error(`"=" or "(" expected following "version"`); 2170 deallocate(node); 2171 return null; 2172 } 2173 break; 2174 case tok!"debug": 2175 if (peekIs(tok!"=")) 2176 mixin(nullCheck!`node.debugSpecification = parseDebugSpecification()`); 2177 else 2178 mixin(nullCheck!`node.conditionalDeclaration = parseConditionalDeclaration()`); 2179 break; 2180 default: 2181 error("Declaration expected for parse declartion"); 2182 deallocate(node); 2183 return null; 2184 } 2185 return node; 2186 } 2187 2188 /** 2189 * Parses DeclarationsAndStatements 2190 * 2191 * $(GRAMMAR $(RULEDEF declarationsAndStatements): 2192 * $(RULE declarationOrStatement)+ 2193 * ;) 2194 */ 2195 DeclarationsAndStatements parseDeclarationsAndStatements() 2196 { 2197 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2198 auto node = allocate!DeclarationsAndStatements; 2199 DeclarationOrStatement[] declarationsAndStatements; 2200 while (!currentIsOneOf(tok!"}", tok!"else") && moreTokens() && suppressedErrorCount <= MAX_ERRORS) 2201 { 2202 if (currentIs(tok!"while")) 2203 { 2204 auto b = setBookmark(); 2205 scope (exit) goToBookmark(b); 2206 advance(); 2207 if (currentIs(tok!"(")) 2208 { 2209 const p = peekPastParens(); 2210 if (p !is null && *p == tok!";") 2211 break; 2212 } 2213 } 2214 auto dos = parseDeclarationOrStatement(); 2215 if (dos !is null) 2216 declarationsAndStatements ~= dos; 2217 else if (suppressMessages > 0) 2218 { 2219 deallocate(node); 2220 return null; 2221 } 2222 } 2223 node.declarationsAndStatements = ownArray(declarationsAndStatements); 2224 return node; 2225 } 2226 2227 /** 2228 * Parses a DeclarationOrStatement 2229 * 2230 * $(GRAMMAR $(RULEDEF declarationOrStatement): 2231 * $(RULE declaration) 2232 * | $(RULE statement) 2233 * ;) 2234 */ 2235 DeclarationOrStatement parseDeclarationOrStatement() 2236 { 2237 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2238 auto node = allocate!DeclarationOrStatement; 2239 // "Any ambiguities in the grammar between Statements and 2240 // Declarations are resolved by the declarations taking precedence." 2241 auto b = setBookmark(); 2242 auto d = parseDeclaration(true); 2243 if (d is null) 2244 { 2245 goToBookmark(b); 2246 mixin(nullCheck!`node.statement = parseStatement()`); 2247 } 2248 else 2249 { 2250 // TODO: Make this more efficient. Right now we parse the declaration 2251 // twice, once with errors and warnings ignored, and once with them 2252 // printed. Maybe store messages to then be abandoned or written later? 2253 deallocate(d); 2254 goToBookmark(b); 2255 node.declaration = parseDeclaration(); 2256 } 2257 return node; 2258 } 2259 2260 /** 2261 * Parses a Declarator 2262 * 2263 * $(GRAMMAR $(RULEDEF declarator): 2264 * $(LITERAL Identifier) 2265 * | $(LITERAL Identifier) $(LITERAL '=') $(RULE initializer) 2266 * | $(LITERAL Identifier) $(RULE templateParameters) $(LITERAL '=') $(RULE initializer) 2267 * ;) 2268 */ 2269 Declarator parseDeclarator() 2270 { 2271 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2272 auto node = allocate!Declarator; 2273 const id = expect(tok!"identifier"); 2274 mixin(nullCheck!`id`); 2275 node.name = *id; 2276 if (currentIs(tok!"[")) // dmd doesn't accept pointer after identifier 2277 { 2278 warn("C-style array declaration."); 2279 TypeSuffix[] typeSuffixes; 2280 while (moreTokens() && currentIs(tok!"[")) 2281 { 2282 auto suffix = parseTypeSuffix(); 2283 mixin(nullCheck!`suffix`); 2284 typeSuffixes ~= suffix; 2285 } 2286 node.cstyle = ownArray(typeSuffixes); 2287 } 2288 if (currentIs(tok!"(")) 2289 { 2290 mixin(nullCheck!`(node.templateParameters = parseTemplateParameters())`); 2291 mixin(nullCheck!`expect(tok!"=")`); 2292 mixin(nullCheck!`(node.initializer = parseInitializer())`); 2293 } 2294 else if (currentIs(tok!"=")) 2295 { 2296 advance(); 2297 mixin(nullCheck!`node.initializer = parseInitializer()`); 2298 } 2299 return node; 2300 } 2301 2302 /** 2303 * Parses a DefaultStatement 2304 * 2305 * $(GRAMMAR $(RULEDEF defaultStatement): 2306 * $(LITERAL 'default') $(LITERAL ':') $(RULE declarationsAndStatements) 2307 * ;) 2308 */ 2309 DefaultStatement parseDefaultStatement() 2310 { 2311 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2312 auto node = allocate!DefaultStatement; 2313 mixin(nullCheck!`expect(tok!"default")`); 2314 const colon = expect(tok!":"); 2315 if (colon is null) 2316 { 2317 deallocate(node); 2318 return null; 2319 } 2320 node.colonLocation = colon.index; 2321 mixin(nullCheck!`node.declarationsAndStatements = parseDeclarationsAndStatements()`); 2322 return node; 2323 } 2324 2325 /** 2326 * Parses a DeleteExpression 2327 * 2328 * $(GRAMMAR $(RULEDEF deleteExpression): 2329 * $(LITERAL 'delete') $(RULE unaryExpression) 2330 * ;) 2331 */ 2332 DeleteExpression parseDeleteExpression() 2333 { 2334 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2335 auto node = allocate!DeleteExpression; 2336 node.line = current.line; 2337 node.column = current.column; 2338 mixin(nullCheck!`expect(tok!"delete")`); 2339 mixin(nullCheck!`node.unaryExpression = parseUnaryExpression()`); 2340 return node; 2341 } 2342 2343 /** 2344 * Parses a Deprecated attribute 2345 * 2346 * $(GRAMMAR $(RULEDEF deprecated): 2347 * $(LITERAL 'deprecated') ($(LITERAL '$(LPAREN)') $(LITERAL StringLiteral)+ $(LITERAL '$(RPAREN)'))? 2348 * ;) 2349 */ 2350 Deprecated parseDeprecated() 2351 { 2352 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2353 auto node = allocate!Deprecated; 2354 mixin(nullCheck!`expect(tok!"deprecated")`); 2355 if (currentIs(tok!"(")) 2356 { 2357 advance(); 2358 Token[] tokens; 2359 while (currentIs(tok!"stringLiteral") || currentIs(tok!"~")) 2360 tokens ~= advance(); 2361 node.stringLiterals = ownArray(tokens); 2362 mixin(nullCheck!`expect(tok!")")`); 2363 } 2364 return node; 2365 } 2366 2367 /** 2368 * Parses a Destructor 2369 * 2370 * $(GRAMMAR $(RULEDEF destructor): 2371 * $(LITERAL '~') $(LITERAL 'this') $(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)') $(RULE memberFunctionAttribute)* ($(RULE functionBody) | $(LITERAL ';')) 2372 * ;) 2373 */ 2374 Destructor parseDestructor() 2375 { 2376 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2377 auto node = allocate!Destructor; 2378 node.comment = comment; 2379 comment = null; 2380 mixin(nullCheck!`expect(tok!"~")`); 2381 if (!moreTokens) 2382 { 2383 error("'this' expected"); 2384 deallocate(node); 2385 return null; 2386 } 2387 node.index = current.index; 2388 node.line = current.line; 2389 node.column = current.column; 2390 mixin(nullCheck!`expect(tok!"this")`); 2391 mixin(nullCheck!`expect(tok!"(")`); 2392 mixin(nullCheck!`expect(tok!")")`); 2393 if (currentIs(tok!";")) 2394 advance(); 2395 else 2396 { 2397 MemberFunctionAttribute[] memberFunctionAttributes; 2398 while (moreTokens() && currentIsMemberFunctionAttribute()) 2399 memberFunctionAttributes ~= parseMemberFunctionAttribute(); 2400 node.memberFunctionAttributes = ownArray(memberFunctionAttributes); 2401 mixin(nullCheck!`node.functionBody = parseFunctionBody()`); 2402 } 2403 return node; 2404 } 2405 2406 /** 2407 * Parses a DoStatement 2408 * 2409 * $(GRAMMAR $(RULEDEF doStatement): 2410 * $(LITERAL 'do') $(RULE statementNoCaseNoDefault) $(LITERAL 'while') $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)') $(LITERAL ';') 2411 * ;) 2412 */ 2413 DoStatement parseDoStatement() 2414 { 2415 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2416 auto node = allocate!DoStatement; 2417 mixin(nullCheck!`expect(tok!"do")`); 2418 mixin(nullCheck!`node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault()`); 2419 mixin(nullCheck!`expect(tok!"while")`); 2420 mixin(nullCheck!`expect(tok!"(")`); 2421 mixin(nullCheck!`node.expression = parseExpression()`); 2422 mixin(nullCheck!`expect(tok!")")`); 2423 mixin(nullCheck!`expect(tok!";")`); 2424 return node; 2425 } 2426 2427 /** 2428 * Parses an EnumBody 2429 * 2430 * $(GRAMMAR $(RULEDEF enumBody): 2431 * $(LITERAL '{') $(RULE enumMember) ($(LITERAL ',') $(RULE enumMember)?)* $(LITERAL '}') 2432 * ;) 2433 */ 2434 EnumBody parseEnumBody() 2435 { 2436 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2437 EnumBody node = allocate!EnumBody; 2438 const open = expect(tok!"{"); 2439 mixin(nullCheck!`open`); 2440 node.startLocation = open.index; 2441 EnumMember[] enumMembers; 2442 while (moreTokens()) 2443 { 2444 if (currentIs(tok!",")) 2445 { 2446 if (enumMembers.length > 0 && enumMembers[$ - 1].comment is null) 2447 enumMembers[$ - 1].comment = current.trailingComment; 2448 advance(); 2449 continue; 2450 } 2451 else if (currentIs(tok!"}")) 2452 { 2453 if (enumMembers.length > 0 && enumMembers[$ - 1].comment is null) 2454 enumMembers[$ - 1].comment = tokens[index - 1].trailingComment; 2455 break; 2456 } 2457 else 2458 { 2459 auto member = parseEnumMember(); 2460 if (member is null) 2461 return null; 2462 enumMembers ~= member; 2463 } 2464 } 2465 node.enumMembers = ownArray(enumMembers); 2466 const close = expect (tok!"}"); 2467 if (close !is null) 2468 node.endLocation = close.index; 2469 return node; 2470 } 2471 2472 /** 2473 * $(GRAMMAR $(RULEDEF anonymousEnumMember): 2474 * $(RULE type) $(LITERAL identifier) $(LITERAL '=') $(RULE assignExpression) 2475 * | $(LITERAL identifier) $(LITERAL '=') $(RULE assignExpression) 2476 * | $(LITERAL identifier) 2477 * ;) 2478 */ 2479 AnonymousEnumMember parseAnonymousEnumMember(bool typeAllowed) 2480 { 2481 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2482 auto node = allocate!AnonymousEnumMember; 2483 2484 2485 2486 while (moreTokens()) 2487 { 2488 if(currentIs(tok!"@")) { 2489 if(peek() !is null && (*peek()) == tok!"identifier" && (*peek()).text == "disable") { 2490 advance(); 2491 advance(); 2492 node.isDisabled = true; 2493 } else { 2494 AtAttribute atAttribute; 2495 mixin(nullCheck!`atAttribute = parseAtAttribute()`); 2496 if (atAttribute is null) { deallocate(node); break; } 2497 node.atAttributes ~= atAttribute; 2498 } 2499 } else if(currentIs(tok!"deprecated")) { 2500 mixin(nullCheck!`node.deprecated_ = parseDeprecated()`); 2501 } else { 2502 break; 2503 } 2504 } 2505 2506 2507 2508 node.line = current.line; 2509 2510 if (currentIs(tok!"identifier") && peekIsOneOf(tok!",", tok!"=", tok!"}")) 2511 { 2512 node.comment = current.comment; 2513 comment = null; 2514 mixin(tokenCheck!(`node.name`, `identifier`)); 2515 if (currentIs(tok!"=")) 2516 { 2517 advance(); // = 2518 goto assign; 2519 } 2520 } 2521 else if (typeAllowed) 2522 { 2523 node.comment = current.comment; 2524 comment = null; 2525 mixin(nullCheck!`node.type = parseType()`); 2526 mixin(tokenCheck!(`node.name`, `identifier`)); 2527 mixin(nullCheck!`expect(tok!"=")`); 2528 assign: 2529 mixin(nullCheck!`node.assignExpression = parseAssignExpression()`); 2530 } 2531 else 2532 { 2533 error("Cannot specify anonymous enum member type if anonymous enum has a base type."); 2534 deallocate(node); 2535 return null; 2536 } 2537 return node; 2538 } 2539 2540 /** 2541 * $(GRAMMAR $(RULEDEF anonymousEnumDeclaration): 2542 * $(LITERAL 'enum') ($(LITERAL ':') $(RULE type))? $(LITERAL '{') $(RULE anonymousEnumMember)+ $(LITERAL '}') 2543 * ;) 2544 */ 2545 AnonymousEnumDeclaration parseAnonymousEnumDeclaration() 2546 { 2547 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2548 auto node = allocate!AnonymousEnumDeclaration; 2549 node.line = current.line; 2550 node.comment = comment; 2551 mixin(nullCheck!`expect(tok!"enum")`); 2552 immutable bool hasBaseType = currentIs(tok!":"); 2553 if (hasBaseType) 2554 { 2555 advance(); 2556 mixin(nullCheck!`node.baseType = parseType()`); 2557 } 2558 mixin(nullCheck!`expect(tok!"{")`); 2559 AnonymousEnumMember[] members; 2560 while (moreTokens()) 2561 { 2562 if (currentIs(tok!",")) 2563 { 2564 if (members.length > 0 && members[$ - 1].comment is null) 2565 members[$ - 1].comment = current.trailingComment; 2566 advance(); 2567 continue; 2568 } 2569 else if (currentIs(tok!"}")) 2570 { 2571 if (members.length > 0 && members[$ - 1].comment is null) 2572 members[$ - 1].comment = tokens[index - 1].trailingComment; 2573 break; 2574 } 2575 else 2576 { 2577 auto member = parseAnonymousEnumMember(!hasBaseType); 2578 if (member is null) 2579 return null; 2580 members ~= member; 2581 } 2582 } 2583 node.members = ownArray(members); 2584 mixin(nullCheck!`expect(tok!"}")`); 2585 return node; 2586 } 2587 2588 /** 2589 * Parses an EnumDeclaration 2590 * 2591 * $(GRAMMAR $(RULEDEF enumDeclaration): 2592 * $(LITERAL 'enum') $(LITERAL Identifier) ($(LITERAL ':') $(RULE type))? $(LITERAL ';') 2593 * | $(LITERAL 'enum') $(LITERAL Identifier) ($(LITERAL ':') $(RULE type))? $(RULE enumBody) 2594 * ;) 2595 */ 2596 EnumDeclaration parseEnumDeclaration() 2597 { 2598 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2599 auto node = allocate!EnumDeclaration; 2600 mixin(nullCheck!`expect(tok!"enum")`); 2601 mixin(tokenCheck!(`node.name`, `identifier`)); 2602 node.comment = comment; 2603 comment = null; 2604 if (currentIs(tok!";")) 2605 { 2606 advance(); 2607 return node; 2608 } 2609 if (currentIs(tok!":")) 2610 { 2611 advance(); // skip ':' 2612 mixin(nullCheck!`node.type = parseType()`); 2613 } 2614 mixin(nullCheck!`node.enumBody = parseEnumBody()`); 2615 return node; 2616 } 2617 2618 /** 2619 * Parses an EnumMember 2620 * 2621 * $(GRAMMAR $(RULEDEF enumMember): 2622 * $(LITERAL Identifier) 2623 * | $(LITERAL Identifier) $(LITERAL '=') $(RULE assignExpression) 2624 * ;) 2625 */ 2626 EnumMember parseEnumMember() 2627 { 2628 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2629 auto node = allocate!EnumMember; 2630 node.comment = current.comment; 2631 comment = null; 2632 2633 2634 while (moreTokens()) 2635 { 2636 if(currentIs(tok!"@")) { 2637 if(peek() !is null && (*peek()) == tok!"identifier" && (*peek()).text == "disable") { 2638 advance(); 2639 advance(); 2640 node.isDisabled = true; 2641 } else { 2642 AtAttribute atAttribute; 2643 mixin(nullCheck!`atAttribute = parseAtAttribute()`); 2644 if (atAttribute is null) { deallocate(node); break; } 2645 node.atAttributes ~= atAttribute; 2646 } 2647 } else if(currentIs(tok!"deprecated")) { 2648 mixin(nullCheck!`node.deprecated_ = parseDeprecated()`); 2649 } else { 2650 break; 2651 } 2652 } 2653 2654 2655 mixin(tokenCheck!(`node.name`, `identifier`)); 2656 if (currentIs(tok!"=")) 2657 { 2658 advance(); 2659 mixin(nullCheck!`node.assignExpression = parseAssignExpression()`); 2660 } 2661 return node; 2662 } 2663 2664 /** 2665 * Parses an EponymousTemplateDeclaration 2666 * 2667 * $(GRAMMAR $(RULEDEF eponymousTemplateDeclaration): 2668 * $(LITERAL 'enum') $(LITERAL Identifier) $(RULE templateParameters) $(LITERAL '=') $(RULE assignExpression) $(LITERAL ';') 2669 * ;) 2670 */ 2671 EponymousTemplateDeclaration parseEponymousTemplateDeclaration() 2672 { 2673 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2674 auto node = allocate!EponymousTemplateDeclaration; 2675 node.comment = comment; 2676 comment = null; 2677 advance(); // enum 2678 const ident = expect(tok!"identifier"); 2679 mixin(nullCheck!`ident`); 2680 node.name = *ident; 2681 mixin(nullCheck!`node.templateParameters = parseTemplateParameters()`); 2682 expect(tok!"="); 2683 node.assignExpression = parseAssignExpression(); 2684 if (node.assignExpression is null) 2685 mixin(nullCheck!`node.type = parseType()`); 2686 expect(tok!";"); 2687 return node; 2688 } 2689 2690 /** 2691 * Parses an EqualExpression 2692 * 2693 * $(GRAMMAR $(RULEDEF equalExpression): 2694 * $(RULE shiftExpression) ($(LITERAL '==') | $(LITERAL '!=')) $(RULE shiftExpression) 2695 * ;) 2696 */ 2697 EqualExpression parseEqualExpression(ExpressionNode shift = null) 2698 { 2699 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2700 auto node = allocate!EqualExpression; 2701 mixin(nullCheck!`node.left = shift is null ? parseShiftExpression() : shift`); 2702 if (currentIsOneOf(tok!"==", tok!"!=")) 2703 node.operator = advance().type; 2704 mixin(nullCheck!`node.right = parseShiftExpression()`); 2705 return node; 2706 } 2707 2708 /** 2709 * Parses an Expression 2710 * 2711 * $(GRAMMAR $(RULEDEF expression): 2712 * $(RULE assignExpression) ($(LITERAL ',') $(RULE assignExpression))* 2713 * ;) 2714 */ 2715 Expression parseExpression() 2716 { 2717 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2718 if (suppressedErrorCount > MAX_ERRORS) 2719 return null; 2720 if (!moreTokens()) 2721 { 2722 error("Expected expression instead of EOF"); 2723 return null; 2724 } 2725 return parseCommaSeparatedRule!(Expression, AssignExpression, true)(); 2726 } 2727 2728 /** 2729 * Parses an ExpressionStatement 2730 * 2731 * $(GRAMMAR $(RULEDEF expressionStatement): 2732 * $(RULE expression) $(LITERAL ';') 2733 * ;) 2734 */ 2735 ExpressionStatement parseExpressionStatement(Expression expression = null) 2736 { 2737 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2738 auto node = allocate!ExpressionStatement; 2739 node.expression = expression is null ? parseExpression() : expression; 2740 if (node.expression is null || expect(tok!";") is null) { deallocate(node); return null; } 2741 return node; 2742 } 2743 2744 /** 2745 * Parses a FinalSwitchStatement 2746 * 2747 * $(GRAMMAR $(RULEDEF finalSwitchStatement): 2748 * $(LITERAL 'final') $(RULE switchStatement) 2749 * ;) 2750 */ 2751 FinalSwitchStatement parseFinalSwitchStatement() 2752 { 2753 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2754 mixin(simpleParse!(FinalSwitchStatement, tok!"final", "switchStatement|parseSwitchStatement")); 2755 } 2756 2757 /** 2758 * Parses a Finally 2759 * 2760 * $(GRAMMAR $(RULEDEF finally): 2761 * $(LITERAL 'finally') $(RULE declarationOrStatement) 2762 * ;) 2763 */ 2764 Finally parseFinally() 2765 { 2766 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2767 auto node = allocate!Finally; 2768 mixin(nullCheck!`expect(tok!"finally")`); 2769 mixin(nullCheck!`node.declarationOrStatement = parseDeclarationOrStatement()`); 2770 return node; 2771 } 2772 2773 /** 2774 * Parses a ForStatement 2775 * 2776 * $(GRAMMAR $(RULEDEF forStatement): 2777 * $(LITERAL 'for') $(LITERAL '$(LPAREN)') ($(RULE declaration) | $(RULE statementNoCaseNoDefault)) $(RULE expression)? $(LITERAL ';') $(RULE expression)? $(LITERAL '$(RPAREN)') $(RULE declarationOrStatement) 2778 * ;) 2779 */ 2780 ForStatement parseForStatement() 2781 { 2782 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2783 auto node = allocate!ForStatement; 2784 mixin(nullCheck!`expect(tok!"for")`); 2785 if (!moreTokens) node.startIndex = current().index; 2786 mixin(nullCheck!`expect(tok!"(")`); 2787 2788 if (currentIs(tok!";")) 2789 advance(); 2790 else 2791 mixin(nullCheck!`node.initialization = parseDeclarationOrStatement()`); 2792 2793 if (currentIs(tok!";")) 2794 advance(); 2795 else 2796 { 2797 mixin(nullCheck!`node.test = parseExpression()`); 2798 expect(tok!";"); 2799 } 2800 2801 if (!currentIs(tok!")")) 2802 mixin(nullCheck!`node.increment = parseExpression()`); 2803 2804 mixin(nullCheck!`expect(tok!")")`); 2805 if (currentIs(tok!"}")) 2806 { 2807 error("Statement expected", false); 2808 return node; // this line makes DCD better 2809 } 2810 mixin(nullCheck!`node.declarationOrStatement = parseDeclarationOrStatement()`); 2811 return node; 2812 } 2813 2814 /** 2815 * Parses a ForeachStatement 2816 * 2817 * $(GRAMMAR $(RULEDEF foreachStatement): 2818 * ($(LITERAL 'foreach') | $(LITERAL 'foreach_reverse')) $(LITERAL '$(LPAREN)') $(RULE foreachTypeList) $(LITERAL ';') $(RULE expression) $(LITERAL '$(RPAREN)') $(RULE declarationOrStatement) 2819 * | ($(LITERAL 'foreach') | $(LITERAL 'foreach_reverse')) $(LITERAL '$(LPAREN)') $(RULE foreachType) $(LITERAL ';') $(RULE expression) $(LITERAL '..') $(RULE expression) $(LITERAL '$(RPAREN)') $(RULE declarationOrStatement) 2820 * ;) 2821 */ 2822 ForeachStatement parseForeachStatement() 2823 { 2824 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2825 ForeachStatement node = allocate!ForeachStatement; 2826 if (currentIsOneOf(tok!"foreach", tok!"foreach_reverse")) 2827 node.type = advance().type; 2828 else 2829 { 2830 error(`"foreach" or "foreach_reverse" expected`); 2831 deallocate(node); 2832 return null; 2833 } 2834 node.startIndex = current().index; 2835 mixin(nullCheck!`expect(tok!"(")`); 2836 ForeachTypeList feType = parseForeachTypeList(); 2837 mixin(nullCheck!`feType`); 2838 immutable bool canBeRange = feType.items.length == 1; 2839 2840 mixin(nullCheck!`expect(tok!";")`); 2841 mixin(nullCheck!`node.low = parseExpression()`); 2842 mixin(nullCheck!`node.low`); 2843 if (currentIs(tok!"..")) 2844 { 2845 if (!canBeRange) 2846 { 2847 error(`Cannot have more than one foreach variable for a foreach range statement`); 2848 return null; 2849 } 2850 advance(); 2851 mixin(nullCheck!`node.high = parseExpression()`); 2852 node.foreachType = feType.items[0]; 2853 mixin(nullCheck!`node.high`); 2854 } 2855 else 2856 { 2857 node.foreachTypeList = feType; 2858 } 2859 mixin(nullCheck!`expect(tok!")")`); 2860 if (currentIs(tok!"}")) 2861 { 2862 error("Statement expected", false); 2863 return node; // this line makes DCD better 2864 } 2865 mixin(nullCheck!`node.declarationOrStatement = parseDeclarationOrStatement()`); 2866 return node; 2867 } 2868 2869 /** 2870 * Parses a ForeachType 2871 * 2872 * $(GRAMMAR $(RULEDEF foreachType): 2873 * $(LITERAL 'ref')? $(RULE typeConstructors)? $(RULE type)? $(LITERAL Identifier) 2874 * | $(RULE typeConstructors)? $(LITERAL 'ref')? $(RULE type)? $(LITERAL Identifier) 2875 * ;) 2876 */ 2877 ForeachType parseForeachType() 2878 { 2879 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2880 auto node = allocate!ForeachType; 2881 if (currentIs(tok!"ref")) 2882 { 2883 node.isRef = true; 2884 advance(); 2885 } 2886 if (currentIsOneOf(tok!"const", tok!"immutable", 2887 tok!"inout", tok!"shared") && !peekIs(tok!"(")) 2888 { 2889 trace("\033[01;36mType constructor"); 2890 if ((node.typeConstructors = parseTypeConstructors()) is null) 2891 return null; 2892 } 2893 if (currentIs(tok!"ref")) 2894 { 2895 node.isRef = true; 2896 advance(); 2897 } 2898 if (currentIs(tok!"identifier") && peekIsOneOf(tok!",", tok!";")) 2899 { 2900 node.identifier = advance(); 2901 return node; 2902 } 2903 if ((node.type = parseType()) is null) { deallocate(node); return null; } 2904 const ident = expect(tok!"identifier"); 2905 if (ident is null) { deallocate(node); return null; } 2906 node.identifier = *ident; 2907 return node; 2908 } 2909 2910 /** 2911 * Parses a ForeachTypeList 2912 * 2913 * $(GRAMMAR $(RULEDEF foreachTypeList): 2914 * $(RULE foreachType) ($(LITERAL ',') $(RULE foreachType))* 2915 * ;) 2916 */ 2917 ForeachTypeList parseForeachTypeList() 2918 { 2919 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2920 return parseCommaSeparatedRule!(ForeachTypeList, ForeachType)(); 2921 } 2922 2923 /** 2924 * Parses a FunctionAttribute 2925 * 2926 * $(GRAMMAR $(RULEDEF functionAttribute): 2927 * $(RULE atAttribute) 2928 * | $(LITERAL 'pure') 2929 * | $(LITERAL 'nothrow') 2930 * ;) 2931 */ 2932 FunctionAttribute parseFunctionAttribute(bool validate = true) 2933 { 2934 auto node = allocate!FunctionAttribute; 2935 switch (current.type) 2936 { 2937 case tok!"@": 2938 mixin(nullCheck!`node.atAttribute = parseAtAttribute()`); 2939 break; 2940 case tok!"pure": 2941 case tok!"nothrow": 2942 node.token = advance(); 2943 break; 2944 default: 2945 if (validate) 2946 error(`@attribute, "pure", or "nothrow" expected`); 2947 deallocate(node); 2948 return null; 2949 } 2950 return node; 2951 } 2952 2953 /** 2954 * Parses a FunctionBody 2955 * 2956 * $(GRAMMAR $(RULEDEF functionBody): 2957 * $(RULE blockStatement) 2958 * | ($(RULE inStatement) | $(RULE outStatement) | $(RULE outStatement) $(RULE inStatement) | $(RULE inStatement) $(RULE outStatement))? $(RULE bodyStatement)? 2959 * ;) 2960 */ 2961 FunctionBody parseFunctionBody() 2962 { 2963 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 2964 auto node = allocate!FunctionBody; 2965 if (currentIs(tok!";")) 2966 { 2967 advance(); 2968 return node; 2969 } 2970 else if (currentIs(tok!"{")) 2971 { 2972 2973 hackFunctionBody(); 2974 auto fb = new FunctionBody(); 2975 fb.hadABody = true; 2976 return fb; 2977 2978 if ((node.blockStatement = parseBlockStatement()) is null) 2979 { 2980 deallocate(node); 2981 return null; 2982 } 2983 } 2984 else if (currentIs(tok!"=>")) 2985 { 2986 advance(); 2987 parseAssignExpression(); 2988 expect(tok!";"); 2989 auto fb = new FunctionBody(); 2990 fb.hadABody = true; 2991 return fb; 2992 } 2993 else 2994 { 2995 while(currentIs(tok!"in") || currentIs(tok!"out")) { 2996 if (currentIs(tok!"in")) 2997 { 2998 mixin(nullCheck!`node.inStatement = parseInStatement()`); 2999 } 3000 else if (currentIs(tok!"out")) 3001 { 3002 mixin(nullCheck!`node.outStatement = parseOutStatement()`); 3003 } 3004 } 3005 // Allow function bodies without body statements because this is 3006 // valid inside of interfaces. 3007 if (currentIs(tok!"identifier")) // was tok!"body" 3008 mixin(nullCheck!`node.bodyStatement = parseBodyStatement()`); 3009 else if(currentIs(tok!"do")) 3010 mixin(nullCheck!`node.bodyStatement = parseBodyDoStatement()`); 3011 else if(currentIs(tok!"{")) { 3012 hackFunctionBody(); 3013 3014 auto fb = new FunctionBody(); 3015 fb.hadABody = true; 3016 return fb; 3017 } else if(currentIs(tok!"=>")) { 3018 advance(); 3019 parseAssignExpression(); 3020 expect(tok!";"); 3021 auto fb = new FunctionBody(); 3022 fb.hadABody = true; 3023 return fb; 3024 } 3025 } 3026 if(minimize_memory) { 3027 .destroy(node.blockStatement); 3028 .destroy(node.bodyStatement); 3029 } 3030 return node; 3031 } 3032 3033 /** 3034 * Parses a FunctionCallExpression 3035 * 3036 * $(GRAMMAR $(RULEDEF functionCallExpression): 3037 * $(RULE symbol) $(RULE arguments) 3038 * $(RULE unaryExpression) $(RULE arguments) 3039 * | $(RULE type) $(RULE arguments) 3040 * ;) 3041 */ 3042 FunctionCallExpression parseFunctionCallExpression(UnaryExpression unary = null) 3043 { 3044 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 3045 auto node = allocate!FunctionCallExpression; 3046 switch (current.type) 3047 { 3048 case tok!"const": 3049 case tok!"immutable": 3050 case tok!"inout": 3051 case tok!"shared": 3052 case tok!"scope": 3053 case tok!"pure": 3054 case tok!"nothrow": 3055 mixin(nullCheck!`node.type = parseType()`); 3056 mixin(nullCheck!`node.arguments = parseArguments()`); 3057 break; 3058 default: 3059 if (unary !is null) 3060 node.unaryExpression = unary; 3061 else 3062 mixin(nullCheck!`node.unaryExpression = parseUnaryExpression()`); 3063 if (currentIs(tok!"!")) 3064 mixin(nullCheck!`node.templateArguments = parseTemplateArguments()`); 3065 if (unary !is null) 3066 mixin(nullCheck!`node.arguments = parseArguments()`); 3067 } 3068 return node; 3069 } 3070 3071 /** 3072 * Parses a FunctionDeclaration 3073 * 3074 * $(GRAMMAR $(RULEDEF functionDeclaration): 3075 * ($(RULE storageClass)+ | $(RULE _type)) $(LITERAL Identifier) $(RULE parameters) $(RULE memberFunctionAttribute)* ($(RULE functionBody) | $(LITERAL ';')) 3076 * | ($(RULE storageClass)+ | $(RULE _type)) $(LITERAL Identifier) $(RULE templateParameters) $(RULE parameters) $(RULE memberFunctionAttribute)* $(RULE constraint)? ($(RULE functionBody) | $(LITERAL ';')) 3077 * ;) 3078 */ 3079 FunctionDeclaration parseFunctionDeclaration(Type type = null, bool isAuto = false, 3080 Attribute[] attributes = null) 3081 { 3082 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 3083 auto node = allocate!FunctionDeclaration; 3084 node.comment = comment; 3085 comment = null; 3086 MemberFunctionAttribute[] memberFunctionAttributes; 3087 3088 node.attributes = attributes; 3089 3090 if (isAuto) 3091 { 3092 StorageClass[] storageClasses; 3093 while (isStorageClass()) 3094 { 3095 auto s = parseStorageClass(); 3096 if (s is null) 3097 { 3098 deallocate(node); 3099 return null; 3100 } 3101 else 3102 storageClasses ~= s; 3103 } 3104 node.storageClasses = storageClasses; 3105 3106 3107 foreach (a; node.attributes) 3108 { 3109 if (a.attribute == tok!"auto") 3110 node.hasAuto = true; 3111 else if (a.attribute == tok!"ref") 3112 node.hasRef = true; 3113 else 3114 continue; 3115 } 3116 } 3117 else 3118 { 3119 while (moreTokens() && currentIsMemberFunctionAttribute()) 3120 memberFunctionAttributes ~= parseMemberFunctionAttribute(); 3121 3122 node.returnType = type is null ? parseType() : type; 3123 } 3124 3125 const ident = expect(tok!"identifier"); 3126 if (ident is null) { deallocate(node); return null; } 3127 3128 node.name = *ident; 3129 3130 if (!currentIs(tok!"(")) 3131 { 3132 error(`"(" expected`); 3133 return null; 3134 } 3135 3136 assert (currentIs(tok!"(")); 3137 const p = peekPastParens(); 3138 immutable bool isTemplate = p !is null && p.type == tok!"("; 3139 3140 if (isTemplate) 3141 mixin(nullCheck!`node.templateParameters = parseTemplateParameters()`); 3142 3143 mixin(nullCheck!`node.parameters = parseParameters()`); 3144 if (node.parameters is null) { deallocate(node); return null; } 3145 3146 /+ 3147 if(comment) { 3148 import std.stdio; writeln("omgomg ", comment); 3149 } 3150 +/ 3151 3152 while (moreTokens() && currentIsMemberFunctionAttribute()) 3153 memberFunctionAttributes ~= parseMemberFunctionAttribute(); 3154 3155 if (isTemplate && currentIs(tok!"if")) 3156 mixin(nullCheck!`node.constraint = parseConstraint()`); 3157 3158 3159 if (currentIs(tok!";")) 3160 advance(); 3161 else 3162 mixin(nullCheck!`node.functionBody = parseFunctionBody()`); 3163 node.memberFunctionAttributes = ownArray(memberFunctionAttributes); 3164 return node; 3165 } 3166 3167 /** 3168 * Parses a FunctionLiteralExpression 3169 * 3170 * $(GRAMMAR $(RULEDEF functionLiteralExpression): 3171 * (($(LITERAL 'function') | $(LITERAL 'delegate')) $(RULE type)?)? ($(RULE parameters) $(RULE functionAttribute)*)? $(RULE functionBody) 3172 * ;) 3173 */ 3174 FunctionLiteralExpression parseFunctionLiteralExpression() 3175 { 3176 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 3177 auto node = allocate!FunctionLiteralExpression; 3178 if (currentIsOneOf(tok!"function", tok!"delegate")) 3179 { 3180 node.functionOrDelegate = advance().type; 3181 if (!currentIsOneOf(tok!"(", tok!"in", tok!"do", // tok!"body" should be here too but awkard 3182 tok!"out", tok!"{")) 3183 { 3184 mixin(nullCheck!`node.type = parseType()`); 3185 if (node.type is null) { deallocate(node); return null; } 3186 } 3187 } 3188 if (currentIs(tok!"(")) 3189 { 3190 mixin(nullCheck!`node.parameters = parseParameters()`); 3191 if (node.parameters is null) { deallocate(node); return null; } 3192 MemberFunctionAttribute[] memberFunctionAttributes; 3193 while (currentIsMemberFunctionAttribute()) 3194 { 3195 auto attr = parseMemberFunctionAttribute(); 3196 if (attr is null) 3197 break; 3198 else 3199 memberFunctionAttributes ~= attr; 3200 } 3201 node.memberFunctionAttributes = ownArray(memberFunctionAttributes); 3202 } 3203 if ((node.functionBody = parseFunctionBody()) is null) { deallocate(node); return null; } 3204 return node; 3205 } 3206 3207 /** 3208 * Parses a GotoStatement 3209 * 3210 * $(GRAMMAR $(RULEDEF gotoStatement): 3211 * $(LITERAL 'goto') ($(LITERAL Identifier) | $(LITERAL 'default') | $(LITERAL 'case') $(RULE expression)?) $(LITERAL ';') 3212 * ;) 3213 */ 3214 GotoStatement parseGotoStatement() 3215 { 3216 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 3217 auto node = allocate!GotoStatement; 3218 if (expect(tok!"goto") is null) { deallocate(node); return null; } 3219 switch (current.type) 3220 { 3221 case tok!"identifier": 3222 case tok!"default": 3223 node.label = advance(); 3224 break; 3225 case tok!"case": 3226 node.label = advance(); 3227 if (!currentIs(tok!";")) 3228 mixin(nullCheck!`node.expression = parseExpression()`); 3229 break; 3230 default: 3231 error(`Identifier, "default", or "case" expected`); 3232 return null; 3233 } 3234 if (expect(tok!";") is null) { deallocate(node); return null; } 3235 return node; 3236 } 3237 3238 /** 3239 * Parses an IdentifierChain 3240 * 3241 * $(GRAMMAR $(RULEDEF identifierChain): 3242 * $(LITERAL Identifier) ($(LITERAL '.') $(LITERAL Identifier))* 3243 * ;) 3244 */ 3245 IdentifierChain parseIdentifierChain() 3246 { 3247 auto node = allocate!IdentifierChain; 3248 Token[] identifiers; 3249 while (moreTokens()) 3250 { 3251 const ident = expect(tok!"identifier"); 3252 if (ident is null) { deallocate(node); return null; } 3253 identifiers ~= *ident; 3254 if (currentIs(tok!".")) 3255 { 3256 advance(); 3257 continue; 3258 } 3259 else 3260 break; 3261 } 3262 node.identifiers = ownArray(identifiers); 3263 return node; 3264 } 3265 3266 /** 3267 * Parses an IdentifierList 3268 * 3269 * $(GRAMMAR $(RULEDEF identifierList): 3270 * $(LITERAL Identifier) ($(LITERAL ',') $(LITERAL Identifier))* 3271 * ;) 3272 */ 3273 IdentifierList parseIdentifierList() 3274 { 3275 auto node = allocate!IdentifierList; 3276 Token[] identifiers; 3277 while (moreTokens()) 3278 { 3279 const ident = expect(tok!"identifier"); 3280 if (ident is null) { deallocate(node); return null; } 3281 identifiers ~= *ident; 3282 if (currentIs(tok!",")) 3283 { 3284 advance(); 3285 continue; 3286 } 3287 else 3288 break; 3289 } 3290 node.identifiers = ownArray(identifiers); 3291 return node; 3292 } 3293 3294 /** 3295 * Parses an IdentifierOrTemplateChain 3296 * 3297 * $(GRAMMAR $(RULEDEF identifierOrTemplateChain): 3298 * $(RULE identifierOrTemplateInstance) ($(LITERAL '.') $(RULE identifierOrTemplateInstance))* 3299 * ;) 3300 */ 3301 IdentifierOrTemplateChain parseIdentifierOrTemplateChain() 3302 { 3303 auto node = allocate!IdentifierOrTemplateChain; 3304 IdentifierOrTemplateInstance[] identifiersOrTemplateInstances; 3305 while (moreTokens()) 3306 { 3307 auto t = parseIdentifierOrTemplateInstance(); 3308 if (t !is null) 3309 identifiersOrTemplateInstances ~= t; 3310 else 3311 break; 3312 if (!currentIs(tok!".")) 3313 break; 3314 else 3315 advance(); 3316 } 3317 node.identifiersOrTemplateInstances = ownArray(identifiersOrTemplateInstances); 3318 return node; 3319 } 3320 3321 /** 3322 * Parses an IdentifierOrTemplateInstance 3323 * 3324 * $(GRAMMAR $(RULEDEF identifierOrTemplateInstance): 3325 * $(LITERAL Identifier) 3326 * | $(RULE templateInstance) 3327 * ;) 3328 */ 3329 IdentifierOrTemplateInstance parseIdentifierOrTemplateInstance() 3330 { 3331 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 3332 auto node = allocate!IdentifierOrTemplateInstance; 3333 if (peekIs(tok!"!") && !startsWith(tok!"identifier", 3334 tok!"!", tok!"is") 3335 && !startsWith(tok!"identifier", tok!"!", tok!"in")) 3336 { 3337 mixin(nullCheck!`node.templateInstance = parseTemplateInstance()`); 3338 } 3339 else 3340 { 3341 const ident = expect(tok!"identifier"); 3342 if (ident is null) { deallocate(node); return null; } 3343 node.identifier = *ident; 3344 } 3345 return node; 3346 } 3347 3348 /** 3349 * Parses an IdentityExpression 3350 * 3351 * $(GRAMMAR $(RULEDEF identityExpression): 3352 * $(RULE shiftExpression) ($(LITERAL 'is') | ($(LITERAL '!') $(LITERAL 'is'))) $(RULE shiftExpression) 3353 * ;) 3354 */ 3355 ExpressionNode parseIdentityExpression(ExpressionNode shift = null) 3356 { 3357 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 3358 auto node = allocate!IdentityExpression; 3359 node.left = shift is null ? parseShiftExpression() : shift; 3360 if (currentIs(tok!"!")) 3361 { 3362 advance(); 3363 node.negated = true; 3364 } 3365 if (expect(tok!"is") is null) { deallocate(node); return null; } 3366 mixin(nullCheck!`node.right = parseShiftExpression()`); 3367 return node; 3368 } 3369 3370 /** 3371 * Parses an IfStatement 3372 * 3373 * $(GRAMMAR $(RULEDEF ifStatement): 3374 * $(LITERAL 'if') $(LITERAL '$(LPAREN)') $(RULE ifCondition) $(LITERAL '$(RPAREN)') $(RULE declarationOrStatement) ($(LITERAL 'else') $(RULE declarationOrStatement))? 3375 *$(RULEDEF ifCondition): 3376 * $(LITERAL 'auto') $(LITERAL Identifier) $(LITERAL '=') $(RULE expression) 3377 * | $(RULE type) $(LITERAL Identifier) $(LITERAL '=') $(RULE expression) 3378 * | $(RULE expression) 3379 * ;) 3380 */ 3381 IfStatement parseIfStatement() 3382 { 3383 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 3384 auto node = allocate!IfStatement; 3385 node.line = current().line; 3386 node.column = current().column; 3387 if (expect(tok!"if") is null) { deallocate(node); return null; } 3388 node.startIndex = current().index; 3389 if (expect(tok!"(") is null) { deallocate(node); return null; } 3390 3391 if (currentIs(tok!"auto") || currentIs(tok!"const") || currentIs(tok!"immutable") || currentIs(tok!"inout") || currentIs(tok!"shared")) 3392 { 3393 while(currentIs(tok!"auto") || currentIs(tok!"const") || currentIs(tok!"immutable") || currentIs(tok!"inout") || currentIs(tok!"shared")) 3394 advance(); 3395 /* 3396 3397 auto b = setBookmark(); 3398 auto t = parseType(); 3399 3400 if(t is null) 3401 goToBookmark(b); 3402 */ 3403 3404 const i = expect(tok!"identifier"); 3405 if (i !is null) 3406 node.identifier = *i; 3407 expect(tok!"="); 3408 mixin(nullCheck!`node.expression = parseExpression()`); 3409 } 3410 else 3411 { 3412 auto b = setBookmark(); 3413 auto t = parseType(); 3414 if (t is null || !currentIs(tok!"identifier") 3415 || !peekIs(tok!"=")) 3416 { 3417 goToBookmark(b); 3418 mixin(nullCheck!`node.expression = parseExpression()`); 3419 } 3420 else 3421 { 3422 goToBookmark(b); 3423 mixin(nullCheck!`node.type = parseType()`); 3424 const i = expect(tok!"identifier"); 3425 if (i !is null) 3426 node.identifier = *i; 3427 expect(tok!"="); 3428 mixin(nullCheck!`node.expression = parseExpression()`); 3429 } 3430 } 3431 3432 if (expect(tok!")") is null) { deallocate(node); return null; } 3433 if (currentIs(tok!"}")) 3434 { 3435 error("Statement expected", false); 3436 return node; // this line makes DCD better 3437 } 3438 mixin(nullCheck!`node.thenStatement = parseDeclarationOrStatement()`); 3439 if (currentIs(tok!"else")) 3440 { 3441 advance(); 3442 mixin(nullCheck!`node.elseStatement = parseDeclarationOrStatement()`); 3443 } 3444 return node; 3445 } 3446 3447 /** 3448 * Parses an ImportBind 3449 * 3450 * $(GRAMMAR $(RULEDEF importBind): 3451 * $(LITERAL Identifier) ($(LITERAL '=') $(LITERAL Identifier))? 3452 * ;) 3453 */ 3454 ImportBind parseImportBind() 3455 { 3456 auto node = allocate!ImportBind; 3457 const ident = expect(tok!"identifier"); 3458 if (ident is null) { deallocate(node); return null; } 3459 node.left = *ident; 3460 if (currentIs(tok!"=")) 3461 { 3462 advance(); 3463 const id = expect(tok!"identifier"); 3464 if (id is null) { deallocate(node); return null; } 3465 node.right = *id; 3466 } 3467 return node; 3468 } 3469 3470 /** 3471 * Parses ImportBindings 3472 * 3473 * $(GRAMMAR $(RULEDEF importBindings): 3474 * $(RULE singleImport) $(LITERAL ':') $(RULE importBind) ($(LITERAL ',') $(RULE importBind))* 3475 * ;) 3476 */ 3477 ImportBindings parseImportBindings(SingleImport singleImport) 3478 { 3479 auto node = allocate!ImportBindings; 3480 node.singleImport = singleImport is null ? parseSingleImport() : singleImport; 3481 if (expect(tok!":") is null) { deallocate(node); return null; } 3482 ImportBind[] importBinds; 3483 while (moreTokens()) 3484 { 3485 auto b = parseImportBind(); 3486 if (b !is null) 3487 { 3488 importBinds ~= b; 3489 if (currentIs(tok!",")) 3490 advance(); 3491 else 3492 break; 3493 } 3494 else 3495 break; 3496 } 3497 node.importBinds = ownArray(importBinds); 3498 return node; 3499 } 3500 3501 /** 3502 * Parses an ImportDeclaration 3503 * 3504 * $(GRAMMAR $(RULEDEF importDeclaration): 3505 * $(LITERAL 'import') $(RULE singleImport) ($(LITERAL ',') $(RULE singleImport))* ($(LITERAL ',') $(RULE importBindings))? $(LITERAL ';') 3506 * | $(LITERAL 'import') $(RULE importBindings) $(LITERAL ';') 3507 * ;) 3508 */ 3509 ImportDeclaration parseImportDeclaration() 3510 { 3511 auto node = allocate!ImportDeclaration; 3512 if (expect(tok!"import") is null) { deallocate(node); return null; } 3513 3514 node.comment = comment; 3515 comment = null; 3516 node.line = current.line; 3517 3518 SingleImport si = parseSingleImport(); 3519 if (currentIs(tok!":")) 3520 node.importBindings = parseImportBindings(si); 3521 else 3522 { 3523 SingleImport[] singleImports; 3524 singleImports ~= si; 3525 if (currentIs(tok!",")) 3526 { 3527 advance(); 3528 while (moreTokens()) 3529 { 3530 auto single = parseSingleImport(); 3531 if (single is null) 3532 return null; 3533 if (currentIs(tok!":")) 3534 { 3535 node.importBindings = parseImportBindings(single); 3536 break; 3537 } 3538 else 3539 { 3540 singleImports ~= single; 3541 if (currentIs(tok!",")) 3542 advance(); 3543 else 3544 break; 3545 } 3546 } 3547 } 3548 node.singleImports = ownArray(singleImports); 3549 } 3550 if (expect(tok!";") is null) { deallocate(node); return null; } 3551 return node; 3552 } 3553 3554 /** 3555 * Parses an ImportExpression 3556 * 3557 * $(GRAMMAR $(RULEDEF importExpression): 3558 * $(LITERAL 'import') $(LITERAL '$(LPAREN)') $(RULE assignExpression) $(LITERAL '$(RPAREN)') 3559 * ;) 3560 */ 3561 ImportExpression parseImportExpression() 3562 { 3563 auto node = allocate!ImportExpression; 3564 if (expect(tok!"import") is null) { deallocate(node); return null; } 3565 if (expect(tok!"(") is null) { deallocate(node); return null; } 3566 mixin(nullCheck!`node.assignExpression = parseAssignExpression()`); 3567 if (expect(tok!")") is null) { deallocate(node); return null; } 3568 return node; 3569 } 3570 3571 /** 3572 * Parses an Index 3573 * 3574 * $(GRAMMAR $(RULEDEF index): 3575 * $(RULE assignExpression) ($(LITERAL '..') $(RULE assignExpression))? 3576 * ; 3577 * ) 3578 */ 3579 Index parseIndex() 3580 { 3581 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 3582 auto node = allocate!Index(); 3583 mixin(nullCheck!`node.low = parseAssignExpression()`); 3584 if (currentIs(tok!"..")) 3585 { 3586 advance(); 3587 mixin(nullCheck!`node.high = parseAssignExpression()`); 3588 } 3589 return node; 3590 } 3591 3592 /** 3593 * Parses an IndexExpression 3594 * 3595 * $(GRAMMAR $(RULEDEF indexExpression): 3596 * $(RULE unaryExpression) $(LITERAL '[') $(LITERAL ']') 3597 * | $(RULE unaryExpression) $(LITERAL '[') $(RULE index) ($(LITERAL ',') $(RULE index))* $(LITERAL ']') 3598 * ; 3599 * ) 3600 */ 3601 IndexExpression parseIndexExpression(UnaryExpression unaryExpression = null) 3602 { 3603 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 3604 auto node = allocate!IndexExpression; 3605 node.unaryExpression = unaryExpression is null ? parseUnaryExpression() : unaryExpression; 3606 mixin(nullCheck!`node.unaryExpression`); 3607 mixin(nullCheck!`expect(tok!"[")`); 3608 Index[] indexes; 3609 while (true) 3610 { 3611 if (!moreTokens()) 3612 { 3613 error("Expected unary expression instead of EOF"); 3614 deallocate(node); 3615 return null; 3616 } 3617 if (currentIs(tok!"]")) 3618 break; 3619 auto index = parseIndex(); 3620 mixin(nullCheck!`index`); 3621 indexes ~= index; 3622 if (currentIs(tok!",")) 3623 advance(); 3624 else 3625 break; 3626 } 3627 node.indexes = ownArray(indexes); 3628 advance(); // ] 3629 return node; 3630 } 3631 3632 /** 3633 * Parses an InExpression 3634 * 3635 * $(GRAMMAR $(RULEDEF inExpression): 3636 * $(RULE shiftExpression) ($(LITERAL 'in') | ($(LITERAL '!') $(LITERAL 'in'))) $(RULE shiftExpression) 3637 * ;) 3638 */ 3639 ExpressionNode parseInExpression(ExpressionNode shift = null) 3640 { 3641 auto node = allocate!InExpression; 3642 node.left = shift is null ? parseShiftExpression() : shift; 3643 if (currentIs(tok!"!")) 3644 { 3645 node.negated = true; 3646 advance(); 3647 } 3648 if (expect(tok!"in") is null) { deallocate(node); return null; } 3649 mixin(nullCheck!`node.right = parseShiftExpression()`); 3650 return node; 3651 } 3652 3653 /** 3654 * Parses an InStatement 3655 * 3656 * $(GRAMMAR $(RULEDEF inStatement): 3657 * $(LITERAL 'in') $(RULE blockStatement) 3658 * ;) 3659 */ 3660 InStatement parseInStatement() 3661 { 3662 auto node = allocate!InStatement; 3663 const i = expect(tok!"in"); 3664 mixin(nullCheck!`i`); 3665 node.inTokenLocation = i.index; 3666 if(currentIs(tok!"(")) { 3667 advance(); 3668 mixin(nullCheck!`node.expression = parseExpression()`); 3669 if (node.expression is null) 3670 return null; 3671 version(none) 3672 if(currentIs(tok!",")) { 3673 advance(); 3674 parseExpression(); // FIXME: probably should store this but it is the string message 3675 3676 } 3677 expect(tok!")"); 3678 } else { 3679 mixin(nullCheck!`node.blockStatement = parseBlockStatement()`); 3680 if (node.blockStatement is null) 3681 return null; 3682 } 3683 return node; 3684 } 3685 3686 /** 3687 * Parses an Initializer 3688 * 3689 * $(GRAMMAR $(RULEDEF initializer): 3690 * $(LITERAL 'void') 3691 * | $(RULE nonVoidInitializer) 3692 * ;) 3693 */ 3694 Initializer parseInitializer() 3695 { 3696 auto node = allocate!Initializer; 3697 if (currentIs(tok!"void") && peekIsOneOf(tok!",", tok!";")) 3698 advance(); 3699 else 3700 mixin(nullCheck!`node.nonVoidInitializer = parseNonVoidInitializer()`); 3701 return node; 3702 } 3703 3704 /** 3705 * Parses an InterfaceDeclaration 3706 * 3707 * $(GRAMMAR $(RULEDEF interfaceDeclaration): 3708 * $(LITERAL 'interface') $(LITERAL Identifier) $(LITERAL ';') 3709 * | $(LITERAL 'interface') $(LITERAL Identifier) ($(LITERAL ':') $(RULE baseClassList))? $(RULE structBody) 3710 * | $(LITERAL 'interface') $(LITERAL Identifier) $(RULE templateParameters) $(RULE constraint)? ($(LITERAL ':') $(RULE baseClassList))? $(RULE structBody) 3711 * | $(LITERAL 'interface') $(LITERAL Identifier) $(RULE templateParameters) ($(LITERAL ':') $(RULE baseClassList))? $(RULE constraint)? $(RULE structBody) 3712 * ;) 3713 */ 3714 InterfaceDeclaration parseInterfaceDeclaration() 3715 { 3716 auto node = allocate!InterfaceDeclaration; 3717 expect(tok!"interface"); 3718 mixin(PARSE_INTERFACE_OR_CLASS); 3719 } 3720 3721 /** 3722 * Parses an Invariant 3723 * 3724 * $(GRAMMAR $(RULEDEF invariant): 3725 * $(LITERAL 'invariant') ($(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)'))? $(RULE blockStatement) 3726 * ;) 3727 */ 3728 Invariant parseInvariant() 3729 { 3730 auto node = allocate!Invariant; 3731 node.index = current.index; 3732 node.line = current.line; 3733 if (expect(tok!"invariant") is null) { deallocate(node); return null; } 3734 if (currentIs(tok!"(")) 3735 { 3736 advance(); 3737 if (expect(tok!")") is null) { deallocate(node); return null; } 3738 } 3739 if ((node.blockStatement = parseBlockStatement()) is null) { deallocate(node); return null; } 3740 return node; 3741 } 3742 3743 /** 3744 * Parses an IsExpression 3745 * 3746 * $(GRAMMAR $(RULEDEF isExpression): 3747 * $(LITERAL'is') $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL identifier)? $(LITERAL '$(RPAREN)') 3748 * $(LITERAL'is') $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL identifier)? $(LITERAL ':') $(RULE typeSpecialization) $(LITERAL '$(RPAREN)') 3749 * $(LITERAL'is') $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL identifier)? $(LITERAL '=') $(RULE typeSpecialization) $(LITERAL '$(RPAREN)') 3750 * $(LITERAL'is') $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL identifier)? $(LITERAL ':') $(RULE typeSpecialization) $(LITERAL ',') $(RULE templateParameterList) $(LITERAL '$(RPAREN)') 3751 * $(LITERAL'is') $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL identifier)? $(LITERAL '=') $(RULE typeSpecialization) $(LITERAL ',') $(RULE templateParameterList) $(LITERAL '$(RPAREN)') 3752 * ;) 3753 */ 3754 IsExpression parseIsExpression() 3755 { 3756 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 3757 auto node = allocate!IsExpression; 3758 if (expect(tok!"is") is null) { deallocate(node); return null; } 3759 if (expect(tok!"(") is null) { deallocate(node); return null; } 3760 mixin(nullCheck!`node.type = parseType()`); 3761 if (node.type is null) { deallocate(node); return null; } 3762 if (currentIs(tok!"identifier")) 3763 node.identifier = advance(); 3764 if (currentIsOneOf(tok!"==", tok!":")) 3765 { 3766 node.equalsOrColon = advance().type; 3767 mixin(nullCheck!`node.typeSpecialization = parseTypeSpecialization()`); 3768 if (currentIs(tok!",")) 3769 { 3770 advance(); 3771 mixin(nullCheck!`node.templateParameterList = parseTemplateParameterList()`); 3772 } 3773 } 3774 if (expect(tok!")") is null) { deallocate(node); return null; } 3775 return node; 3776 } 3777 3778 /** 3779 * Parses a KeyValuePair 3780 * 3781 * $(GRAMMAR $(RULEDEF keyValuePair): 3782 * $(RULE assignExpression) $(LITERAL ':') $(RULE assignExpression) 3783 * ;) 3784 */ 3785 KeyValuePair parseKeyValuePair() 3786 { 3787 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 3788 auto node = allocate!KeyValuePair; 3789 mixin(nullCheck!`node.key = parseAssignExpression()`); 3790 if (expect(tok!":") is null) { deallocate(node); return null; } 3791 mixin(nullCheck!`node.value = parseAssignExpression()`); 3792 return node; 3793 } 3794 3795 /** 3796 * Parses KeyValuePairs 3797 * 3798 * $(GRAMMAR $(RULEDEF keyValuePairs): 3799 * $(RULE keyValuePair) ($(LITERAL ',') $(RULE keyValuePair))* $(LITERAL ',')? 3800 * ;) 3801 */ 3802 KeyValuePairs parseKeyValuePairs() 3803 { 3804 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 3805 auto node = allocate!KeyValuePairs; 3806 KeyValuePair[] keyValuePairs; 3807 while (moreTokens()) 3808 { 3809 auto kvPair = parseKeyValuePair(); 3810 if (kvPair !is null) 3811 keyValuePairs ~= kvPair; 3812 if (currentIs(tok!",")) 3813 { 3814 advance(); 3815 if (currentIs(tok!"]")) 3816 break; 3817 } 3818 else 3819 break; 3820 } 3821 node.keyValuePairs = ownArray(keyValuePairs); 3822 return node; 3823 } 3824 3825 /** 3826 * Parses a LabeledStatement 3827 * 3828 * $(GRAMMAR $(RULEDEF labeledStatement): 3829 * $(LITERAL Identifier) $(LITERAL ':') $(RULE declarationOrStatement)? 3830 * ;) 3831 */ 3832 LabeledStatement parseLabeledStatement() 3833 { 3834 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 3835 auto node = allocate!LabeledStatement; 3836 const ident = expect(tok!"identifier"); 3837 if (ident is null) { deallocate(node); return null; } 3838 node.identifier = *ident; 3839 expect(tok!":"); 3840 if (!currentIs(tok!"}")) 3841 mixin(nullCheck!`node.declarationOrStatement = parseDeclarationOrStatement()`); 3842 return node; 3843 } 3844 3845 /** 3846 * Parses a LambdaExpression 3847 * 3848 * $(GRAMMAR $(RULEDEF lambdaExpression): 3849 * $(LITERAL Identifier) $(LITERAL '=>') $(RULE assignExpression) 3850 * | $(LITERAL 'function') $(RULE type)? $(RULE parameters) $(RULE functionAttribute)* $(LITERAL '=>') $(RULE assignExpression) 3851 * | $(LITERAL 'delegate') $(RULE type)? $(RULE parameters) $(RULE functionAttribute)* $(LITERAL '=>') $(RULE assignExpression) 3852 * | $(RULE parameters) $(RULE functionAttribute)* $(LITERAL '=>') $(RULE assignExpression) 3853 * ;) 3854 */ 3855 LambdaExpression parseLambdaExpression() 3856 { 3857 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 3858 auto node = allocate!LambdaExpression; 3859 if (currentIsOneOf(tok!"function", tok!"delegate")) 3860 { 3861 node.functionType = advance().type; 3862 if (!currentIs(tok!"(")) 3863 if ((node.returnType = parseType()) is null) { deallocate(node); return null; } 3864 goto lParen; 3865 } 3866 else if (startsWith(tok!"identifier", tok!"=>")) 3867 { 3868 node.identifier = advance(); 3869 goto lambda; 3870 } 3871 3872 if (currentIs(tok!"(")) 3873 { 3874 lParen: 3875 mixin(nullCheck!`node.parameters = parseParameters()`); 3876 FunctionAttribute[] functionAttributes; 3877 while (moreTokens()) 3878 { 3879 auto attribute = parseFunctionAttribute(false); 3880 if (attribute is null) 3881 break; 3882 functionAttributes ~= attribute; 3883 } 3884 node.functionAttributes = ownArray(functionAttributes); 3885 } 3886 else 3887 { 3888 error(`Identifier, type, or argument list expected`); 3889 return null; 3890 } 3891 3892 lambda: 3893 if (expect(tok!"=>") is null) { deallocate(node); return null; } 3894 if ((node.assignExpression = parseAssignExpression()) is null) { deallocate(node); return null; } 3895 return node; 3896 } 3897 3898 /** 3899 * Parses a LastCatch 3900 * 3901 * $(GRAMMAR $(RULEDEF lastCatch): 3902 * $(LITERAL 'catch') $(RULE statementNoCaseNoDefault) 3903 * ;) 3904 */ 3905 LastCatch parseLastCatch() 3906 { 3907 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 3908 auto node = allocate!LastCatch; 3909 const t = expect(tok!"catch"); 3910 if (t is null) { deallocate(node); return null; } 3911 node.line = t.line; 3912 node.column = t.column; 3913 if ((node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault()) is null) 3914 return null; 3915 return node; 3916 } 3917 3918 /** 3919 * Parses a LinkageAttribute 3920 * 3921 * $(GRAMMAR $(RULEDEF linkageAttribute): 3922 * $(LITERAL 'extern') $(LITERAL '$(LPAREN)') $(LITERAL Identifier) ($(LITERAL '++') ($(LITERAL ',') $(RULE identifierChain))?)? $(LITERAL '$(RPAREN)') 3923 * ;) 3924 */ 3925 LinkageAttribute parseLinkageAttribute() 3926 { 3927 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 3928 auto node = allocate!LinkageAttribute; 3929 expect(tok!"extern"); 3930 expect(tok!"("); 3931 const ident = expect(tok!"identifier"); 3932 if (ident is null) { deallocate(node); return null; } 3933 node.identifier = *ident; 3934 if (currentIs(tok!"-")) 3935 { 3936 advance(); // skip the - 3937 advance(); // skip the C 3938 } else if (currentIs(tok!"++")) 3939 { 3940 advance(); 3941 node.hasPlusPlus = true; 3942 if (currentIs(tok!",")) 3943 { 3944 advance(); 3945 if(currentIs(tok!"struct") || currentIs(tok!"class")) { 3946 advance(); // FIXME: discarding it! 3947 3948 } else if(currentIs(tok!"(")) { 3949 parseExpression(); // FIXME: discarding it! 3950 } else 3951 mixin(nullCheck!`node.identifierChain = parseIdentifierChain()`); 3952 } 3953 } 3954 expect(tok!")"); 3955 return node; 3956 } 3957 3958 /** 3959 * Parses a MemberFunctionAttribute 3960 * 3961 * $(GRAMMAR $(RULEDEF memberFunctionAttribute): 3962 * $(RULE functionAttribute) 3963 * | $(LITERAL 'immutable') 3964 * | $(LITERAL 'inout') 3965 * | $(LITERAL 'shared') 3966 * | $(LITERAL 'const') 3967 * | $(LITERAL 'return') 3968 * ;) 3969 */ 3970 MemberFunctionAttribute parseMemberFunctionAttribute() 3971 { 3972 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 3973 auto node = allocate!MemberFunctionAttribute; 3974 switch (current.type) 3975 { 3976 case tok!"@": 3977 mixin(nullCheck!`node.atAttribute = parseAtAttribute()`); 3978 break; 3979 case tok!"immutable": 3980 case tok!"inout": 3981 case tok!"shared": 3982 case tok!"const": 3983 case tok!"pure": 3984 case tok!"nothrow": 3985 case tok!"return": 3986 case tok!"scope": 3987 node.tokenType = advance().type; 3988 break; 3989 default: 3990 error(`Member function attribute expected`); 3991 } 3992 return node; 3993 } 3994 3995 /** 3996 * Parses a MixinDeclaration 3997 * 3998 * $(GRAMMAR $(RULEDEF mixinDeclaration): 3999 * $(RULE mixinExpression) $(LITERAL ';') 4000 * | $(RULE templateMixinExpression) $(LITERAL ';') 4001 * ;) 4002 */ 4003 MixinDeclaration parseMixinDeclaration() 4004 { 4005 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4006 auto node = allocate!MixinDeclaration; 4007 if (peekIsOneOf(tok!"identifier", tok!"typeof", tok!".")) 4008 mixin(nullCheck!`node.templateMixinExpression = parseTemplateMixinExpression()`); 4009 else if (peekIs(tok!"(")) { 4010 mixin(nullCheck!`node.mixinExpression = parseMixinExpression()`); 4011 4012 if(auto ae = cast(UnaryExpression) node.mixinExpression.assignExpression) { 4013 auto pe = ae.primaryExpression; 4014 if(pe) { 4015 auto txt = pe.primary.text; 4016 if(txt.length > 5 && txt[0 .. 2] == "q{") { 4017 txt = txt[2 .. $-1]; 4018 4019 LexerConfig config; 4020 StringCache* stringCache = new StringCache(128); 4021 4022 config.stringBehavior = StringBehavior.source; 4023 config.whitespaceBehavior = WhitespaceBehavior.include; 4024 config.fileName = "mixin"; 4025 4026 auto tokens = getTokensForParser(cast(ubyte[]) txt, config, stringCache); 4027 4028 foreach(ref token; tokens) { 4029 cast() token.line += pe.primary.line - 1; 4030 } 4031 auto m = .parseModule(tokens, "mixin"); 4032 node.trivialDeclarations = m.declarations.dup; 4033 } 4034 } 4035 } 4036 4037 //node.trivialDeclarations = parseDeclaration 4038 } else 4039 { 4040 error(`"(" or identifier expected`); 4041 return null; 4042 } 4043 expect(tok!";"); 4044 return node; 4045 } 4046 4047 /** 4048 * Parses a MixinExpression 4049 * 4050 * $(GRAMMAR $(RULEDEF mixinExpression): 4051 * $(LITERAL 'mixin') $(LITERAL '$(LPAREN)') $(RULE assignExpression) $(LITERAL '$(RPAREN)') 4052 * ;) 4053 */ 4054 MixinExpression parseMixinExpression() 4055 { 4056 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4057 auto node = allocate!MixinExpression; 4058 expect(tok!"mixin"); 4059 expect(tok!"("); 4060 moar: 4061 // FIXME: it discards the others... 4062 mixin(nullCheck!`node.assignExpression = parseAssignExpression()`); 4063 if (currentIs(tok!",")) { 4064 advance(); 4065 goto moar; 4066 } 4067 expect(tok!")"); 4068 return node; 4069 } 4070 4071 /** 4072 * Parses a MixinTemplateDeclaration 4073 * 4074 * $(GRAMMAR $(RULEDEF mixinTemplateDeclaration): 4075 * $(LITERAL 'mixin') $(RULE templateDeclaration) 4076 * ;) 4077 */ 4078 MixinTemplateDeclaration parseMixinTemplateDeclaration() 4079 { 4080 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4081 auto node = allocate!MixinTemplateDeclaration; 4082 if (expect(tok!"mixin") is null) { deallocate(node); return null; } 4083 mixin(nullCheck!`node.templateDeclaration = parseTemplateDeclaration()`); 4084 if (node.templateDeclaration is null) { deallocate(node); return null; } 4085 return node; 4086 } 4087 4088 /** 4089 * Parses a MixinTemplateName 4090 * 4091 * $(GRAMMAR $(RULEDEF mixinTemplateName): 4092 * $(RULE symbol) 4093 * | $(RULE typeofExpression) $(LITERAL '.') $(RULE identifierOrTemplateChain) 4094 * ;) 4095 */ 4096 MixinTemplateName parseMixinTemplateName() 4097 { 4098 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4099 auto node = allocate!MixinTemplateName; 4100 if (currentIs(tok!"typeof")) 4101 { 4102 mixin(nullCheck!`node.typeofExpression = parseTypeofExpression()`); 4103 expect(tok!"."); 4104 mixin(nullCheck!`node.identifierOrTemplateChain = parseIdentifierOrTemplateChain()`); 4105 } 4106 else 4107 mixin(nullCheck!`node.symbol = parseSymbol()`); 4108 return node; 4109 } 4110 4111 /** 4112 * Parses a Module 4113 * 4114 * $(GRAMMAR $(RULEDEF module): 4115 * $(RULE moduleDeclaration)? $(RULE declaration)* 4116 * ;) 4117 */ 4118 Module parseModule() 4119 { 4120 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4121 Module m = allocate!Module; 4122 if (currentIs(tok!"scriptLine")) 4123 m.scriptLine = advance(); 4124 bool isDeprecatedModule; 4125 if (currentIs(tok!"deprecated")) 4126 { 4127 auto b = setBookmark(); 4128 advance(); 4129 if (currentIs(tok!"(")) 4130 skipParens(); 4131 isDeprecatedModule = currentIs(tok!"module"); 4132 goToBookmark(b); 4133 } 4134 if (currentIs(tok!"module") || isDeprecatedModule) 4135 m.moduleDeclaration = parseModuleDeclaration(); 4136 Declaration[] declarations; 4137 while (moreTokens()) 4138 { 4139 auto declaration = parseDeclaration(); 4140 if (declaration !is null) 4141 declarations ~= declaration; 4142 } 4143 m.declarations = ownArray(declarations); 4144 return m; 4145 } 4146 4147 /** 4148 * Parses a ModuleDeclaration 4149 * 4150 * $(GRAMMAR $(RULEDEF moduleDeclaration): 4151 * $(RULE deprecated)? $(LITERAL 'module') $(RULE identifierChain) $(LITERAL ';') 4152 * ;) 4153 */ 4154 ModuleDeclaration parseModuleDeclaration() 4155 { 4156 auto node = allocate!ModuleDeclaration; 4157 if (currentIs(tok!"deprecated")) 4158 mixin(nullCheck!`node.deprecated_ = parseDeprecated()`); 4159 const start = expect(tok!"module"); 4160 if (start is null) { deallocate(node); return null; } 4161 mixin(nullCheck!`node.moduleName = parseIdentifierChain()`); 4162 node.comment = start.comment; 4163 if (node.comment is null) 4164 node.comment = start.trailingComment; 4165 comment = null; 4166 const end = expect(tok!";"); 4167 node.startLocation = start.index; 4168 if (end !is null) 4169 node.endLocation = end.index; 4170 return node; 4171 } 4172 4173 /** 4174 * Parses a MulExpression. 4175 * 4176 * $(GRAMMAR $(RULEDEF mulExpression): 4177 * $(RULE powExpression) 4178 * | $(RULE mulExpression) ($(LITERAL '*') | $(LITERAL '/') | $(LITERAL '%')) $(RULE powExpression) 4179 * ;) 4180 */ 4181 ExpressionNode parseMulExpression() 4182 { 4183 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4184 return parseLeftAssocBinaryExpression!(MulExpression, PowExpression, 4185 tok!"*", tok!"/", tok!"%")(); 4186 } 4187 4188 /** 4189 * Parses a NewAnonClassExpression 4190 * 4191 * $(GRAMMAR $(RULEDEF newAnonClassExpression): 4192 * $(LITERAL 'new') $(RULE arguments)? $(LITERAL 'class') $(RULE arguments)? $(RULE baseClassList)? $(RULE structBody) 4193 * ;) 4194 */ 4195 NewAnonClassExpression parseNewAnonClassExpression() 4196 { 4197 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4198 auto node = allocate!NewAnonClassExpression; 4199 expect(tok!"new"); 4200 if (currentIs(tok!"(")) 4201 mixin(nullCheck!`node.allocatorArguments = parseArguments()`); 4202 expect(tok!"class"); 4203 if (currentIs(tok!"(")) 4204 mixin(nullCheck!`node.constructorArguments = parseArguments()`); 4205 if (!currentIs(tok!"{")) 4206 mixin(nullCheck!`node.baseClassList = parseBaseClassList()`); 4207 mixin(nullCheck!`node.structBody = parseStructBody()`); 4208 return node; 4209 } 4210 4211 /** 4212 * Parses a NewExpression 4213 * 4214 * $(GRAMMAR $(RULEDEF newExpression): 4215 * $(LITERAL 'new') $(RULE type) (($(LITERAL '[') $(RULE assignExpression) $(LITERAL ']')) | $(RULE arguments))? 4216 * | $(RULE newAnonClassExpression) 4217 * ;) 4218 */ 4219 NewExpression parseNewExpression() 4220 { 4221 // Parse ambiguity. 4222 // auto a = new int[10]; 4223 // ^^^^^^^ 4224 // auto a = new int[10]; 4225 // ^^^**** 4226 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4227 auto node = allocate!NewExpression; 4228 if (peekIsOneOf(tok!"class", tok!"(")) 4229 { 4230 mixin(nullCheck!`node.newAnonClassExpression = parseNewAnonClassExpression()`); 4231 if (node.newAnonClassExpression is null) 4232 { 4233 deallocate(node); 4234 return null; 4235 } 4236 } 4237 else 4238 { 4239 expect(tok!"new"); 4240 if (!moreTokens()) goto fail; 4241 if ((node.type = parseType()) is null) goto fail; 4242 if (currentIs(tok!"[")) 4243 { 4244 advance(); 4245 mixin(nullCheck!`node.assignExpression = parseAssignExpression()`); 4246 expect(tok!"]"); 4247 } 4248 else if (currentIs(tok!"(")) 4249 mixin(nullCheck!`node.arguments = parseArguments()`); 4250 } 4251 return node; 4252 fail: 4253 deallocate(node); 4254 return null; 4255 } 4256 4257 /** 4258 * Parses a NonVoidInitializer 4259 * 4260 * $(GRAMMAR $(RULEDEF nonVoidInitializer): 4261 * $(RULE assignExpression) 4262 * | $(RULE arrayInitializer) 4263 * | $(RULE structInitializer) 4264 * ;) 4265 */ 4266 NonVoidInitializer parseNonVoidInitializer() 4267 { 4268 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4269 auto node = allocate!NonVoidInitializer; 4270 if (currentIs(tok!"{")) 4271 { 4272 const b = peekPastBraces(); 4273 if (b !is null && (b.type == tok!"(")) 4274 mixin(nullCheck!`node.assignExpression = parseAssignExpression()`); 4275 else 4276 { 4277 assert (currentIs(tok!"{")); 4278 auto m = setBookmark(); 4279 auto initializer = parseStructInitializer(); 4280 if (initializer !is null) 4281 { 4282 node.structInitializer = initializer; 4283 abandonBookmark(m); 4284 } 4285 else 4286 { 4287 goToBookmark(m); 4288 mixin(nullCheck!`node.assignExpression = parseAssignExpression()`); 4289 } 4290 } 4291 } 4292 else if (currentIs(tok!"[")) 4293 { 4294 const b = peekPastBrackets(); 4295 if (b !is null && (b.type == tok!"," 4296 || b.type == tok!")" 4297 || b.type == tok!"]" 4298 || b.type == tok!"}" 4299 || b.type == tok!";")) 4300 { 4301 mixin(nullCheck!`node.arrayInitializer = parseArrayInitializer()`); 4302 } 4303 else 4304 mixin(nullCheck!`node.assignExpression = parseAssignExpression()`); 4305 } 4306 else 4307 mixin(nullCheck!`node.assignExpression = parseAssignExpression()`); 4308 if (node.assignExpression is null && node.arrayInitializer is null 4309 && node.structInitializer is null) 4310 { 4311 deallocate(node); 4312 return null; 4313 } 4314 return node; 4315 } 4316 4317 /** 4318 * Parses Operands 4319 * 4320 * $(GRAMMAR $(RULEDEF operands): 4321 * $(RULE asmExp) 4322 * | $(RULE asmExp) $(LITERAL ',') $(RULE operands) 4323 * ;) 4324 */ 4325 Operands parseOperands() 4326 { 4327 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4328 Operands node = allocate!Operands; 4329 ExpressionNode[] expressions; 4330 while (true) 4331 { 4332 ExpressionNode exp = parseAsmExp(); 4333 if (exp is null) 4334 return null; 4335 expressions ~= exp; 4336 if (currentIs(tok!",")) 4337 advance(); 4338 else 4339 break; 4340 } 4341 node.operands = ownArray(expressions); 4342 return node; 4343 } 4344 4345 /** 4346 * Parses an OrExpression 4347 * 4348 * $(GRAMMAR $(RULEDEF orExpression): 4349 * $(RULE xorExpression) 4350 * | $(RULE orExpression) $(LITERAL '|') $(RULE xorExpression) 4351 * ;) 4352 */ 4353 ExpressionNode parseOrExpression() 4354 { 4355 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4356 return parseLeftAssocBinaryExpression!(OrExpression, XorExpression, 4357 tok!"|")(); 4358 } 4359 4360 /** 4361 * Parses an OrOrExpression 4362 * 4363 * $(GRAMMAR $(RULEDEF orOrExpression): 4364 * $(RULE andAndExpression) 4365 * | $(RULE orOrExpression) $(LITERAL '||') $(RULE andAndExpression) 4366 * ;) 4367 */ 4368 ExpressionNode parseOrOrExpression() 4369 { 4370 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4371 return parseLeftAssocBinaryExpression!(OrOrExpression, AndAndExpression, 4372 tok!"||")(); 4373 } 4374 4375 /** 4376 * Parses an OutStatement 4377 * 4378 * $(GRAMMAR $(RULEDEF outStatement): 4379 * $(LITERAL 'out') ($(LITERAL '$(LPAREN)') $(LITERAL Identifier) $(LITERAL '$(RPAREN)'))? $(RULE blockStatement) 4380 * ;) 4381 */ 4382 OutStatement parseOutStatement() 4383 { 4384 auto node = allocate!OutStatement; 4385 const o = expect(tok!"out"); 4386 mixin(nullCheck!`o`); 4387 node.outTokenLocation = o.index; 4388 4389 /* 4390 if tere's a semicolon in the parens, it is the short syntax. 4391 */ 4392 4393 if (currentIs(tok!"(")) 4394 { 4395 advance(); 4396 if(currentIs(tok!"identifier")) { 4397 const ident = expect(tok!"identifier"); 4398 node.parameter = *ident; 4399 } 4400 if(currentIs(tok!";")) { 4401 // short syntax...... 4402 advance(); 4403 node.expression = parseExpression; 4404 expect(tok!")"); 4405 return node; 4406 } else { 4407 expect(tok!")"); 4408 } 4409 } 4410 mixin(nullCheck!`node.blockStatement = parseBlockStatement()`); 4411 if (node.blockStatement is null) 4412 return null; 4413 return node; 4414 } 4415 4416 /** 4417 * Parses a Parameter 4418 * 4419 * $(GRAMMAR $(RULEDEF parameter): 4420 * $(RULE parameterAttribute)* $(RULE type) 4421 * $(RULE parameterAttribute)* $(RULE type) $(LITERAL Identifier)? $(LITERAL '...') 4422 * $(RULE parameterAttribute)* $(RULE type) $(LITERAL Identifier)? ($(LITERAL '=') $(RULE assignExpression))? 4423 * ;) 4424 */ 4425 Parameter parseParameter() 4426 { 4427 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4428 auto node = allocate!Parameter; 4429 4430 node.comment = current.comment; 4431 4432 while (moreTokens()) 4433 { 4434 if(currentIs(tok!"@")) { 4435 AtAttribute atAttribute; 4436 mixin(nullCheck!`atAttribute = parseAtAttribute()`); 4437 if (atAttribute is null) { deallocate(node); break; } 4438 node.atAttributes ~= atAttribute; 4439 } else { 4440 break; 4441 } 4442 } 4443 4444 IdType[] parameterAttributes; 4445 while (moreTokens()) 4446 { 4447 IdType type = parseParameterAttribute(false); 4448 if (type == tok!"") 4449 break; 4450 else 4451 parameterAttributes ~= type; 4452 } 4453 node.parameterAttributes = ownArray(parameterAttributes); 4454 mixin(nullCheck!`node.type = parseType()`); 4455 if (node.type is null) { deallocate(node); return null; } 4456 if (currentIs(tok!"identifier")) 4457 { 4458 node.name = advance(); 4459 if (currentIs(tok!"...")) 4460 { 4461 advance(); 4462 node.vararg = true; 4463 } 4464 else if (currentIs(tok!"=")) 4465 { 4466 advance(); 4467 mixin(nullCheck!`node.default_ = parseAssignExpression()`); 4468 } 4469 else if (currentIs(tok!"[")) 4470 { 4471 TypeSuffix[] typeSuffixes; 4472 while(moreTokens() && currentIs(tok!"[")) 4473 { 4474 auto suffix = parseTypeSuffix(); 4475 if (suffix !is null) 4476 typeSuffixes ~= suffix; 4477 else 4478 return null; 4479 } 4480 node.cstyle = ownArray(typeSuffixes); 4481 } 4482 } 4483 else if (currentIs(tok!"...")) 4484 { 4485 node.vararg = true; 4486 advance(); 4487 } 4488 else if (currentIs(tok!"=")) 4489 { 4490 advance(); 4491 mixin(nullCheck!`node.default_ = parseAssignExpression()`); 4492 } 4493 return node; 4494 } 4495 4496 /** 4497 * Parses a ParameterAttribute 4498 * 4499 * $(GRAMMAR $(RULEDEF parameterAttribute): 4500 * $(RULE typeConstructor) 4501 * | $(LITERAL 'final') 4502 * | $(LITERAL 'in') 4503 * | $(LITERAL 'lazy') 4504 * | $(LITERAL 'out') 4505 * | $(LITERAL 'ref') 4506 * | $(LITERAL 'scope') 4507 * | $(LITERAL 'auto') 4508 * | $(LITERAL 'return') 4509 * ;) 4510 */ 4511 IdType parseParameterAttribute(bool validate = false) 4512 { 4513 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4514 switch (current.type) 4515 { 4516 case tok!"immutable": 4517 case tok!"shared": 4518 case tok!"const": 4519 case tok!"inout": 4520 if (peekIs(tok!"(")) 4521 return tok!""; 4522 else 4523 goto case; 4524 case tok!"final": 4525 case tok!"in": 4526 case tok!"lazy": 4527 case tok!"out": 4528 case tok!"ref": 4529 case tok!"scope": 4530 case tok!"auto": 4531 case tok!"return": 4532 return advance().type; 4533 default: 4534 if (validate) 4535 error("Parameter attribute expected"); 4536 return tok!""; 4537 } 4538 } 4539 4540 /** 4541 * Parses Parameters 4542 * 4543 * $(GRAMMAR $(RULEDEF parameters): 4544 * $(LITERAL '$(LPAREN)') $(RULE parameter) ($(LITERAL ',') $(RULE parameter))* ($(LITERAL ',') $(LITERAL '...'))? $(LITERAL '$(RPAREN)') 4545 * | $(LITERAL '$(LPAREN)') $(LITERAL '...') $(LITERAL '$(RPAREN)') 4546 * | $(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)') 4547 * ;) 4548 */ 4549 Parameters parseParameters() 4550 { 4551 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4552 auto node = allocate!Parameters; 4553 if (expect(tok!"(") is null) { deallocate(node); return null; } 4554 Parameter[] parameters; 4555 if (currentIs(tok!")")) 4556 goto end; 4557 if (currentIs(tok!"...")) 4558 { 4559 advance(); 4560 node.hasVarargs = true; 4561 goto end; 4562 } 4563 while (moreTokens()) 4564 { 4565 if (currentIs(tok!"...")) 4566 { 4567 advance(); 4568 node.hasVarargs = true; 4569 break; 4570 } 4571 if (currentIs(tok!")")) 4572 break; 4573 auto param = parseParameter(); 4574 if (param is null) 4575 return null; 4576 parameters ~= param; 4577 if (currentIs(tok!",")) 4578 advance(); 4579 else 4580 break; 4581 } 4582 node.parameters = ownArray(parameters); 4583 end: 4584 if (expect(tok!")") is null) 4585 return null; 4586 return node; 4587 } 4588 4589 /** 4590 * Parses a Postblit 4591 * 4592 * $(GRAMMAR $(RULEDEF postblit): 4593 * $(LITERAL 'this') $(LITERAL '$(LPAREN)') $(LITERAL 'this') $(LITERAL '$(RPAREN)') $(RULE memberFunctionAttribute)* ($(RULE functionBody) | $(LITERAL ';')) 4594 * ;) 4595 */ 4596 Postblit parsePostblit() 4597 { 4598 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4599 auto node = allocate!Postblit; 4600 node.comment = comment; 4601 node.line = current.line; 4602 comment = null; 4603 expect(tok!"this"); 4604 expect(tok!"("); 4605 expect(tok!"this"); 4606 expect(tok!")"); 4607 MemberFunctionAttribute[] memberFunctionAttributes; 4608 while (currentIsMemberFunctionAttribute()) 4609 memberFunctionAttributes ~= parseMemberFunctionAttribute(); 4610 node.memberFunctionAttributes = ownArray(memberFunctionAttributes); 4611 if (currentIs(tok!";")) 4612 advance(); 4613 else 4614 mixin(nullCheck!`node.functionBody = parseFunctionBody()`); 4615 return node; 4616 } 4617 4618 /** 4619 * Parses a PowExpression 4620 * 4621 * $(GRAMMAR $(RULEDEF powExpression): 4622 * $(RULE unaryExpression) 4623 * | $(RULE powExpression) $(LITERAL '^^') $(RULE unaryExpression) 4624 * ;) 4625 */ 4626 ExpressionNode parsePowExpression() 4627 { 4628 mixin(traceEnterAndExit!(__FUNCTION__)); 4629 return parseLeftAssocBinaryExpression!(PowExpression, UnaryExpression, 4630 tok!"^^")(); 4631 } 4632 4633 /** 4634 * Parses a PragmaDeclaration 4635 * 4636 * $(GRAMMAR $(RULEDEF pragmaDeclaration): 4637 * $(RULE pragmaExpression) $(LITERAL ';') 4638 * ;) 4639 */ 4640 PragmaDeclaration parsePragmaDeclaration() 4641 { 4642 mixin(traceEnterAndExit!(__FUNCTION__)); 4643 auto node = allocate!PragmaDeclaration; 4644 mixin(nullCheck!`node.pragmaExpression = parsePragmaExpression()`); 4645 expect(tok!";"); 4646 return node; 4647 } 4648 4649 /** 4650 * Parses a PragmaExpression 4651 * 4652 * $(GRAMMAR $(RULEDEF pragmaExpression): 4653 * $(RULE 'pragma') $(LITERAL '$(LPAREN)') $(LITERAL Identifier) ($(LITERAL ',') $(RULE argumentList))? $(LITERAL '$(RPAREN)') 4654 * ;) 4655 */ 4656 PragmaExpression parsePragmaExpression() 4657 { 4658 mixin(traceEnterAndExit!(__FUNCTION__)); 4659 auto node = allocate!PragmaExpression; 4660 expect(tok!"pragma"); 4661 expect(tok!"("); 4662 const ident = expect(tok!"identifier"); 4663 if (ident is null) { deallocate(node); return null; } 4664 node.identifier = *ident; 4665 if (currentIs(tok!",")) 4666 { 4667 advance(); 4668 mixin(nullCheck!`node.argumentList = parseArgumentList()`); 4669 } 4670 expect(tok!")"); 4671 return node; 4672 } 4673 4674 /** 4675 * Parses a PrimaryExpression 4676 * 4677 * $(GRAMMAR $(RULEDEF primaryExpression): 4678 * $(RULE identifierOrTemplateInstance) 4679 * | $(LITERAL '.') $(RULE identifierOrTemplateInstance) 4680 * | $(RULE typeConstructor) $(LITERAL '$(LPAREN)') $(RULE basicType) $(LITERAL '$(RPAREN)') $(LITERAL '.') $(LITERAL Identifier) 4681 * | $(RULE basicType) $(LITERAL '.') $(LITERAL Identifier) 4682 * | $(RULE basicType) $(RULE arguments) 4683 * | $(RULE typeofExpression) 4684 * | $(RULE typeidExpression) 4685 * | $(RULE vector) 4686 * | $(RULE arrayLiteral) 4687 * | $(RULE assocArrayLiteral) 4688 * | $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)') 4689 * | $(RULE isExpression) 4690 * | $(RULE lambdaExpression) 4691 * | $(RULE functionLiteralExpression) 4692 * | $(RULE traitsExpression) 4693 * | $(RULE mixinExpression) 4694 * | $(RULE importExpression) 4695 * | $(LITERAL '$') 4696 * | $(LITERAL 'this') 4697 * | $(LITERAL 'super') 4698 * | $(LITERAL '_null') 4699 * | $(LITERAL '_true') 4700 * | $(LITERAL '_false') 4701 * | $(LITERAL '___DATE__') 4702 * | $(LITERAL '___TIME__') 4703 * | $(LITERAL '___TIMESTAMP__') 4704 * | $(LITERAL '___VENDOR__') 4705 * | $(LITERAL '___VERSION__') 4706 * | $(LITERAL '___FILE__') 4707 * | $(LITERAL '___LINE__') 4708 * | $(LITERAL '___MODULE__') 4709 * | $(LITERAL '___FUNCTION__') 4710 * | $(LITERAL '___PRETTY_FUNCTION__') 4711 * | $(LITERAL IntegerLiteral) 4712 * | $(LITERAL FloatLiteral) 4713 * | $(LITERAL StringLiteral)+ 4714 * | $(LITERAL CharacterLiteral) 4715 * ;) 4716 */ 4717 PrimaryExpression parsePrimaryExpression() 4718 { 4719 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4720 auto node = allocate!PrimaryExpression; 4721 if (!moreTokens()) 4722 { 4723 error("Expected primary statement instead of EOF"); 4724 return null; 4725 } 4726 switch (current.type) 4727 { 4728 case tok!".": 4729 node.dot = advance(); 4730 goto case; 4731 case tok!"identifier": 4732 if (peekIs(tok!"=>")) 4733 mixin(nullCheck!`node.lambdaExpression = parseLambdaExpression()`); 4734 else 4735 mixin(nullCheck!`node.identifierOrTemplateInstance = parseIdentifierOrTemplateInstance()`); 4736 break; 4737 case tok!"immutable": 4738 case tok!"const": 4739 case tok!"inout": 4740 case tok!"shared": 4741 advance(); 4742 expect(tok!"("); 4743 mixin(nullCheck!`node.type = parseType()`); 4744 expect(tok!")"); 4745 expect(tok!"."); 4746 { 4747 const ident = expect(tok!"identifier"); 4748 if (ident !is null) 4749 node.primary = *ident; 4750 } 4751 break; 4752 mixin(BUILTIN_TYPE_CASES); 4753 node.basicType = advance(); 4754 if (currentIs(tok!".")) 4755 { 4756 advance(); 4757 const t = expect(tok!"identifier"); 4758 if (t !is null) 4759 node.primary = *t; 4760 } 4761 else if (currentIs(tok!"(")) 4762 mixin(nullCheck!`node.arguments = parseArguments()`); 4763 break; 4764 case tok!"function": 4765 case tok!"delegate": 4766 if (peekIs(tok!"(")) 4767 { 4768 auto b = setBookmark(); 4769 advance(); // function | delegate 4770 skipParens(); 4771 while (isAttribute()) 4772 parseAttribute(); 4773 if (currentIs(tok!"=>")) 4774 { 4775 goToBookmark(b); 4776 mixin(nullCheck!`node.lambdaExpression = parseLambdaExpression()`); 4777 break; 4778 } 4779 else 4780 { 4781 goToBookmark(b); 4782 mixin(nullCheck!`node.functionLiteralExpression = parseFunctionLiteralExpression()`); 4783 break; 4784 } 4785 } 4786 else if (peekIs(tok!"{")) 4787 { 4788 mixin(nullCheck!`node.functionLiteralExpression = parseFunctionLiteralExpression()`); 4789 break; 4790 } 4791 else 4792 { 4793 auto b = setBookmark(); 4794 advance(); // function or delegate 4795 if (parseType() is null) 4796 { 4797 goToBookmark(b); 4798 goto case; 4799 } 4800 if (!currentIs(tok!"(")) 4801 { 4802 goToBookmark(b); 4803 goto case; 4804 } 4805 skipParens(); 4806 while (currentIsMemberFunctionAttribute()) 4807 parseMemberFunctionAttribute(); 4808 if (!currentIs(tok!"=>")) 4809 { 4810 goToBookmark(b); 4811 goto case; 4812 } 4813 goToBookmark(b); 4814 if ((node.lambdaExpression = parseLambdaExpression()) is null) { deallocate(node); return null; } 4815 return node; 4816 } 4817 case tok!"{": 4818 case tok!"in": 4819 case tok!"out": 4820 // case tok!"body": 4821 case tok!"do": 4822 if ((node.functionLiteralExpression = parseFunctionLiteralExpression()) is null) 4823 { 4824 deallocate(node); 4825 return null; 4826 } 4827 break; 4828 case tok!"typeof": 4829 mixin(nullCheck!`node.typeofExpression = parseTypeofExpression()`); 4830 break; 4831 case tok!"typeid": 4832 mixin(nullCheck!`node.typeidExpression = parseTypeidExpression()`); 4833 break; 4834 case tok!"__vector": 4835 mixin(nullCheck!`node.vector = parseVector()`); 4836 break; 4837 case tok!"[": 4838 if (isAssociativeArrayLiteral()) 4839 mixin(nullCheck!`node.assocArrayLiteral = parseAssocArrayLiteral()`); 4840 else 4841 mixin(nullCheck!`node.arrayLiteral = parseArrayLiteral()`); 4842 break; 4843 case tok!"(": 4844 auto b = setBookmark(); 4845 skipParens(); 4846 while (isAttribute()) 4847 parseAttribute(); 4848 if (currentIs(tok!"=>")) 4849 { 4850 goToBookmark(b); 4851 mixin(nullCheck!`node.lambdaExpression = parseLambdaExpression()`); 4852 } 4853 else if (currentIs(tok!"{")) 4854 { 4855 goToBookmark(b); 4856 mixin(nullCheck!`node.functionLiteralExpression = parseFunctionLiteralExpression()`); 4857 } 4858 else 4859 { 4860 goToBookmark(b); 4861 advance(); 4862 mixin(nullCheck!`node.expression = parseExpression()`); 4863 mixin(nullCheck!`expect(tok!")")`); 4864 } 4865 break; 4866 case tok!"is": 4867 mixin(nullCheck!`node.isExpression = parseIsExpression()`); 4868 break; 4869 case tok!"__traits": 4870 mixin(nullCheck!`node.traitsExpression = parseTraitsExpression()`); 4871 break; 4872 case tok!"mixin": 4873 mixin(nullCheck!`node.mixinExpression = parseMixinExpression()`); 4874 break; 4875 case tok!"import": 4876 mixin(nullCheck!`node.importExpression = parseImportExpression()`); 4877 break; 4878 case tok!"$": 4879 case tok!"this": 4880 case tok!"super": 4881 case tok!"null": 4882 case tok!"true": 4883 case tok!"false": 4884 mixin(SPECIAL_CASES); 4885 mixin(LITERAL_CASES); 4886 if (currentIsOneOf(tok!"stringLiteral", tok!"wstringLiteral", tok!"dstringLiteral")) 4887 { 4888 node.primary = advance(); 4889 bool alreadyWarned = false; 4890 while (currentIsOneOf(tok!"stringLiteral", tok!"wstringLiteral", 4891 tok!"dstringLiteral")) 4892 { 4893 if (!alreadyWarned) 4894 { 4895 warn("Implicit concatenation of string literals"); 4896 alreadyWarned = true; 4897 } 4898 node.primary.text ~= advance().text; 4899 } 4900 } 4901 else 4902 node.primary = advance(); 4903 break; 4904 default: 4905 deallocate(node); 4906 error("Primary expression expected"); 4907 return null; 4908 } 4909 return node; 4910 } 4911 4912 /** 4913 * Parses a Register 4914 * 4915 * $(GRAMMAR $(RULEDEF register): 4916 * $(LITERAL Identifier) 4917 * | $(LITERAL Identifier) $(LITERAL '$(LPAREN)') $(LITERAL IntegerLiteral) $(LITERAL '$(RPAREN)') 4918 * ;) 4919 */ 4920 Register parseRegister() 4921 { 4922 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4923 auto node = allocate!Register; 4924 const ident = expect(tok!"identifier"); 4925 if (ident is null) { deallocate(node); return null; } 4926 node.identifier = *ident; 4927 if (currentIs(tok!"(")) 4928 { 4929 advance(); 4930 const intLit = expect(tok!"intLiteral"); 4931 if (intLit is null) { deallocate(node); return null; } 4932 node.intLiteral = *intLit; 4933 expect(tok!")"); 4934 } 4935 return node; 4936 } 4937 4938 /** 4939 * Parses a RelExpression 4940 * 4941 * $(GRAMMAR $(RULEDEF relExpression): 4942 * $(RULE shiftExpression) 4943 * | $(RULE relExpression) $(RULE relOperator) $(RULE shiftExpression) 4944 * ; 4945 *$(RULEDEF relOperator): 4946 * $(LITERAL '<') 4947 * | $(LITERAL '<=') 4948 * | $(LITERAL '>') 4949 * | $(LITERAL '>=') 4950 * | $(LITERAL '!<>=') 4951 * | $(LITERAL '!<>') 4952 * | $(LITERAL '<>') 4953 * | $(LITERAL '<>=') 4954 * | $(LITERAL '!>') 4955 * | $(LITERAL '!>=') 4956 * | $(LITERAL '!<') 4957 * | $(LITERAL '!<=') 4958 * ;) 4959 */ 4960 ExpressionNode parseRelExpression(ExpressionNode shift) 4961 { 4962 mixin(traceEnterAndExit!(__FUNCTION__)); 4963 return parseLeftAssocBinaryExpression!(RelExpression, ShiftExpression, 4964 tok!"<", tok!"<=", tok!">", tok!">=", tok!"!<>=", tok!"!<>", 4965 tok!"<>", tok!"<>=", tok!"!>", tok!"!>=", tok!"!>=", tok!"!<", 4966 tok!"!<=")(shift); 4967 } 4968 4969 /** 4970 * Parses a ReturnStatement 4971 * 4972 * $(GRAMMAR $(RULEDEF returnStatement): 4973 * $(LITERAL 'return') $(RULE expression)? $(LITERAL ';') 4974 * ;) 4975 */ 4976 ReturnStatement parseReturnStatement() 4977 { 4978 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 4979 auto node = allocate!ReturnStatement; 4980 const start = expect(tok!"return"); 4981 if (start is null) { deallocate(node); return null; } 4982 node.startLocation = start.index; 4983 if (!currentIs(tok!";")) 4984 { 4985 if ((node.expression = parseExpression()) is null) 4986 { 4987 deallocate(node); 4988 return null; 4989 } 4990 } 4991 const semicolon = expect(tok!";"); 4992 if (semicolon is null) { deallocate(node); return null; } 4993 node.endLocation = semicolon.index; 4994 return node; 4995 } 4996 4997 /** 4998 * Parses a ScopeGuardStatement 4999 * 5000 * $(GRAMMAR $(RULEDEF scopeGuardStatement): 5001 * $(LITERAL 'scope') $(LITERAL '$(LPAREN)') $(LITERAL Identifier) $(LITERAL '$(RPAREN)') $(RULE statementNoCaseNoDefault) 5002 * ;) 5003 */ 5004 ScopeGuardStatement parseScopeGuardStatement() 5005 { 5006 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5007 auto node = allocate!ScopeGuardStatement; 5008 expect(tok!"scope"); 5009 expect(tok!"("); 5010 const ident = expect(tok!"identifier"); 5011 if (ident is null) { deallocate(node); return null; } 5012 node.identifier = *ident; 5013 expect(tok!")"); 5014 mixin(nullCheck!`node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault()`); 5015 return node; 5016 } 5017 5018 /** 5019 * Parses a SharedStaticConstructor 5020 * 5021 * $(GRAMMAR $(RULEDEF sharedStaticConstructor): 5022 * $(LITERAL 'shared') $(LITERAL 'static') $(LITERAL 'this') $(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)') $(RULE functionBody) 5023 * ;) 5024 */ 5025 SharedStaticConstructor parseSharedStaticConstructor() 5026 { 5027 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5028 mixin(simpleParse!(SharedStaticConstructor, tok!"shared", tok!"static", 5029 tok!"this", tok!"(", tok!")", "functionBody|parseFunctionBody")); 5030 } 5031 5032 /** 5033 * Parses a SharedStaticDestructor 5034 * 5035 * $(GRAMMAR $(RULEDEF sharedStaticDestructor): 5036 * $(LITERAL 'shared') $(LITERAL 'static') $(LITERAL '~') $(LITERAL 'this') $(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)') $(RULE functionBody) 5037 * ;) 5038 */ 5039 SharedStaticDestructor parseSharedStaticDestructor() 5040 { 5041 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5042 mixin(simpleParse!(SharedStaticDestructor, tok!"shared", tok!"static", 5043 tok!"~", tok!"this", tok!"(", tok!")", 5044 "functionBody|parseFunctionBody")); 5045 } 5046 5047 /** 5048 * Parses a ShiftExpression 5049 * 5050 * $(GRAMMAR $(RULEDEF shiftExpression): 5051 * $(RULE addExpression) 5052 * | $(RULE shiftExpression) ($(LITERAL '<<') | $(LITERAL '>>') | $(LITERAL '>>>')) $(RULE addExpression) 5053 * ;) 5054 */ 5055 ExpressionNode parseShiftExpression() 5056 { 5057 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5058 return parseLeftAssocBinaryExpression!(ShiftExpression, AddExpression, 5059 tok!"<<", tok!">>", tok!">>>")(); 5060 } 5061 5062 /** 5063 * Parses a SingleImport 5064 * 5065 * $(GRAMMAR $(RULEDEF singleImport): 5066 * ($(LITERAL Identifier) $(LITERAL '='))? $(RULE identifierChain) 5067 * ;) 5068 */ 5069 SingleImport parseSingleImport() 5070 { 5071 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5072 auto node = allocate!SingleImport; 5073 if (startsWith(tok!"identifier", tok!"=")) 5074 { 5075 node.rename = advance(); 5076 advance(); // = 5077 } 5078 mixin(nullCheck!`node.identifierChain = parseIdentifierChain()`); 5079 if (node.identifierChain is null) 5080 return null; 5081 return node; 5082 } 5083 5084 /** 5085 * Parses a Statement 5086 * 5087 * $(GRAMMAR $(RULEDEF statement): 5088 * $(RULE statementNoCaseNoDefault) 5089 * | $(RULE caseStatement) 5090 * | $(RULE caseRangeStatement) 5091 * | $(RULE defaultStatement) 5092 * ;) 5093 */ 5094 Statement parseStatement() 5095 { 5096 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5097 auto node = allocate!Statement; 5098 if (!moreTokens()) 5099 { 5100 error("Expected statement instead of EOF"); 5101 return null; 5102 } 5103 switch (current.type) 5104 { 5105 case tok!"case": 5106 advance(); 5107 auto argumentList = parseArgumentList(); 5108 if (argumentList is null) 5109 { 5110 deallocate(node); 5111 return null; 5112 } 5113 if (argumentList.items.length == 1 && startsWith(tok!":", tok!"..")) 5114 node.caseRangeStatement = parseCaseRangeStatement(argumentList.items[0]); 5115 else 5116 node.caseStatement = parseCaseStatement(argumentList); 5117 break; 5118 case tok!"default": 5119 mixin(nullCheck!`node.defaultStatement = parseDefaultStatement()`); 5120 break; 5121 default: 5122 if ((node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault()) is null) 5123 { 5124 deallocate(node); 5125 return null; 5126 } 5127 break; 5128 } 5129 return node; 5130 } 5131 5132 /** 5133 * Parses a StatementNoCaseNoDefault 5134 * 5135 * $(GRAMMAR $(RULEDEF statementNoCaseNoDefault): 5136 * $(RULE labeledStatement) 5137 * | $(RULE blockStatement) 5138 * | $(RULE ifStatement) 5139 * | $(RULE whileStatement) 5140 * | $(RULE doStatement) 5141 * | $(RULE forStatement) 5142 * | $(RULE foreachStatement) 5143 * | $(RULE switchStatement) 5144 * | $(RULE finalSwitchStatement) 5145 * | $(RULE continueStatement) 5146 * | $(RULE breakStatement) 5147 * | $(RULE returnStatement) 5148 * | $(RULE gotoStatement) 5149 * | $(RULE withStatement) 5150 * | $(RULE synchronizedStatement) 5151 * | $(RULE tryStatement) 5152 * | $(RULE throwStatement) 5153 * | $(RULE scopeGuardStatement) 5154 * | $(RULE asmStatement) 5155 * | $(RULE conditionalStatement) 5156 * | $(RULE staticAssertStatement) 5157 * | $(RULE versionSpecification) 5158 * | $(RULE debugSpecification) 5159 * | $(RULE expressionStatement) 5160 * ;) 5161 */ 5162 StatementNoCaseNoDefault parseStatementNoCaseNoDefault() 5163 { 5164 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5165 auto node = allocate!StatementNoCaseNoDefault; 5166 node.startLocation = current().index; 5167 switch (current.type) 5168 { 5169 case tok!"{": 5170 mixin(nullCheck!`node.blockStatement = parseBlockStatement()`); 5171 break; 5172 case tok!"if": 5173 mixin(nullCheck!`node.ifStatement = parseIfStatement()`); 5174 break; 5175 case tok!"while": 5176 mixin(nullCheck!`node.whileStatement = parseWhileStatement()`); 5177 break; 5178 case tok!"do": 5179 mixin(nullCheck!`node.doStatement = parseDoStatement()`); 5180 break; 5181 case tok!"for": 5182 mixin(nullCheck!`node.forStatement = parseForStatement()`); 5183 break; 5184 case tok!"foreach": 5185 case tok!"foreach_reverse": 5186 mixin(nullCheck!`node.foreachStatement = parseForeachStatement()`); 5187 break; 5188 case tok!"switch": 5189 mixin(nullCheck!`node.switchStatement = parseSwitchStatement()`); 5190 break; 5191 case tok!"continue": 5192 mixin(nullCheck!`node.continueStatement = parseContinueStatement()`); 5193 break; 5194 case tok!"break": 5195 mixin(nullCheck!`node.breakStatement = parseBreakStatement()`); 5196 break; 5197 case tok!"return": 5198 mixin(nullCheck!`node.returnStatement = parseReturnStatement()`); 5199 break; 5200 case tok!"goto": 5201 mixin(nullCheck!`node.gotoStatement = parseGotoStatement()`); 5202 break; 5203 case tok!"with": 5204 mixin(nullCheck!`node.withStatement = parseWithStatement()`); 5205 break; 5206 case tok!"synchronized": 5207 mixin(nullCheck!`node.synchronizedStatement = parseSynchronizedStatement()`); 5208 break; 5209 case tok!"try": 5210 mixin(nullCheck!`node.tryStatement = parseTryStatement()`); 5211 break; 5212 case tok!"throw": 5213 mixin(nullCheck!`node.throwStatement = parseThrowStatement()`); 5214 break; 5215 case tok!"scope": 5216 mixin(nullCheck!`node.scopeGuardStatement = parseScopeGuardStatement()`); 5217 break; 5218 case tok!"asm": 5219 mixin(nullCheck!`node.asmStatement = parseAsmStatement()`); 5220 break; 5221 case tok!"final": 5222 if (peekIs(tok!"switch")) 5223 { 5224 mixin(nullCheck!`node.finalSwitchStatement = parseFinalSwitchStatement()`); 5225 break; 5226 } 5227 else 5228 { 5229 error(`"switch" expected`); 5230 return null; 5231 } 5232 case tok!"debug": 5233 if (peekIs(tok!"=")) 5234 mixin(nullCheck!`node.debugSpecification = parseDebugSpecification()`); 5235 else 5236 mixin(nullCheck!`node.conditionalStatement = parseConditionalStatement()`); 5237 break; 5238 case tok!"version": 5239 if (peekIs(tok!"=")) 5240 mixin(nullCheck!`node.versionSpecification = parseVersionSpecification()`); 5241 else 5242 mixin(nullCheck!`node.conditionalStatement = parseConditionalStatement()`); 5243 break; 5244 case tok!"static": 5245 if (peekIs(tok!"if")) 5246 mixin(nullCheck!`node.conditionalStatement = parseConditionalStatement()`); 5247 else if (peekIs(tok!"assert")) 5248 mixin(nullCheck!`node.staticAssertStatement = parseStaticAssertStatement()`); 5249 else if (peekIs(tok!"foreach")) 5250 mixin(nullCheck!`node.staticForeachStatement = parseStaticForeachStatement()`); 5251 else 5252 { 5253 error("'if' or 'assert' expected."); 5254 return null; 5255 } 5256 break; 5257 case tok!"identifier": 5258 if (peekIs(tok!":")) 5259 { 5260 mixin(nullCheck!`node.labeledStatement = parseLabeledStatement()`); 5261 break; 5262 } 5263 goto default; 5264 case tok!"delete": 5265 case tok!"assert": 5266 default: 5267 if ((node.expressionStatement = parseExpressionStatement()) is null) 5268 { 5269 deallocate(node); 5270 return null; 5271 } 5272 break; 5273 } 5274 node.endLocation = tokens[index - 1].index; 5275 return node; 5276 } 5277 5278 /** 5279 * Parses a StaticAssertDeclaration 5280 * 5281 * $(GRAMMAR $(RULEDEF staticAssertDeclaration): 5282 * $(RULE staticAssertStatement) 5283 * ;) 5284 */ 5285 StaticAssertDeclaration parseStaticAssertDeclaration() 5286 { 5287 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5288 mixin(simpleParse!(StaticAssertDeclaration, 5289 "staticAssertStatement|parseStaticAssertStatement")); 5290 } 5291 5292 5293 /** 5294 * Parses a StaticAssertStatement 5295 * 5296 * $(GRAMMAR $(RULEDEF staticAssertStatement): 5297 * $(LITERAL 'static') $(RULE assertExpression) $(LITERAL ';') 5298 * ;) 5299 */ 5300 StaticAssertStatement parseStaticAssertStatement() 5301 { 5302 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5303 mixin(simpleParse!(StaticAssertStatement, 5304 tok!"static", "assertExpression|parseAssertExpression", tok!";")); 5305 } 5306 5307 // FIXME: so this one is kinda important but i am doing it lazily 5308 StaticForeachDeclaration parseStaticForeachDeclaration() 5309 { 5310 5311 5312 auto node = new StaticForeachDeclaration(); 5313 5314 expect(tok!"static"); 5315 expect(tok!"foreach"); 5316 expect(tok!"("); 5317 auto n = advance(); 5318 int parensCount = 1; 5319 while(parensCount > 0) { 5320 if(n == tok!"(") 5321 parensCount++; 5322 else if(n == tok!")") 5323 parensCount--; 5324 n = advance(); 5325 } 5326 5327 if(n == tok!"{") { 5328 int bracesCount = 1; 5329 n = advance(); 5330 while(bracesCount > 0) { 5331 if(n == tok!"}") { 5332 bracesCount--; 5333 if(bracesCount == 0) break; 5334 } else if(n == tok!"{") 5335 bracesCount++; 5336 n = advance(); 5337 } 5338 } else { 5339 if(isDeclaration()) 5340 parseDeclaration(); 5341 else 5342 parseStatement(); 5343 } 5344 5345 return node; 5346 5347 5348 /+ 5349 5350 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5351 expect(tok!"static"); 5352 expect(tok!"foreach"); 5353 expect(tok!"("); 5354 auto n = advance(); 5355 int parensCount = 1; 5356 while(parensCount > 0) { 5357 if(n == tok!"(") 5358 parensCount++; 5359 else if(n == tok!")") 5360 parensCount--; 5361 n = advance(); 5362 } 5363 5364 auto node = new StaticForeachDeclaration(); 5365 5366 Declaration[] declarations; 5367 if (currentIs(tok!"{")) 5368 { 5369 advance(); 5370 while (moreTokens() && !currentIs(tok!"}")) 5371 { 5372 auto b = setBookmark(); 5373 auto d = parseDeclaration(); 5374 if (d !is null) 5375 { 5376 abandonBookmark(b); 5377 declarations ~= d; 5378 } 5379 else 5380 { 5381 goToBookmark(b); 5382 return null; 5383 } 5384 } 5385 node.declarations = declarations; 5386 return node; 5387 } else { 5388 node.declarations ~= parseDeclaration(); 5389 } 5390 5391 return node; 5392 +/ 5393 } 5394 5395 // FIXME. i don't really care about this right now but just want it 5396 // good enough to avoid errors for now 5397 StaticForeachStatement parseStaticForeachStatement() 5398 { 5399 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5400 5401 auto node = new StaticForeachStatement(); 5402 5403 expect(tok!"static"); 5404 expect(tok!"foreach"); 5405 expect(tok!"("); 5406 auto n = advance(); 5407 int parensCount = 1; 5408 while(parensCount > 0) { 5409 if(n == tok!"(") 5410 parensCount++; 5411 else if(n == tok!")") 5412 parensCount--; 5413 n = advance(); 5414 } 5415 5416 if(n == tok!"{") { 5417 int bracesCount = 1; 5418 n = advance(); 5419 while(bracesCount > 0) { 5420 if(n == tok!"}") { 5421 bracesCount--; 5422 if(bracesCount == 0) break; 5423 } else if(n == tok!"{") 5424 bracesCount++; 5425 n = advance(); 5426 } 5427 } else { 5428 if(isDeclaration()) 5429 parseDeclaration(); 5430 else 5431 parseStatement(); 5432 } 5433 5434 return node; 5435 } 5436 5437 /** 5438 * Parses a StaticConstructor 5439 * 5440 * $(GRAMMAR $(RULEDEF staticConstructor): 5441 * $(LITERAL 'static') $(LITERAL 'this') $(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)') $(RULE functionBody) 5442 * ;) 5443 */ 5444 StaticConstructor parseStaticConstructor() 5445 { 5446 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5447 mixin(simpleParse!(StaticConstructor, tok!"static", tok!"this", 5448 tok!"(", tok!")", "functionBody|parseFunctionBody")); 5449 } 5450 5451 /** 5452 * Parses a StaticDestructor 5453 * 5454 * $(GRAMMAR $(RULEDEF staticDestructor): 5455 * $(LITERAL 'static') $(LITERAL '~') $(LITERAL 'this') $(LITERAL '$(LPAREN)') $(LITERAL '$(RPAREN)') $(RULE functionBody) 5456 * ;) 5457 */ 5458 StaticDestructor parseStaticDestructor() 5459 { 5460 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5461 mixin(simpleParse!(StaticDestructor, tok!"static", tok!"~", tok!"this", 5462 tok!"(", tok!")", "functionBody|parseFunctionBody")); 5463 } 5464 5465 /** 5466 * Parses an StaticIfCondition 5467 * 5468 * $(GRAMMAR $(RULEDEF staticIfCondition): 5469 * $(LITERAL 'static') $(LITERAL 'if') $(LITERAL '$(LPAREN)') $(RULE assignExpression) $(LITERAL '$(RPAREN)') 5470 * ;) 5471 */ 5472 StaticIfCondition parseStaticIfCondition() 5473 { 5474 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5475 mixin(simpleParse!(StaticIfCondition, tok!"static", tok!"if", tok!"(", 5476 "assignExpression|parseAssignExpression", tok!")")); 5477 } 5478 5479 /** 5480 * Parses a StorageClass 5481 * 5482 * $(GRAMMAR $(RULEDEF storageClass): 5483 * $(RULE alignAttribute) 5484 * | $(RULE linkageAttribute) 5485 * | $(RULE atAttribute) 5486 * | $(RULE typeConstructor) 5487 * | $(RULE deprecated) 5488 * | $(LITERAL 'abstract') 5489 * | $(LITERAL 'auto') 5490 * | $(LITERAL 'enum') 5491 * | $(LITERAL 'extern') 5492 * | $(LITERAL 'final') 5493 * | $(LITERAL 'nothrow') 5494 * | $(LITERAL 'override') 5495 * | $(LITERAL 'pure') 5496 * | $(LITERAL 'ref') 5497 * | $(LITERAL '___gshared') 5498 * | $(LITERAL 'scope') 5499 * | $(LITERAL 'static') 5500 * | $(LITERAL 'synchronized') 5501 * ;) 5502 */ 5503 StorageClass parseStorageClass() 5504 { 5505 auto node = allocate!StorageClass; 5506 switch (current.type) 5507 { 5508 case tok!"@": 5509 mixin(nullCheck!`node.atAttribute = parseAtAttribute()`); 5510 if (node.atAttribute is null) { deallocate(node); return null; } 5511 break; 5512 case tok!"deprecated": 5513 mixin(nullCheck!`node.deprecated_ = parseDeprecated()`); 5514 break; 5515 case tok!"align": 5516 mixin(nullCheck!`node.alignAttribute = parseAlignAttribute()`); 5517 break; 5518 case tok!"extern": 5519 if (peekIs(tok!"(")) 5520 { 5521 mixin(nullCheck!`node.linkageAttribute = parseLinkageAttribute()`); 5522 break; 5523 } 5524 else goto case; 5525 case tok!"const": 5526 case tok!"immutable": 5527 case tok!"inout": 5528 case tok!"shared": 5529 case tok!"abstract": 5530 case tok!"auto": 5531 case tok!"enum": 5532 case tok!"final": 5533 case tok!"nothrow": 5534 case tok!"override": 5535 case tok!"pure": 5536 case tok!"ref": 5537 case tok!"__gshared": 5538 case tok!"scope": 5539 case tok!"static": 5540 case tok!"synchronized": 5541 node.token = advance(); 5542 break; 5543 default: 5544 error(`Storage class expected`); 5545 return null; 5546 } 5547 return node; 5548 } 5549 5550 /** 5551 * Parses a StructBody 5552 * 5553 * $(GRAMMAR $(RULEDEF structBody): 5554 * $(LITERAL '{') $(RULE declaration)* $(LITERAL '}') 5555 * ;) 5556 */ 5557 StructBody parseStructBody() 5558 { 5559 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5560 auto node = allocate!StructBody; 5561 const start = expect(tok!"{"); 5562 if (start !is null) node.startLocation = start.index; 5563 Declaration[] declarations; 5564 while (!currentIs(tok!"}") && moreTokens()) 5565 { 5566 auto dec = parseDeclaration(); 5567 if (dec !is null) 5568 declarations ~= dec; 5569 } 5570 node.declarations = ownArray(declarations); 5571 const end = expect(tok!"}"); 5572 if (end !is null) node.endLocation = end.index; 5573 return node; 5574 } 5575 5576 /** 5577 * Parses a StructDeclaration 5578 * 5579 * $(GRAMMAR $(RULEDEF structDeclaration): 5580 * $(LITERAL 'struct') $(LITERAL Identifier)? ($(RULE templateParameters) $(RULE constraint)? $(RULE structBody) | ($(RULE structBody) | $(LITERAL ';'))) 5581 * ;) 5582 */ 5583 StructDeclaration parseStructDeclaration() 5584 { 5585 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5586 auto node = allocate!StructDeclaration; 5587 const t = expect(tok!"struct"); 5588 if (currentIs(tok!"identifier")) 5589 node.name = advance(); 5590 else 5591 { 5592 node.name.line = t.line; 5593 node.name.column = t.column; 5594 } 5595 node.comment = comment; 5596 comment = null; 5597 5598 if (currentIs(tok!"(")) 5599 { 5600 mixin(nullCheck!`node.templateParameters = parseTemplateParameters()`); 5601 if (currentIs(tok!"if")) 5602 mixin(nullCheck!`node.constraint = parseConstraint()`); 5603 mixin(nullCheck!`node.structBody = parseStructBody()`); 5604 } 5605 else if (currentIs(tok!"{")) 5606 { 5607 mixin(nullCheck!`node.structBody = parseStructBody()`); 5608 } 5609 else if (currentIs(tok!";")) 5610 advance(); 5611 else 5612 { 5613 error("Template Parameters, Struct Body, or Semicolon expected"); 5614 return null; 5615 } 5616 return node; 5617 } 5618 5619 /** 5620 * Parses an StructInitializer 5621 * 5622 * $(GRAMMAR $(RULEDEF structInitializer): 5623 * $(LITERAL '{') $(RULE structMemberInitializers)? $(LITERAL '}') 5624 * ;) 5625 */ 5626 StructInitializer parseStructInitializer() 5627 { 5628 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5629 auto node = allocate!StructInitializer; 5630 const a = expect(tok!"{"); 5631 node.startLocation = a.index; 5632 if (currentIs(tok!"}")) 5633 { 5634 node.endLocation = current.index; 5635 advance(); 5636 } 5637 else 5638 { 5639 mixin(nullCheck!`node.structMemberInitializers = parseStructMemberInitializers()`); 5640 const e = expect(tok!"}"); 5641 mixin(nullCheck!`e`); 5642 node.endLocation = e.index; 5643 } 5644 return node; 5645 } 5646 5647 /** 5648 * Parses a StructMemberInitializer 5649 * 5650 * $(GRAMMAR $(RULEDEF structMemberInitializer): 5651 * ($(LITERAL Identifier) $(LITERAL ':'))? $(RULE nonVoidInitializer) 5652 * ;) 5653 */ 5654 StructMemberInitializer parseStructMemberInitializer() 5655 { 5656 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5657 auto node = allocate!StructMemberInitializer; 5658 if (startsWith(tok!"identifier", tok!":")) 5659 { 5660 node.identifier = tokens[index++]; 5661 index++; 5662 } 5663 mixin(nullCheck!`node.nonVoidInitializer = parseNonVoidInitializer()`); 5664 return node; 5665 } 5666 5667 /** 5668 * Parses StructMemberInitializers 5669 * 5670 * $(GRAMMAR $(RULEDEF structMemberInitializers): 5671 * $(RULE structMemberInitializer) ($(LITERAL ',') $(RULE structMemberInitializer)?)* 5672 * ;) 5673 */ 5674 StructMemberInitializers parseStructMemberInitializers() 5675 { 5676 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5677 auto node = allocate!StructMemberInitializers; 5678 StructMemberInitializer[] structMemberInitializers; 5679 do 5680 { 5681 auto structMemberInitializer = parseStructMemberInitializer(); 5682 if (structMemberInitializer is null) 5683 { 5684 deallocate(node); 5685 return null; 5686 } 5687 else 5688 structMemberInitializers ~= structMemberInitializer; 5689 5690 if (currentIs(tok!",")) 5691 { 5692 advance(); 5693 if (!currentIs(tok!"}")) 5694 continue; 5695 else 5696 break; 5697 } 5698 else 5699 break; 5700 } while (moreTokens()); 5701 node.structMemberInitializers = ownArray(structMemberInitializers); 5702 return node; 5703 } 5704 5705 /** 5706 * Parses a SwitchStatement 5707 * 5708 * $(GRAMMAR $(RULEDEF switchStatement): 5709 * $(LITERAL 'switch') $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)') $(RULE statement) 5710 * ;) 5711 */ 5712 SwitchStatement parseSwitchStatement() 5713 { 5714 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5715 auto node = allocate!SwitchStatement; 5716 expect(tok!"switch"); 5717 expect(tok!"("); 5718 mixin(nullCheck!`node.expression = parseExpression()`); 5719 expect(tok!")"); 5720 mixin(nullCheck!`node.statement = parseStatement()`); 5721 return node; 5722 } 5723 5724 /** 5725 * Parses a Symbol 5726 * 5727 * $(GRAMMAR $(RULEDEF symbol): 5728 * $(LITERAL '.')? $(RULE identifierOrTemplateChain) 5729 * ;) 5730 */ 5731 Symbol parseSymbol() 5732 { 5733 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5734 auto node = allocate!Symbol; 5735 if (currentIs(tok!".")) 5736 { 5737 node.dot = true; 5738 advance(); 5739 } 5740 mixin(nullCheck!`node.identifierOrTemplateChain = parseIdentifierOrTemplateChain()`); 5741 return node; 5742 } 5743 5744 /** 5745 * Parses a SynchronizedStatement 5746 * 5747 * $(GRAMMAR $(RULEDEF synchronizedStatement): 5748 * $(LITERAL 'synchronized') ($(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)'))? $(RULE statementNoCaseNoDefault) 5749 * ;) 5750 */ 5751 SynchronizedStatement parseSynchronizedStatement() 5752 { 5753 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5754 auto node = allocate!SynchronizedStatement; 5755 expect(tok!"synchronized"); 5756 if (currentIs(tok!"(")) 5757 { 5758 expect(tok!"("); 5759 mixin(nullCheck!`node.expression = parseExpression()`); 5760 expect(tok!")"); 5761 } 5762 mixin(nullCheck!`node.statementNoCaseNoDefault = parseStatementNoCaseNoDefault()`); 5763 return node; 5764 } 5765 5766 /** 5767 * Parses a TemplateAliasParameter 5768 * 5769 * $(GRAMMAR $(RULEDEF templateAliasParameter): 5770 * $(LITERAL 'alias') $(RULE type)? $(LITERAL Identifier) ($(LITERAL ':') ($(RULE type) | $(RULE assignExpression)))? ($(LITERAL '=') ($(RULE type) | $(RULE assignExpression)))? 5771 * ;) 5772 */ 5773 TemplateAliasParameter parseTemplateAliasParameter() 5774 { 5775 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5776 auto node = allocate!TemplateAliasParameter; 5777 expect(tok!"alias"); 5778 if (currentIs(tok!"identifier") && !peekIs(tok!".")) 5779 { 5780 if (peekIsOneOf(tok!",", tok!")", tok!"=", tok!":")) 5781 node.identifier = advance(); 5782 else 5783 goto type; 5784 } 5785 else 5786 { 5787 type: 5788 if ((node.type = parseType()) is null) { deallocate(node); return null; } 5789 const ident = expect(tok!"identifier"); 5790 if (ident is null) { deallocate(node); return null; } 5791 node.identifier = *ident; 5792 } 5793 5794 if (currentIs(tok!":")) 5795 { 5796 advance(); 5797 if (isType()) 5798 mixin(nullCheck!`node.colonType = parseType()`); 5799 else 5800 mixin(nullCheck!`node.colonExpression = parseAssignExpression()`); 5801 } 5802 if (currentIs(tok!"=")) 5803 { 5804 advance(); 5805 if (isType()) 5806 mixin(nullCheck!`node.assignType = parseType()`); 5807 else 5808 mixin(nullCheck!`node.assignExpression = parseAssignExpression()`); 5809 } 5810 return node; 5811 } 5812 5813 /** 5814 * Parses a TemplateArgument 5815 * 5816 * $(GRAMMAR $(RULEDEF templateArgument): 5817 * $(RULE type) 5818 * | $(RULE assignExpression) 5819 * ;) 5820 */ 5821 TemplateArgument parseTemplateArgument() 5822 { 5823 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5824 if (suppressedErrorCount > MAX_ERRORS) return null; 5825 auto node = allocate!TemplateArgument; 5826 auto b = setBookmark(); 5827 auto t = parseType(); 5828 if (t !is null && currentIsOneOf(tok!",", tok!")")) 5829 { 5830 abandonBookmark(b); 5831 node.type = t; 5832 } 5833 else 5834 { 5835 goToBookmark(b); 5836 if ((node.assignExpression = parseAssignExpression()) is null) { deallocate(node); return null; } 5837 } 5838 return node; 5839 } 5840 5841 /** 5842 * Parses a TemplateArgumentList 5843 * 5844 * $(GRAMMAR $(RULEDEF templateArgumentList): 5845 * $(RULE templateArgument) ($(LITERAL ',') $(RULE templateArgument)?)* 5846 * ;) 5847 */ 5848 TemplateArgumentList parseTemplateArgumentList() 5849 { 5850 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5851 return parseCommaSeparatedRule!(TemplateArgumentList, TemplateArgument)(true); 5852 } 5853 5854 /** 5855 * Parses TemplateArguments 5856 * 5857 * $(GRAMMAR $(RULEDEF templateArguments): 5858 * $(LITERAL '!') ($(LITERAL '$(LPAREN)') $(RULE templateArgumentList)? $(LITERAL '$(RPAREN)')) | $(RULE templateSingleArgument) 5859 * ;) 5860 */ 5861 TemplateArguments parseTemplateArguments() 5862 { 5863 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5864 if (suppressedErrorCount > MAX_ERRORS) return null; 5865 auto node = allocate!TemplateArguments; 5866 expect(tok!"!"); 5867 if (currentIs(tok!"(")) 5868 { 5869 advance(); 5870 if (!currentIs(tok!")")) 5871 mixin(nullCheck!`node.templateArgumentList = parseTemplateArgumentList()`); 5872 if (expect(tok!")") is null) { deallocate(node); return null; } 5873 } 5874 else 5875 mixin(nullCheck!`node.templateSingleArgument = parseTemplateSingleArgument()`); 5876 return node; 5877 } 5878 5879 /** 5880 * Parses a TemplateDeclaration 5881 * 5882 * $(GRAMMAR $(RULEDEF templateDeclaration): 5883 * $(LITERAL 'template') $(LITERAL Identifier) $(RULE templateParameters) $(RULE constraint)? $(LITERAL '{') $(RULE declaration)* $(LITERAL '}') 5884 * ;) 5885 */ 5886 TemplateDeclaration parseTemplateDeclaration() 5887 { 5888 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5889 auto node = allocate!TemplateDeclaration; 5890 node.comment = comment; 5891 comment = null; 5892 expect(tok!"template"); 5893 const ident = expect(tok!"identifier"); 5894 if (ident is null) { deallocate(node); return null; } 5895 node.name = *ident; 5896 mixin(nullCheck!`node.templateParameters = parseTemplateParameters()`); 5897 if (currentIs(tok!"if")) 5898 mixin(nullCheck!`node.constraint = parseConstraint()`); 5899 const start = expect(tok!"{"); 5900 if (start is null) { deallocate(node); return null; } else node.startLocation = start.index; 5901 Declaration[] declarations; 5902 while (moreTokens() && !currentIs(tok!"}")) 5903 { 5904 auto decl = parseDeclaration(); 5905 if (decl !is null) 5906 declarations ~= decl; 5907 } 5908 node.declarations = ownArray(declarations); 5909 const end = expect(tok!"}"); 5910 if (end !is null) node.endLocation = end.index; 5911 return node; 5912 } 5913 5914 /** 5915 * Parses a TemplateInstance 5916 * 5917 * $(GRAMMAR $(RULEDEF templateInstance): 5918 * $(LITERAL Identifier) $(RULE templateArguments) 5919 * ;) 5920 */ 5921 TemplateInstance parseTemplateInstance() 5922 { 5923 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5924 if (suppressedErrorCount > MAX_ERRORS) return null; 5925 auto node = allocate!TemplateInstance; 5926 const ident = expect(tok!"identifier"); 5927 if (ident is null) { deallocate(node); return null; } 5928 node.identifier = *ident; 5929 mixin(nullCheck!`node.templateArguments = parseTemplateArguments()`); 5930 if (node.templateArguments is null) 5931 return null; 5932 return node; 5933 } 5934 5935 /** 5936 * Parses a TemplateMixinExpression 5937 * 5938 * $(GRAMMAR $(RULEDEF templateMixinExpression): 5939 * $(LITERAL 'mixin') $(RULE mixinTemplateName) $(RULE templateArguments)? $(LITERAL Identifier)? 5940 * ;) 5941 */ 5942 TemplateMixinExpression parseTemplateMixinExpression() 5943 { 5944 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5945 auto node = allocate!TemplateMixinExpression; 5946 node.comment = comment; 5947 node.line = current.line; 5948 comment = null; 5949 if (expect(tok!"mixin") is null) { deallocate(node); return null; } 5950 mixin(nullCheck!`node.mixinTemplateName = parseMixinTemplateName()`); 5951 if (currentIs(tok!"!")) 5952 mixin(nullCheck!`node.templateArguments = parseTemplateArguments()`); 5953 if (currentIs(tok!"identifier")) 5954 node.identifier = advance(); 5955 return node; 5956 } 5957 5958 /** 5959 * Parses a TemplateParameter 5960 * 5961 * $(GRAMMAR $(RULEDEF templateParameter): 5962 * $(RULE templateTypeParameter) 5963 * | $(RULE templateValueParameter) 5964 * | $(RULE templateAliasParameter) 5965 * | $(RULE templateTupleParameter) 5966 * | $(RULE templateThisParameter) 5967 * ;) 5968 */ 5969 TemplateParameter parseTemplateParameter() 5970 { 5971 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 5972 auto node = allocate!TemplateParameter; 5973 5974 node.comment = current.comment; 5975 5976 switch (current.type) 5977 { 5978 case tok!"alias": 5979 mixin(nullCheck!`node.templateAliasParameter = parseTemplateAliasParameter()`); 5980 break; 5981 case tok!"identifier": 5982 if (peekIs(tok!"...")) 5983 mixin(nullCheck!`node.templateTupleParameter = parseTemplateTupleParameter()`); 5984 else if (peekIsOneOf(tok!":", tok!"=", tok!",", tok!")")) 5985 mixin(nullCheck!`node.templateTypeParameter = parseTemplateTypeParameter()`); 5986 else 5987 mixin(nullCheck!`node.templateValueParameter = parseTemplateValueParameter()`); 5988 break; 5989 case tok!"this": 5990 mixin(nullCheck!`node.templateThisParameter = parseTemplateThisParameter()`); 5991 break; 5992 default: 5993 mixin(nullCheck!`node.templateValueParameter = parseTemplateValueParameter()`); 5994 break; 5995 } 5996 return node; 5997 } 5998 5999 /** 6000 * Parses an TemplateParameterList 6001 * 6002 * $(GRAMMAR $(RULEDEF templateParameterList): 6003 * $(RULE templateParameter) ($(LITERAL ',') $(RULE templateParameter)?)* 6004 * ;) 6005 */ 6006 TemplateParameterList parseTemplateParameterList() 6007 { 6008 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6009 return parseCommaSeparatedRule!(TemplateParameterList, TemplateParameter)(true); 6010 } 6011 6012 /** 6013 * Parses TemplateParameters 6014 * 6015 * $(GRAMMAR $(RULEDEF templateParameters): 6016 * $(LITERAL '$(LPAREN)') $(RULE templateParameterList)? $(LITERAL '$(RPAREN)') 6017 * ;) 6018 */ 6019 TemplateParameters parseTemplateParameters() 6020 { 6021 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6022 auto node = allocate!TemplateParameters; 6023 if (expect(tok!"(") is null) { deallocate(node); return null; } 6024 if (!currentIs(tok!")")) 6025 if ((node.templateParameterList = parseTemplateParameterList()) is null) { deallocate(node); return null; } 6026 if (expect(tok!")") is null) { deallocate(node); return null; } 6027 return node; 6028 } 6029 6030 /** 6031 * Parses a TemplateSingleArgument 6032 * 6033 * $(GRAMMAR $(RULEDEF templateSingleArgument): 6034 * $(RULE builtinType) 6035 * | $(LITERAL Identifier) 6036 * | $(LITERAL CharacterLiteral) 6037 * | $(LITERAL StringLiteral) 6038 * | $(LITERAL IntegerLiteral) 6039 * | $(LITERAL FloatLiteral) 6040 * | $(LITERAL '_true') 6041 * | $(LITERAL '_false') 6042 * | $(LITERAL '_null') 6043 * | $(LITERAL 'this') 6044 * | $(LITERAL '___DATE__') 6045 * | $(LITERAL '___TIME__') 6046 * | $(LITERAL '___TIMESTAMP__') 6047 * | $(LITERAL '___VENDOR__') 6048 * | $(LITERAL '___VERSION__') 6049 * | $(LITERAL '___FILE__') 6050 * | $(LITERAL '___LINE__') 6051 * | $(LITERAL '___MODULE__') 6052 * | $(LITERAL '___FUNCTION__') 6053 * | $(LITERAL '___PRETTY_FUNCTION__') 6054 * ;) 6055 */ 6056 TemplateSingleArgument parseTemplateSingleArgument() 6057 { 6058 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6059 auto node = allocate!TemplateSingleArgument; 6060 if (!moreTokens) 6061 { 6062 error("template argument expected instead of EOF"); 6063 return null; 6064 } 6065 switch (current.type) 6066 { 6067 case tok!"true": 6068 case tok!"false": 6069 case tok!"null": 6070 case tok!"this": 6071 case tok!"identifier": 6072 mixin(SPECIAL_CASES); 6073 mixin(LITERAL_CASES); 6074 mixin(BUILTIN_TYPE_CASES); 6075 node.token = advance(); 6076 break; 6077 default: 6078 error(`Invalid template argument. (Try enclosing in parenthesis?)`); 6079 return null; 6080 } 6081 return node; 6082 } 6083 6084 /** 6085 * Parses a TemplateThisParameter 6086 * 6087 * $(GRAMMAR $(RULEDEF templateThisParameter): 6088 * $(LITERAL 'this') $(RULE templateTypeParameter) 6089 * ;) 6090 */ 6091 TemplateThisParameter parseTemplateThisParameter() 6092 { 6093 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6094 auto node = allocate!TemplateThisParameter; 6095 expect(tok!"this"); 6096 mixin(nullCheck!`node.templateTypeParameter = parseTemplateTypeParameter()`); 6097 return node; 6098 } 6099 6100 /** 6101 * Parses an TemplateTupleParameter 6102 * 6103 * $(GRAMMAR $(RULEDEF templateTupleParameter): 6104 * $(LITERAL Identifier) $(LITERAL '...') 6105 * ;) 6106 */ 6107 TemplateTupleParameter parseTemplateTupleParameter() 6108 { 6109 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6110 auto node = allocate!TemplateTupleParameter; 6111 const i = expect(tok!"identifier"); 6112 if (i is null) 6113 return null; 6114 node.identifier = *i; 6115 if (expect(tok!"...") is null) { deallocate(node); return null; } 6116 return node; 6117 } 6118 6119 /** 6120 * Parses a TemplateTypeParameter 6121 * 6122 * $(GRAMMAR $(RULEDEF templateTypeParameter): 6123 * $(LITERAL Identifier) ($(LITERAL ':') $(RULE type))? ($(LITERAL '=') $(RULE type))? 6124 * ;) 6125 */ 6126 TemplateTypeParameter parseTemplateTypeParameter() 6127 { 6128 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6129 auto node = allocate!TemplateTypeParameter; 6130 const ident = expect(tok!"identifier"); 6131 if (ident is null) { deallocate(node); return null; } 6132 node.identifier = *ident; 6133 if (currentIs(tok!":")) 6134 { 6135 advance(); 6136 mixin(nullCheck!`node.colonType = parseType()`); 6137 } 6138 if (currentIs(tok!"=")) 6139 { 6140 advance(); 6141 mixin(nullCheck!`node.assignType = parseType()`); 6142 } 6143 return node; 6144 } 6145 6146 /** 6147 * Parses a TemplateValueParameter 6148 * 6149 * $(GRAMMAR $(RULEDEF templateValueParameter): 6150 * $(RULE type) $(LITERAL Identifier) ($(LITERAL ':') $(RULE assignExpression))? $(RULE templateValueParameterDefault)? 6151 * ;) 6152 */ 6153 TemplateValueParameter parseTemplateValueParameter() 6154 { 6155 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6156 auto node = allocate!TemplateValueParameter; 6157 if ((node.type = parseType()) is null) { deallocate(node); return null; } 6158 const ident = expect(tok!"identifier"); 6159 if (ident is null) { deallocate(node); return null; } 6160 node.identifier = *ident; 6161 if (currentIs(tok!":")) 6162 { 6163 advance(); 6164 if ((node.assignExpression = parseAssignExpression()) is null) { deallocate(node); return null; } 6165 } 6166 if (currentIs(tok!"=")) 6167 { 6168 if ((node.templateValueParameterDefault = parseTemplateValueParameterDefault()) is null) 6169 return null; 6170 } 6171 return node; 6172 } 6173 6174 /** 6175 * Parses a TemplateValueParameterDefault 6176 * 6177 * $(GRAMMAR $(RULEDEF templateValueParameterDefault): 6178 * $(LITERAL '=') ($(LITERAL '___FILE__') | $(LITERAL '___MODULE__') | $(LITERAL '___LINE__') | $(LITERAL '___FUNCTION__') | $(LITERAL '___PRETTY_FUNCTION__') | $(RULE assignExpression)) 6179 * ;) 6180 */ 6181 TemplateValueParameterDefault parseTemplateValueParameterDefault() 6182 { 6183 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6184 auto node = allocate!TemplateValueParameterDefault; 6185 expect(tok!"="); 6186 switch (current.type) 6187 { 6188 case tok!"__FILE__": 6189 case tok!"__MODULE__": 6190 case tok!"__LINE__": 6191 case tok!"__FUNCTION__": 6192 case tok!"__PRETTY_FUNCTION__": 6193 node.token = advance(); 6194 break; 6195 default: 6196 mixin(nullCheck!`node.assignExpression = parseAssignExpression()`); 6197 break; 6198 } 6199 return node; 6200 } 6201 6202 /** 6203 * Parses a TernaryExpression 6204 * 6205 * $(GRAMMAR $(RULEDEF ternaryExpression): 6206 * $(RULE orOrExpression) ($(LITERAL '?') $(RULE expression) $(LITERAL ':') $(RULE ternaryExpression))? 6207 * ;) 6208 */ 6209 ExpressionNode parseTernaryExpression() 6210 { 6211 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6212 6213 auto orOrExpression = parseOrOrExpression(); 6214 if (orOrExpression is null) 6215 return null; 6216 if (currentIs(tok!"?")) 6217 { 6218 TernaryExpression node = allocate!TernaryExpression; 6219 node.orOrExpression = orOrExpression; 6220 advance(); 6221 mixin(nullCheck!`node.expression = parseExpression()`); 6222 auto colon = expect(tok!":"); 6223 if (colon is null) { deallocate(node); return null; } 6224 node.colon = *colon; 6225 mixin(nullCheck!`node.ternaryExpression = parseTernaryExpression()`); 6226 return node; 6227 } 6228 return orOrExpression; 6229 } 6230 6231 /** 6232 * Parses a ThrowStatement 6233 * 6234 * $(GRAMMAR $(RULEDEF throwStatement): 6235 * $(LITERAL 'throw') $(RULE expression) $(LITERAL ';') 6236 * ;) 6237 */ 6238 ThrowStatement parseThrowStatement() 6239 { 6240 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6241 auto node = allocate!ThrowStatement; 6242 expect(tok!"throw"); 6243 mixin(nullCheck!`node.expression = parseExpression()`); 6244 expect(tok!";"); 6245 return node; 6246 } 6247 6248 /** 6249 * Parses an TraitsExpression 6250 * 6251 * $(GRAMMAR $(RULEDEF traitsExpression): 6252 * $(LITERAL '___traits') $(LITERAL '$(LPAREN)') $(LITERAL Identifier) $(LITERAL ',') $(RULE TemplateArgumentList) $(LITERAL '$(RPAREN)') 6253 * ;) 6254 */ 6255 TraitsExpression parseTraitsExpression() 6256 { 6257 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6258 auto node = allocate!TraitsExpression; 6259 if (expect(tok!"__traits") is null) { deallocate(node); return null; } 6260 if (expect(tok!"(") is null) { deallocate(node); return null; } 6261 const ident = expect(tok!"identifier"); 6262 if (ident is null) { deallocate(node); return null; } 6263 node.identifier = *ident; 6264 if (currentIs(tok!",")) 6265 { 6266 advance(); 6267 mixin(nullCheck!`(node.templateArgumentList = parseTemplateArgumentList())`); 6268 } 6269 mixin(nullCheck!`expect(tok!")")`); 6270 return node; 6271 } 6272 6273 /** 6274 * Parses a TryStatement 6275 * 6276 * $(GRAMMAR $(RULEDEF tryStatement): 6277 * $(LITERAL 'try') $(RULE declarationOrStatement) ($(RULE catches) | $(RULE catches) $(RULE finally) | $(RULE finally)) 6278 * ;) 6279 */ 6280 TryStatement parseTryStatement() 6281 { 6282 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6283 auto node = allocate!TryStatement; 6284 expect(tok!"try"); 6285 mixin(nullCheck!`node.declarationOrStatement = parseDeclarationOrStatement()`); 6286 if (currentIs(tok!"catch")) 6287 mixin(nullCheck!`node.catches = parseCatches()`); 6288 if (currentIs(tok!"finally")) 6289 mixin(nullCheck!`node.finally_ = parseFinally()`); 6290 return node; 6291 } 6292 6293 /** 6294 * Parses a Type 6295 * 6296 * $(GRAMMAR $(RULEDEF type): 6297 * $(RULE typeConstructors)? $(RULE type2) $(RULE typeSuffix)* 6298 * ;) 6299 */ 6300 Type parseType() 6301 { 6302 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6303 auto node = allocate!Type; 6304 if (!moreTokens) 6305 { 6306 error("type expected"); 6307 return null; 6308 } 6309 switch (current.type) 6310 { 6311 case tok!"__traits": 6312 advance(); 6313 skipParens(); 6314 break; 6315 case tok!"const": 6316 case tok!"immutable": 6317 case tok!"inout": 6318 case tok!"shared": 6319 if (!peekIs(tok!"(")) 6320 mixin(nullCheck!`node.typeConstructors = parseTypeConstructors()`); 6321 break; 6322 default: 6323 break; 6324 } 6325 mixin(nullCheck!`node.type2 = parseType2()`); 6326 if (node.type2 is null) 6327 return null; 6328 TypeSuffix[] typeSuffixes; 6329 loop: while (moreTokens()) switch (current.type) 6330 { 6331 case tok!"[": 6332 // Allow this to fail because of the madness that is the 6333 // newExpression rule. Something starting with '[' may be arguments 6334 // to the newExpression instead of part of the type 6335 auto newBookmark = setBookmark(); 6336 auto suffix = parseTypeSuffix(); 6337 if (suffix !is null) 6338 { 6339 abandonBookmark(newBookmark); 6340 typeSuffixes ~= suffix; 6341 } 6342 else 6343 { 6344 goToBookmark(newBookmark); 6345 break loop; 6346 } 6347 break; 6348 case tok!"*": 6349 case tok!"delegate": 6350 case tok!"function": 6351 auto suffix = parseTypeSuffix(); 6352 if (suffix !is null) 6353 typeSuffixes ~= suffix; 6354 else 6355 return null; 6356 break; 6357 default: 6358 break loop; 6359 } 6360 node.typeSuffixes = ownArray(typeSuffixes); 6361 return node; 6362 } 6363 6364 /** 6365 * Parses a Type2 6366 * 6367 * $(GRAMMAR $(RULEDEF type2): 6368 * $(RULE builtinType) 6369 * | $(RULE symbol) 6370 * | $(RULE typeofExpression) ($(LITERAL '.') $(RULE identifierOrTemplateChain))? 6371 * | $(RULE typeConstructor) $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL '$(RPAREN)') 6372 * | $(RULE vector) 6373 * ;) 6374 */ 6375 Type2 parseType2() 6376 { 6377 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6378 auto node = allocate!Type2; 6379 if (!moreTokens) 6380 { 6381 error("type2 expected instead of EOF"); 6382 return null; 6383 } 6384 switch (current.type) 6385 { 6386 case tok!"identifier": 6387 case tok!".": 6388 if ((node.symbol = parseSymbol()) is null) 6389 return null; 6390 break; 6391 mixin(BUILTIN_TYPE_CASES); 6392 if ((node.builtinType = parseBuiltinType()) == tok!"") 6393 return null; 6394 break; 6395 case tok!"typeof": 6396 if ((node.typeofExpression = parseTypeofExpression()) is null) 6397 return null; 6398 if (currentIs(tok!".")) 6399 { 6400 advance(); 6401 mixin(nullCheck!`node.identifierOrTemplateChain = parseIdentifierOrTemplateChain()`); 6402 if (node.identifierOrTemplateChain is null) 6403 return null; 6404 } 6405 break; 6406 case tok!"const": 6407 case tok!"immutable": 6408 case tok!"inout": 6409 case tok!"shared": 6410 node.typeConstructor = advance().type; 6411 mixin(nullCheck!`expect(tok!"(")`); 6412 mixin(nullCheck!`(node.type = parseType())`); 6413 mixin(nullCheck!`expect(tok!")")`); 6414 break; 6415 case tok!"__vector": 6416 if ((node.vector = parseVector()) is null) 6417 return null; 6418 break; 6419 default: 6420 error("Basic type, type constructor, symbol, or typeof expected"); 6421 return null; 6422 } 6423 return node; 6424 } 6425 6426 /** 6427 * Parses a TypeConstructor 6428 * 6429 * $(GRAMMAR $(RULEDEF typeConstructor): 6430 * $(LITERAL 'const') 6431 * | $(LITERAL 'immutable') 6432 * | $(LITERAL 'inout') 6433 * | $(LITERAL 'shared') 6434 * ;) 6435 */ 6436 IdType parseTypeConstructor(bool validate = true) 6437 { 6438 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6439 switch (current.type) 6440 { 6441 case tok!"const": 6442 case tok!"immutable": 6443 case tok!"inout": 6444 case tok!"shared": 6445 if (!peekIs(tok!"(")) 6446 return advance().type; 6447 goto default; 6448 default: 6449 if (validate) 6450 error(`"const", "immutable", "inout", or "shared" expected`); 6451 return tok!""; 6452 } 6453 } 6454 6455 /** 6456 * Parses TypeConstructors 6457 * 6458 * $(GRAMMAR $(RULEDEF typeConstructors): 6459 * $(RULE typeConstructor)+ 6460 * ;) 6461 */ 6462 IdType[] parseTypeConstructors() 6463 { 6464 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6465 IdType[] r; 6466 while (moreTokens()) 6467 { 6468 IdType type = parseTypeConstructor(false); 6469 if (type == tok!"") 6470 break; 6471 else 6472 r ~= type; 6473 } 6474 return r; 6475 } 6476 6477 /** 6478 * Parses a TypeSpecialization 6479 * 6480 * $(GRAMMAR $(RULEDEF typeSpecialization): 6481 * $(RULE type) 6482 * | $(LITERAL 'struct') 6483 * | $(LITERAL 'union') 6484 * | $(LITERAL 'class') 6485 * | $(LITERAL 'interface') 6486 * | $(LITERAL 'enum') 6487 * | $(LITERAL 'function') 6488 * | $(LITERAL 'delegate') 6489 * | $(LITERAL 'super') 6490 * | $(LITERAL 'const') 6491 * | $(LITERAL 'immutable') 6492 * | $(LITERAL 'inout') 6493 * | $(LITERAL 'shared') 6494 * | $(LITERAL 'return') 6495 * | $(LITERAL 'typedef') 6496 * | $(LITERAL '___parameters') 6497 * ;) 6498 */ 6499 TypeSpecialization parseTypeSpecialization() 6500 { 6501 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6502 auto node = allocate!TypeSpecialization; 6503 switch (current.type) 6504 { 6505 case tok!"struct": 6506 case tok!"union": 6507 case tok!"class": 6508 case tok!"interface": 6509 case tok!"enum": 6510 case tok!"function": 6511 case tok!"delegate": 6512 case tok!"super": 6513 case tok!"return": 6514 case tok!"typedef": 6515 case tok!"__parameters": 6516 case tok!"__vector": 6517 case tok!"const": 6518 case tok!"immutable": 6519 case tok!"inout": 6520 case tok!"shared": 6521 if (peekIsOneOf(tok!")", tok!",")) 6522 { 6523 node.token = advance(); 6524 break; 6525 } 6526 goto default; 6527 default: 6528 mixin(nullCheck!`node.type = parseType()`); 6529 break; 6530 } 6531 return node; 6532 } 6533 6534 /** 6535 * Parses a TypeSuffix 6536 * 6537 * $(GRAMMAR $(RULEDEF typeSuffix): 6538 * $(LITERAL '*') 6539 * | $(LITERAL '[') $(RULE type)? $(LITERAL ']') 6540 * | $(LITERAL '[') $(RULE assignExpression) $(LITERAL ']') 6541 * | $(LITERAL '[') $(RULE assignExpression) $(LITERAL '..') $(RULE assignExpression) $(LITERAL ']') 6542 * | ($(LITERAL 'delegate') | $(LITERAL 'function')) $(RULE parameters) $(RULE memberFunctionAttribute)* 6543 * ;) 6544 */ 6545 TypeSuffix parseTypeSuffix() 6546 { 6547 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6548 auto node = allocate!TypeSuffix; 6549 switch (current.type) 6550 { 6551 case tok!"*": 6552 node.star = advance(); 6553 return node; 6554 case tok!"[": 6555 node.array = true; 6556 advance(); 6557 if (currentIs(tok!"]")) 6558 { 6559 advance(); 6560 return node; 6561 } 6562 auto bookmark = setBookmark(); 6563 auto type = parseType(); 6564 if (type !is null && currentIs(tok!"]")) 6565 { 6566 abandonBookmark(bookmark); 6567 node.type = type; 6568 } 6569 else 6570 { 6571 goToBookmark(bookmark); 6572 mixin(nullCheck!`node.low = parseAssignExpression()`); 6573 mixin(nullCheck!`node.low`); 6574 if (currentIs(tok!"..")) 6575 { 6576 advance(); 6577 mixin(nullCheck!`node.high = parseAssignExpression()`); 6578 mixin(nullCheck!`node.high`); 6579 } 6580 } 6581 mixin(nullCheck!`expect(tok!"]")`); 6582 return node; 6583 case tok!"delegate": 6584 case tok!"function": 6585 node.delegateOrFunction = advance(); 6586 mixin(nullCheck!`node.parameters = parseParameters()`); 6587 MemberFunctionAttribute[] memberFunctionAttributes; 6588 while (currentIsMemberFunctionAttribute()) 6589 memberFunctionAttributes ~= parseMemberFunctionAttribute(); 6590 node.memberFunctionAttributes = ownArray(memberFunctionAttributes); 6591 return node; 6592 default: 6593 error(`"*", "[", "delegate", or "function" expected.`); 6594 return null; 6595 } 6596 } 6597 6598 /** 6599 * Parses a TypeidExpression 6600 * 6601 * $(GRAMMAR $(RULEDEF typeidExpression): 6602 * $(LITERAL 'typeid') $(LITERAL '$(LPAREN)') ($(RULE type) | $(RULE expression)) $(LITERAL '$(RPAREN)') 6603 * ;) 6604 */ 6605 TypeidExpression parseTypeidExpression() 6606 { 6607 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6608 auto node = allocate!TypeidExpression; 6609 expect(tok!"typeid"); 6610 expect(tok!"("); 6611 auto b = setBookmark(); 6612 auto t = parseType(); 6613 if (t is null || !currentIs(tok!")")) 6614 { 6615 goToBookmark(b); 6616 mixin(nullCheck!`node.expression = parseExpression()`); 6617 mixin(nullCheck!`node.expression`); 6618 } 6619 else 6620 { 6621 abandonBookmark(b); 6622 node.type = t; 6623 } 6624 expect(tok!")"); 6625 return node; 6626 } 6627 6628 /** 6629 * Parses a TypeofExpression 6630 * 6631 * $(GRAMMAR $(RULEDEF typeofExpression): 6632 * $(LITERAL 'typeof') $(LITERAL '$(LPAREN)') ($(RULE expression) | $(LITERAL 'return')) $(LITERAL '$(RPAREN)') 6633 * ;) 6634 */ 6635 TypeofExpression parseTypeofExpression() 6636 { 6637 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6638 auto node = allocate!TypeofExpression; 6639 expect(tok!"typeof"); 6640 expect(tok!"("); 6641 if (currentIs(tok!"return")) 6642 node.return_ = advance(); 6643 else 6644 mixin(nullCheck!`node.expression = parseExpression()`); 6645 expect(tok!")"); 6646 return node; 6647 } 6648 6649 /** 6650 * Parses a UnaryExpression 6651 * 6652 * $(GRAMMAR $(RULEDEF unaryExpression): 6653 * $(RULE primaryExpression) 6654 * | $(LITERAL '&') $(RULE unaryExpression) 6655 * | $(LITERAL '!') $(RULE unaryExpression) 6656 * | $(LITERAL '*') $(RULE unaryExpression) 6657 * | $(LITERAL '+') $(RULE unaryExpression) 6658 * | $(LITERAL '-') $(RULE unaryExpression) 6659 * | $(LITERAL '~') $(RULE unaryExpression) 6660 * | $(LITERAL '++') $(RULE unaryExpression) 6661 * | $(LITERAL '--') $(RULE unaryExpression) 6662 * | $(RULE newExpression) 6663 * | $(RULE deleteExpression) 6664 * | $(RULE castExpression) 6665 * | $(RULE assertExpression) 6666 * | $(RULE functionCallExpression) 6667 * | $(RULE indexExpression) 6668 * | $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL '$(RPAREN)') $(LITERAL '.') $(RULE identifierOrTemplateInstance) 6669 * | $(RULE unaryExpression) $(LITERAL '.') $(RULE identifierOrTemplateInstance) 6670 * | $(RULE unaryExpression) $(LITERAL '--') 6671 * | $(RULE unaryExpression) $(LITERAL '++') 6672 * ;) 6673 */ 6674 UnaryExpression parseUnaryExpression() 6675 { 6676 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6677 if (!moreTokens()) 6678 return null; 6679 auto node = allocate!UnaryExpression; 6680 switch (current.type) 6681 { 6682 case tok!"const": 6683 case tok!"immutable": 6684 case tok!"inout": 6685 case tok!"shared": 6686 auto b = setBookmark(); 6687 if (peekIs(tok!"(")) 6688 { 6689 advance(); 6690 const past = peekPastParens(); 6691 if (past !is null && past.type == tok!".") 6692 { 6693 goToBookmark(b); 6694 goto default; 6695 } 6696 } 6697 goToBookmark(b); 6698 goto case; 6699 case tok!"scope": 6700 case tok!"pure": 6701 case tok!"nothrow": 6702 mixin(nullCheck!`node.functionCallExpression = parseFunctionCallExpression()`); 6703 break; 6704 case tok!"&": 6705 case tok!"!": 6706 case tok!"*": 6707 case tok!"+": 6708 case tok!"-": 6709 case tok!"~": 6710 case tok!"++": 6711 case tok!"--": 6712 node.prefix = advance(); 6713 mixin(nullCheck!`node.unaryExpression = parseUnaryExpression()`); 6714 break; 6715 case tok!"new": 6716 mixin(nullCheck!`node.newExpression = parseNewExpression()`); 6717 break; 6718 case tok!"delete": 6719 mixin(nullCheck!`node.deleteExpression = parseDeleteExpression()`); 6720 break; 6721 case tok!"cast": 6722 mixin(nullCheck!`node.castExpression = parseCastExpression()`); 6723 break; 6724 case tok!"assert": 6725 mixin(nullCheck!`node.assertExpression = parseAssertExpression()`); 6726 break; 6727 case tok!"(": 6728 // handle (type).identifier 6729 auto b = setBookmark(); 6730 skipParens(); 6731 if (startsWith(tok!".", tok!"identifier")) 6732 { 6733 // go back to the ( 6734 goToBookmark(b); 6735 b = setBookmark(); 6736 advance(); 6737 auto t = parseType(); 6738 if (t is null || !currentIs(tok!")")) 6739 { 6740 goToBookmark(b); 6741 goto default; 6742 } 6743 abandonBookmark(b); 6744 node.type = t; 6745 advance(); // ) 6746 advance(); // . 6747 mixin(nullCheck!`node.identifierOrTemplateInstance = parseIdentifierOrTemplateInstance()`); 6748 break; 6749 } 6750 else 6751 { 6752 // not (type).identifier, so treat as primary expression 6753 goToBookmark(b); 6754 goto default; 6755 } 6756 default: 6757 mixin(nullCheck!`node.primaryExpression = parsePrimaryExpression()`); 6758 break; 6759 } 6760 6761 loop: while (moreTokens()) switch (current.type) 6762 { 6763 case tok!"!": 6764 if (peekIs(tok!"(")) 6765 { 6766 index++; 6767 const p = peekPastParens(); 6768 immutable bool jump = (currentIs(tok!"(") && p !is null && p.type == tok!"(") 6769 || peekIs(tok!"("); 6770 index--; 6771 if (jump) 6772 goto case tok!"("; 6773 else 6774 break loop; 6775 } 6776 else 6777 break loop; 6778 case tok!"(": 6779 auto newUnary = allocate!UnaryExpression(); 6780 mixin(nullCheck!`newUnary.functionCallExpression = parseFunctionCallExpression(node)`); 6781 node = newUnary; 6782 break; 6783 case tok!"++": 6784 case tok!"--": 6785 auto n = allocate!UnaryExpression(); 6786 n.unaryExpression = node; 6787 n.suffix = advance(); 6788 node = n; 6789 break; 6790 case tok!"[": 6791 auto n = allocate!UnaryExpression; 6792 n.indexExpression = parseIndexExpression(node); 6793 node = n; 6794 break; 6795 case tok!".": 6796 advance(); 6797 auto n = allocate!UnaryExpression(); 6798 n.unaryExpression = node; 6799 n.identifierOrTemplateInstance = parseIdentifierOrTemplateInstance(); 6800 node = n; 6801 break; 6802 default: 6803 break loop; 6804 } 6805 return node; 6806 } 6807 6808 /** 6809 * Parses an UnionDeclaration 6810 * 6811 * $(GRAMMAR $(RULEDEF unionDeclaration): 6812 * $(LITERAL 'union') $(LITERAL Identifier) $(RULE templateParameters) $(RULE constraint)? $(RULE structBody) 6813 * | $(LITERAL 'union') $(LITERAL Identifier) ($(RULE structBody) | $(LITERAL ';')) 6814 * | $(LITERAL 'union') $(RULE structBody) 6815 * ;) 6816 */ 6817 UnionDeclaration parseUnionDeclaration() 6818 { 6819 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6820 auto node = allocate!UnionDeclaration; 6821 // grab line number even if it's anonymous 6822 const t = expect(tok!"union"); 6823 node.comment = comment; 6824 if (currentIs(tok!"identifier")) 6825 { 6826 node.name = advance(); 6827 if (currentIs(tok!"(")) 6828 { 6829 mixin(nullCheck!`node.templateParameters = parseTemplateParameters()`); 6830 if (currentIs(tok!"if")) 6831 mixin(nullCheck!`node.constraint = parseConstraint()`); 6832 mixin(nullCheck!`node.structBody = parseStructBody()`); 6833 } 6834 else 6835 goto semiOrStructBody; 6836 } 6837 else 6838 { 6839 node.name.line = t.line; 6840 node.name.column = t.column; 6841 semiOrStructBody: 6842 if (currentIs(tok!";")) 6843 advance(); 6844 else 6845 mixin(nullCheck!`node.structBody = parseStructBody()`); 6846 } 6847 return node; 6848 } 6849 6850 /** 6851 * Parses a Unittest 6852 * 6853 * $(GRAMMAR $(RULEDEF unittest): 6854 * $(LITERAL 'unittest') $(RULE blockStatement) 6855 * ;) 6856 */ 6857 Unittest parseUnittest() 6858 { 6859 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6860 mixin(simpleParse!(Unittest, tok!"unittest", "blockStatement|parseBlockStatement")); 6861 } 6862 6863 /** 6864 * Parses a VariableDeclaration 6865 * 6866 * $(GRAMMAR $(RULEDEF variableDeclaration): 6867 * $(RULE storageClass)* $(RULE type) $(RULE declarator) ($(LITERAL ',') $(RULE declarator))* $(LITERAL ';') 6868 * | $(RULE storageClass)* $(RULE type) $(LITERAL identifier) $(LITERAL '=') $(RULE functionBody) $(LITERAL ';') 6869 * | $(RULE autoDeclaration) 6870 * ;) 6871 */ 6872 VariableDeclaration parseVariableDeclaration(Type type = null, bool isAuto = false, 6873 Attribute[] attributes = null, bool isEnum = false) 6874 { 6875 mixin(traceEnterAndExit!(__FUNCTION__)); 6876 auto node = allocate!VariableDeclaration; 6877 node.attributes = attributes; 6878 node.isEnum = isEnum; 6879 if (isAuto) 6880 { 6881 mixin(nullCheck!`node.autoDeclaration = parseAutoDeclaration()`); 6882 node.comment = node.autoDeclaration.comment; 6883 return node; 6884 } 6885 6886 StorageClass[] storageClasses; 6887 while (isStorageClass()) 6888 { 6889 auto s = parseStorageClass(); 6890 if (s !is null) 6891 storageClasses ~= s; 6892 else 6893 { 6894 deallocate(node); 6895 return null; 6896 } 6897 } 6898 node.storageClasses = ownArray(storageClasses); 6899 6900 node.type = type is null ? parseType() : type; 6901 node.comment = comment; 6902 comment = null; 6903 6904 // TODO: handle function bodies correctly 6905 6906 Declarator[] declarators; 6907 while (true) 6908 { 6909 auto declarator = parseDeclarator(); 6910 mixin(nullCheck!`declarator`); 6911 declarators ~= declarator; 6912 if (moreTokens() && currentIs(tok!",")) 6913 { 6914 declarator.comment = current.trailingComment; 6915 advance(); 6916 } 6917 else 6918 break; 6919 } 6920 node.declarators = ownArray(declarators); 6921 const semicolon = expect(tok!";"); 6922 mixin(nullCheck!`semicolon`); 6923 declarators[$ - 1].comment = semicolon.trailingComment; 6924 return node; 6925 } 6926 6927 /** 6928 * Parses a Vector 6929 * 6930 * $(GRAMMAR $(RULEDEF vector): 6931 * $(LITERAL '___vector') $(LITERAL '$(LPAREN)') $(RULE type) $(LITERAL '$(RPAREN)') 6932 * ;) 6933 */ 6934 Vector parseVector() 6935 { 6936 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6937 mixin(simpleParse!(Vector, tok!"__vector", tok!"(", "type|parseType", tok!")")); 6938 } 6939 6940 /** 6941 * Parses a VersionCondition 6942 * 6943 * $(GRAMMAR $(RULEDEF versionCondition): 6944 * $(LITERAL 'version') $(LITERAL '$(LPAREN)') ($(LITERAL IntegerLiteral) | $(LITERAL Identifier) | $(LITERAL 'unittest') | $(LITERAL 'assert')) $(LITERAL '$(RPAREN)') 6945 * ;) 6946 */ 6947 VersionCondition parseVersionCondition() 6948 { 6949 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6950 auto node = allocate!VersionCondition; 6951 const v = expect(tok!"version"); 6952 6953 mixin(nullCheck!`v`); 6954 node.versionIndex = v.index; 6955 mixin(nullCheck!`expect(tok!"(")`); 6956 if (currentIsOneOf(tok!"intLiteral", tok!"identifier", 6957 tok!"unittest", tok!"assert")) 6958 { 6959 node.token = advance(); 6960 } 6961 else 6962 { 6963 error(`Expected an integer literal, an identifier, "assert", or "unittest"`); 6964 return null; 6965 } 6966 expect(tok!")"); 6967 return node; 6968 } 6969 6970 /** 6971 * Parses a VersionSpecification 6972 * 6973 * $(GRAMMAR $(RULEDEF versionSpecification): 6974 * $(LITERAL 'version') $(LITERAL '=') ($(LITERAL Identifier) | $(LITERAL IntegerLiteral)) $(LITERAL ';') 6975 * ;) 6976 */ 6977 VersionSpecification parseVersionSpecification() 6978 { 6979 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 6980 auto node = allocate!VersionSpecification; 6981 mixin(expectSequence!(tok!"version", tok!"=")); 6982 if (!currentIsOneOf(tok!"identifier", tok!"intLiteral")) 6983 { 6984 error("Identifier or integer literal expected"); 6985 return null; 6986 } 6987 node.token = advance(); 6988 expect(tok!";"); 6989 return node; 6990 } 6991 6992 /** 6993 * Parses a WhileStatement 6994 * 6995 * $(GRAMMAR $(RULEDEF whileStatement): 6996 * $(LITERAL 'while') $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)') $(RULE declarationOrStatement) 6997 * ;) 6998 */ 6999 WhileStatement parseWhileStatement() 7000 { 7001 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 7002 auto node = allocate!WhileStatement; 7003 expect(tok!"while"); 7004 node.startIndex = current().index; 7005 expect(tok!"("); 7006 mixin(nullCheck!`node.expression = parseExpression()`); 7007 expect(tok!")"); 7008 if (currentIs(tok!"}")) 7009 { 7010 error("Statement expected", false); 7011 return node; // this line makes DCD better 7012 } 7013 mixin(nullCheck!`node.declarationOrStatement = parseDeclarationOrStatement()`); 7014 return node; 7015 } 7016 7017 /** 7018 * Parses a WithStatement 7019 * 7020 * $(GRAMMAR $(RULEDEF withStatement): 7021 * $(LITERAL 'with') $(LITERAL '$(LPAREN)') $(RULE expression) $(LITERAL '$(RPAREN)') $(RULE statementNoCaseNoDefault) 7022 * ;) 7023 */ 7024 WithStatement parseWithStatement() 7025 { 7026 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 7027 mixin(simpleParse!(WithStatement, tok!"with", tok!"(", 7028 "expression|parseExpression", tok!")", 7029 "statementNoCaseNoDefault|parseStatementNoCaseNoDefault")); 7030 } 7031 7032 /** 7033 * Parses an XorExpression 7034 * 7035 * $(GRAMMAR $(RULEDEF xorExpression): 7036 * $(RULE andExpression) 7037 * | $(RULE xorExpression) $(LITERAL '^') $(RULE andExpression) 7038 * ;) 7039 */ 7040 ExpressionNode parseXorExpression() 7041 { 7042 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 7043 return parseLeftAssocBinaryExpression!(XorExpression, AndExpression, 7044 tok!"^")(); 7045 } 7046 7047 /** 7048 * Current error count 7049 */ 7050 uint errorCount; 7051 7052 /** 7053 * Current warning count 7054 */ 7055 uint warningCount; 7056 7057 /** 7058 * Name used when reporting warnings and errors 7059 */ 7060 string fileName; 7061 7062 /** 7063 * Allocator used for creating AST nodes 7064 */ 7065 IAllocator allocator; 7066 7067 /** 7068 * Function that is called when a warning or error is encountered. 7069 * The parameters are the file name, line number, column number, 7070 * and the error or warning message. 7071 */ 7072 void function(string, size_t, size_t, string, bool) messageFunction; 7073 7074 void setTokens(const(Token)[] tokens) 7075 { 7076 this.tokens = tokens; 7077 } 7078 7079 /** 7080 * Returns: true if there are more tokens 7081 */ 7082 bool moreTokens() const nothrow pure @safe 7083 { 7084 return index < tokens.length; 7085 } 7086 7087 protected: 7088 7089 uint suppressedErrorCount; 7090 7091 enum MAX_ERRORS = 500; 7092 7093 T[] ownArray(T)(T[] from) 7094 { 7095 if (allocator is null) 7096 return from; 7097 T[] to = cast(T[]) allocator.allocate(T.sizeof * from.length); 7098 assert (to.length == from.length, format("from.length = %d, to.length = %d", from.length, to.length)); 7099 to[] = from[]; 7100 return to; 7101 } 7102 7103 T allocate(T, Args...)(auto ref Args args) 7104 { 7105 if (allocator is null) 7106 return new T(args); 7107 enum numBytes = __traits(classInstanceSize, T); 7108 void[] mem = allocator.allocate(numBytes); 7109 assert (mem.length == numBytes, format("%d", mem.length)); 7110 T t = emplace!T(mem, args); 7111 assert (cast(void*) t == mem.ptr, "%x, %x".format(cast(void*) t, mem.ptr)); 7112 return t; 7113 } 7114 7115 void deallocate(T)(T t) 7116 { 7117 if (allocator !is null) 7118 allocator.deallocate((cast (void*) t)[0 .. __traits(classInstanceSize, T)]); 7119 } 7120 7121 bool isCastQualifier() const 7122 { 7123 switch (current.type) 7124 { 7125 case tok!"const": 7126 if (peekIs(tok!")")) return true; 7127 return startsWith(tok!"const", tok!"shared", tok!")"); 7128 case tok!"immutable": 7129 return peekIs(tok!")"); 7130 case tok!"inout": 7131 if (peekIs(tok!")")) return true; 7132 return startsWith(tok!"inout", tok!"shared", tok!")"); 7133 case tok!"shared": 7134 if (peekIs(tok!")")) return true; 7135 if (startsWith(tok!"shared", tok!"const", tok!")")) return true; 7136 return startsWith(tok!"shared", tok!"inout", tok!")"); 7137 default: 7138 return false; 7139 } 7140 } 7141 7142 bool isAssociativeArrayLiteral() 7143 { 7144 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 7145 static bool[typeof(current.index)] cached; 7146 if (auto p = current.index in cached) 7147 return *p; 7148 size_t currentIndex = current.index; 7149 auto b = setBookmark(); 7150 scope(exit) goToBookmark(b); 7151 advance(); 7152 bool result = !currentIs(tok!"]") && parseExpression() !is null && currentIs(tok!":"); 7153 cached[currentIndex] = result; 7154 return result; 7155 } 7156 7157 bool hasMagicDelimiter(alias L, alias T)() 7158 { 7159 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 7160 immutable i = index; 7161 scope(exit) index = i; 7162 assert (currentIs(L)); 7163 advance(); 7164 while (moreTokens()) switch (current.type) 7165 { 7166 case tok!"{": skipBraces(); break; 7167 case tok!"(": skipParens(); break; 7168 case tok!"[": skipBrackets(); break; 7169 case tok!"]": case tok!"}": return false; 7170 case T: return true; 7171 default: advance(); break; 7172 } 7173 return false; 7174 } 7175 7176 bool isDeclaration() 7177 { 7178 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 7179 if (!moreTokens()) return false; 7180 switch (current.type) 7181 { 7182 case tok!"final": 7183 return !peekIs(tok!"switch"); 7184 case tok!"debug": 7185 if (peekIs(tok!":")) 7186 return true; 7187 goto case; 7188 case tok!"version": 7189 if (peekIs(tok!"=")) 7190 return true; 7191 if (peekIs(tok!"(")) 7192 { 7193 auto b = setBookmark(); 7194 scope (exit) goToBookmark(b); 7195 auto dec = parseDeclaration(true); 7196 if (dec is null) 7197 return false; 7198 else 7199 { 7200 deallocate(dec); 7201 return true; 7202 } 7203 } 7204 return false; 7205 case tok!"synchronized": 7206 if (peekIs(tok!"(")) 7207 return false; 7208 else 7209 goto default; 7210 case tok!"static": 7211 if (peekIs(tok!"if")) 7212 return false; 7213 goto case; 7214 case tok!"scope": 7215 if (peekIs(tok!"(")) 7216 return false; 7217 goto case; 7218 case tok!"const": 7219 case tok!"immutable": 7220 case tok!"inout": 7221 case tok!"shared": 7222 goto default; 7223 case tok!"@": 7224 case tok!"abstract": 7225 case tok!"alias": 7226 case tok!"align": 7227 case tok!"auto": 7228 case tok!"class": 7229 case tok!"deprecated": 7230 case tok!"enum": 7231 case tok!"export": 7232 case tok!"extern": 7233 case tok!"__gshared": 7234 case tok!"interface": 7235 case tok!"nothrow": 7236 case tok!"override": 7237 case tok!"package": 7238 case tok!"private": 7239 case tok!"protected": 7240 case tok!"public": 7241 case tok!"pure": 7242 case tok!"ref": 7243 case tok!"struct": 7244 case tok!"union": 7245 case tok!"unittest": 7246 return true; 7247 mixin(BUILTIN_TYPE_CASES); 7248 return !peekIsOneOf(tok!".", tok!"("); 7249 case tok!"asm": 7250 case tok!"break": 7251 case tok!"case": 7252 case tok!"continue": 7253 case tok!"default": 7254 case tok!"do": 7255 case tok!"for": 7256 case tok!"foreach": 7257 case tok!"foreach_reverse": 7258 case tok!"goto": 7259 case tok!"if": 7260 case tok!"return": 7261 case tok!"switch": 7262 case tok!"throw": 7263 case tok!"try": 7264 case tok!"while": 7265 case tok!"{": 7266 case tok!"assert": 7267 return false; 7268 default: 7269 auto b = setBookmark(); 7270 auto p = parseDeclaration(); 7271 if (p is null) 7272 { 7273 goToBookmark(b); 7274 return false; 7275 } 7276 else 7277 { 7278 deallocate(p); 7279 goToBookmark(b); 7280 return true; 7281 } 7282 } 7283 } 7284 7285 /// Only use this in template parameter parsing 7286 bool isType() 7287 { 7288 if (!moreTokens()) return false; 7289 auto b = setBookmark(); 7290 scope (exit) goToBookmark(b); 7291 auto t = parseType(); 7292 if (t is null) return false; else deallocate(t); 7293 if (currentIsOneOf(tok!",", tok!")", tok!"=")) return true; 7294 return false; 7295 } 7296 7297 bool isStorageClass() 7298 { 7299 if (!moreTokens()) return false; 7300 switch (current.type) 7301 { 7302 case tok!"const": 7303 case tok!"immutable": 7304 case tok!"inout": 7305 case tok!"shared": 7306 return !peekIs(tok!"("); 7307 case tok!"@": 7308 case tok!"deprecated": 7309 case tok!"abstract": 7310 case tok!"align": 7311 case tok!"auto": 7312 case tok!"enum": 7313 case tok!"extern": 7314 case tok!"final": 7315 case tok!"nothrow": 7316 case tok!"override": 7317 case tok!"pure": 7318 case tok!"ref": 7319 case tok!"__gshared": 7320 case tok!"scope": 7321 case tok!"static": 7322 case tok!"synchronized": 7323 return true; 7324 default: 7325 return false; 7326 } 7327 } 7328 7329 bool isAttribute() 7330 { 7331 if (!moreTokens()) return false; 7332 switch (current.type) 7333 { 7334 case tok!"const": 7335 case tok!"immutable": 7336 case tok!"inout": 7337 case tok!"scope": 7338 return !peekIs(tok!"("); 7339 case tok!"static": 7340 return !peekIsOneOf(tok!"assert", tok!"this", tok!"if", tok!"~"); 7341 case tok!"shared": 7342 return !(startsWith(tok!"shared", tok!"static", tok!"this") 7343 || startsWith(tok!"shared", tok!"static", tok!"~") 7344 || peekIs(tok!"(")); 7345 case tok!"pragma": 7346 auto b = setBookmark(); 7347 scope(exit) goToBookmark(b); 7348 advance(); 7349 const past = peekPastParens(); 7350 if (past is null || *past == tok!";") 7351 return false; 7352 return true; 7353 case tok!"deprecated": 7354 case tok!"private": 7355 case tok!"package": 7356 case tok!"protected": 7357 case tok!"public": 7358 case tok!"export": 7359 case tok!"final": 7360 case tok!"synchronized": 7361 case tok!"override": 7362 case tok!"abstract": 7363 case tok!"auto": 7364 case tok!"__gshared": 7365 case tok!"pure": 7366 case tok!"nothrow": 7367 case tok!"@": 7368 case tok!"ref": 7369 case tok!"extern": 7370 case tok!"align": 7371 return true; 7372 default: 7373 return false; 7374 } 7375 } 7376 7377 bool currentIsMemberFunctionAttribute() const 7378 { 7379 if (!moreTokens) return false; 7380 switch (current.type) 7381 { 7382 case tok!"const": 7383 case tok!"immutable": 7384 case tok!"inout": 7385 case tok!"shared": 7386 case tok!"@": 7387 case tok!"pure": 7388 case tok!"nothrow": 7389 case tok!"return": 7390 case tok!"scope": 7391 return true; 7392 default: 7393 return false; 7394 } 7395 } 7396 7397 ExpressionNode parseLeftAssocBinaryExpression(alias ExpressionType, 7398 alias ExpressionPartType, Operators ...)(ExpressionNode part = null) 7399 { 7400 ExpressionNode node; 7401 mixin("node = part is null ? parse" ~ ExpressionPartType.stringof ~ "() : part;"); 7402 if (node is null) 7403 { 7404 deallocate(node); 7405 return null; 7406 } 7407 while (currentIsOneOf(Operators)) 7408 { 7409 auto n = allocate!ExpressionType; 7410 n.line = current.line; 7411 n.column = current.column; 7412 static if (__traits(hasMember, ExpressionType, "operator")) 7413 n.operator = advance().type; 7414 else 7415 advance(); 7416 n.left = node; 7417 mixin("n.right = parse" ~ ExpressionPartType.stringof ~ "();"); 7418 node = n; 7419 } 7420 return node; 7421 } 7422 7423 ListType parseCommaSeparatedRule(alias ListType, alias ItemType, bool setLineAndColumn = false) 7424 (bool allowTrailingComma = false) 7425 { 7426 auto node = allocate!ListType; 7427 static if (setLineAndColumn) 7428 { 7429 node.line = current.line; 7430 node.column = current.column; 7431 } 7432 static if (is(ItemType : ExpressionNode)) 7433 ExpressionNode[] items; 7434 else 7435 ItemType[] items; 7436 while (moreTokens()) 7437 { 7438 mixin("auto i = parse" ~ ItemType.stringof ~ "();"); 7439 if (i !is null) 7440 items ~= i; 7441 else 7442 { 7443 deallocate(node); 7444 return null; 7445 } 7446 if (currentIs(tok!",")) 7447 { 7448 advance(); 7449 if (allowTrailingComma && currentIsOneOf(tok!")", 7450 tok!"}", tok!"]")) 7451 { 7452 break; 7453 } 7454 else 7455 continue; 7456 } 7457 else 7458 break; 7459 } 7460 node.items = ownArray(items); 7461 return node; 7462 } 7463 7464 void warn(lazy string message) 7465 { 7466 import std.stdio : stderr; 7467 if (suppressMessages > 0) 7468 return; 7469 ++warningCount; 7470 auto column = index < tokens.length ? tokens[index].column : 0; 7471 auto line = index < tokens.length ? tokens[index].line : 0; 7472 if (messageFunction is null) 7473 stderr.writefln("%s(%d:%d)[warn]: %s", fileName, line, column, message); 7474 else 7475 messageFunction(fileName, line, column, message, false); 7476 } 7477 7478 void error(string message, bool shouldAdvance = true) 7479 { 7480 import std.stdio : stderr; 7481 if (suppressMessages == 0) 7482 { 7483 ++errorCount; 7484 auto column = index < tokens.length ? tokens[index].column : tokens[$ - 1].column; 7485 auto line = index < tokens.length ? tokens[index].line : tokens[$ - 1].line; 7486 if (messageFunction is null) 7487 stderr.writefln("%s(%d:%d)[error]: %s", fileName, line, column, message); 7488 else 7489 messageFunction(fileName, line, column, message, true); 7490 } 7491 else 7492 ++suppressedErrorCount; 7493 while (shouldAdvance && moreTokens()) 7494 { 7495 if (currentIsOneOf(tok!";", tok!"}", 7496 tok!")", tok!"]")) 7497 { 7498 advance(); 7499 break; 7500 } 7501 else 7502 advance(); 7503 } 7504 } 7505 7506 void skip(alias O, alias C)() 7507 { 7508 assert (currentIs(O), current().text); 7509 advance(); 7510 int depth = 1; 7511 while (moreTokens()) 7512 { 7513 switch (tokens[index].type) 7514 { 7515 case C: 7516 advance(); 7517 depth--; 7518 if (depth <= 0) 7519 return; 7520 break; 7521 case O: 7522 depth++; 7523 advance(); 7524 break; 7525 default: 7526 advance(); 7527 break; 7528 } 7529 } 7530 } 7531 7532 void skipBraces() 7533 { 7534 skip!(tok!"{", tok!"}")(); 7535 } 7536 7537 void skipParens() 7538 { 7539 version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 7540 skip!(tok!"(", tok!")")(); 7541 } 7542 7543 void skipBrackets() 7544 { 7545 skip!(tok!"[", tok!"]")(); 7546 } 7547 7548 const(Token)* peek() const 7549 { 7550 return index + 1 < tokens.length ? &tokens[index + 1] : null; 7551 } 7552 7553 const(Token)* peekPast(alias O, alias C)() const nothrow 7554 { 7555 if (index >= tokens.length) 7556 return null; 7557 int depth = 1; 7558 size_t i = index; 7559 ++i; 7560 while (i < tokens.length) 7561 { 7562 if (tokens[i] == O) 7563 { 7564 ++depth; 7565 ++i; 7566 } 7567 else if (tokens[i] == C) 7568 { 7569 --depth; 7570 ++i; 7571 if (depth <= 0) 7572 break; 7573 } 7574 else 7575 ++i; 7576 } 7577 return i >= tokens.length ? null : depth == 0 ? &tokens[i] : null; 7578 } 7579 7580 const(Token)* peekPastParens() const nothrow 7581 { 7582 return peekPast!(tok!"(", tok!")")(); 7583 } 7584 7585 const(Token)* peekPastBrackets() const nothrow 7586 { 7587 return peekPast!(tok!"[", tok!"]")(); 7588 } 7589 7590 const(Token)* peekPastBraces() const nothrow 7591 { 7592 return peekPast!(tok!"{", tok!"}")(); 7593 } 7594 7595 bool peekIs(IdType t) const nothrow 7596 { 7597 return index + 1 < tokens.length && tokens[index + 1].type == t; 7598 } 7599 7600 bool peekIsOneOf(IdType[] types...) const nothrow 7601 { 7602 if (index + 1 >= tokens.length) return false; 7603 return canFind(types, tokens[index + 1].type); 7604 } 7605 7606 /** 7607 * Returns a token of the specified type if it was the next token, otherwise 7608 * calls the error function and returns null. Advances the lexer by one token. 7609 */ 7610 const(Token)* expect(IdType type) 7611 { 7612 if (index < tokens.length && tokens[index].type == type) 7613 return &tokens[index++]; 7614 else 7615 { 7616 string tokenString = str(type) is null 7617 ? to!string(type) : str(type); 7618 immutable bool shouldNotAdvance = index < tokens.length 7619 && (tokens[index].type == tok!")" 7620 || tokens[index].type == tok!";" 7621 || tokens[index].type == tok!"}"); 7622 auto token = (index < tokens.length 7623 ? (tokens[index].text is null ? str(tokens[index].type) : tokens[index].text) 7624 : "EOF"); 7625 error("Expected " ~ tokenString ~ " instead of " ~ token, 7626 !shouldNotAdvance); 7627 return null; 7628 } 7629 } 7630 7631 /** 7632 * Returns: the _current token 7633 */ 7634 Token current() const pure nothrow @nogc @property 7635 { 7636 return tokens[index]; 7637 } 7638 7639 /** 7640 * Advances to the next token and returns the current token 7641 */ 7642 Token advance() pure nothrow @nogc 7643 { 7644 debug if(index + 1 > tokens.length) { 7645 import std.stdio; 7646 foreach(token; tokens) { 7647 string tokenString = str(token.type) is null 7648 ? to!string(token.type) : str(token.type); 7649 write(tokenString == "identifier" ? token.text : tokenString, " "); 7650 } 7651 writeln(); 7652 7653 return Token(tok!"}"); 7654 } 7655 return tokens[index++]; 7656 } 7657 7658 /** 7659 * Returns: true if the current token has the given type 7660 */ 7661 bool currentIs(IdType type) const pure nothrow @nogc 7662 { 7663 return index < tokens.length && tokens[index] == type; 7664 } 7665 7666 /** 7667 * Returns: true if the current token is one of the given types 7668 */ 7669 bool currentIsOneOf(IdType[] types...) const pure nothrow @nogc 7670 { 7671 if (index >= tokens.length) 7672 return false; 7673 return canFind(types, current.type); 7674 } 7675 7676 bool startsWith(IdType[] types...) const pure nothrow @nogc 7677 { 7678 if (index + types.length >= tokens.length) 7679 return false; 7680 for (size_t i = 0; (i < types.length) && ((index + i) < tokens.length); ++i) 7681 { 7682 if (tokens[index + i].type != types[i]) 7683 return false; 7684 } 7685 return true; 7686 } 7687 7688 alias Bookmark = size_t; 7689 7690 Bookmark setBookmark() 7691 { 7692 // version(std_parser_verbose) mixin(traceEnterAndExit!(__FUNCTION__)); 7693 ++suppressMessages; 7694 return index; 7695 } 7696 7697 void abandonBookmark(Bookmark) nothrow 7698 { 7699 --suppressMessages; 7700 if (suppressMessages == 0) 7701 suppressedErrorCount = 0; 7702 } 7703 7704 void goToBookmark(Bookmark bookmark) nothrow 7705 { 7706 --suppressMessages; 7707 if (suppressMessages == 0) 7708 suppressedErrorCount = 0; 7709 index = bookmark; 7710 } 7711 7712 template simpleParse(NodeType, parts ...) 7713 { 7714 static if (__traits(hasMember, NodeType, "comment")) 7715 enum nodeComm = "node.comment = comment;\n" 7716 ~ "comment = null;\n"; 7717 else enum nodeComm = ""; 7718 7719 static if (__traits(hasMember, NodeType, "line")) 7720 enum nodeLine = "node.line = current().line;\n"; 7721 else enum nodeLine = ""; 7722 7723 static if (__traits(hasMember, NodeType, "column")) 7724 enum nodeColumn = "node.column = current().column;\n"; 7725 else enum nodeColumn = ""; 7726 7727 static if (__traits(hasMember, NodeType, "location")) 7728 enum nodeLoc = "node.location = current().index;\n"; 7729 else enum nodeLoc = ""; 7730 7731 enum simpleParse = "auto node = allocate!" ~ NodeType.stringof ~ ";\n" 7732 ~ nodeComm ~ nodeLine ~ nodeColumn ~ nodeLoc 7733 ~ simpleParseItems!(parts) 7734 ~ "\nreturn node;\n"; 7735 } 7736 7737 template simpleParseItems(items ...) 7738 { 7739 static if (items.length > 1) 7740 enum simpleParseItems = simpleParseItem!(items[0]) ~ "\n" 7741 ~ simpleParseItems!(items[1 .. $]); 7742 else static if (items.length == 1) 7743 enum simpleParseItems = simpleParseItem!(items[0]); 7744 else 7745 enum simpleParseItems = ""; 7746 } 7747 7748 template simpleParseItem(alias item) 7749 { 7750 static if (is (typeof(item) == string)) 7751 enum simpleParseItem = "if ((node." ~ item[0 .. item.countUntil("|")] 7752 ~ " = " ~ item[item.countUntil("|") + 1 .. $] ~ "()) is null) { deallocate(node); return null; }"; 7753 else 7754 enum simpleParseItem = "if (expect(" ~ item.stringof ~ ") is null) { deallocate(node); return null; }"; 7755 } 7756 7757 template expectSequence(sequence ...) 7758 { 7759 static if (sequence.length == 1) 7760 enum expectSequence = "if (expect(" ~ sequence[0].stringof ~ ") is null) { deallocate(node); return null; }"; 7761 else 7762 enum expectSequence = "if (expect(" ~ sequence[0].stringof ~ ") is null) { deallocate(node); return null; }\n" 7763 ~ expectSequence!(sequence[1..$]); 7764 } 7765 7766 template traceEnterAndExit(string fun) 7767 { 7768 enum traceEnterAndExit = `version (std_parser_verbose) { _traceDepth++; trace("` 7769 ~ `\033[01;32m` ~ fun ~ `\033[0m"); }` 7770 ~ `version (std_parser_verbose) scope(exit) { trace("` 7771 ~ `\033[01;31m` ~ fun ~ `\033[0m"); _traceDepth--; }`; 7772 } 7773 7774 version (std_parser_verbose) 7775 { 7776 import std.stdio : stderr; 7777 void trace(string message) 7778 { 7779 if (suppressMessages > 0) 7780 return; 7781 auto depth = format("%4d ", _traceDepth); 7782 if (index < tokens.length) 7783 stderr.writeln(depth, message, "(", current.line, ":", current.column, ")"); 7784 else 7785 stderr.writeln(depth, message, "(EOF:0)"); 7786 } 7787 } 7788 else 7789 { 7790 void trace(lazy string) {} 7791 } 7792 7793 template nullCheck(string exp) 7794 { 7795 enum nullCheck = "{if ((" ~ exp ~ ") is null) { deallocate(node); return null; }}"; 7796 } 7797 7798 template tokenCheck(string exp, string tok) 7799 { 7800 enum tokenCheck = `{auto t = expect(tok!"` ~ tok ~ `");` 7801 ~ `if (t is null) { deallocate(node); return null;}` 7802 ~ `else {` ~ exp ~ ` = *t; }}`; 7803 } 7804 7805 // This list MUST BE MAINTAINED IN SORTED ORDER. 7806 static immutable string[] REGISTER_NAMES = [ 7807 "AH", "AL", "AX", "BH", "BL", "BP", "BPL", "BX", "CH", "CL", "CR0", "CR2", 7808 "CR3", "CR4", "CS", "CX", "DH", "DI", "DIL", "DL", "DR0", "DR1", "DR2", 7809 "DR3", "DR6", "DR7", "DS", "DX", "EAX", "EBP", "EBX", "ECX", "EDI", "EDX", 7810 "ES", "ESI", "ESP", "FS", "GS", "MM0", "MM1", "MM2", "MM3", "MM4", "MM5", 7811 "MM6", "MM7", "R10", "R10B", "R10D", "R10W", "R11", "R11B", "R11D", "R11W", 7812 "R12", "R12B", "R12D", "R12W", "R13", "R13B", "R13D", "R13W", "R14", "R14B", 7813 "R14D", "R14W", "R15", "R15B", "R15D", "R15W", "R8", "R8B", "R8D", "R8W", 7814 "R9", "R9B", "R9D", "R9W", "RAX", "RBP", "RBX", "RCX", "RDI", "RDX", "RSI", 7815 "RSP", "SI", "SIL", "SP", "SPL", "SS", "ST", "TR3", "TR4", "TR5", "TR6", 7816 "TR7", "XMM0", "XMM1", "XMM10", "XMM11", "XMM12", "XMM13", "XMM14", "XMM15", 7817 "XMM2", "XMM3", "XMM4", "XMM5", "XMM6", "XMM7", "XMM8", "XMM9", "YMM0", 7818 "YMM1", "YMM10", "YMM11", "YMM12", "YMM13", "YMM14", "YMM15", "YMM2", 7819 "YMM3", "YMM4", "YMM5", "YMM6", "YMM7", "YMM8", "YMM9" 7820 ]; 7821 7822 enum string BUILTIN_TYPE_CASES = q{ 7823 case tok!"int": 7824 case tok!"uint": 7825 case tok!"double": 7826 case tok!"idouble": 7827 case tok!"float": 7828 case tok!"ifloat": 7829 case tok!"short": 7830 case tok!"ushort": 7831 case tok!"long": 7832 case tok!"ulong": 7833 case tok!"char": 7834 case tok!"wchar": 7835 case tok!"dchar": 7836 case tok!"bool": 7837 case tok!"void": 7838 case tok!"cent": 7839 case tok!"ucent": 7840 case tok!"real": 7841 case tok!"ireal": 7842 case tok!"byte": 7843 case tok!"ubyte": 7844 case tok!"cdouble": 7845 case tok!"cfloat": 7846 case tok!"creal": 7847 }; 7848 7849 enum string LITERAL_CASES = q{ 7850 case tok!"doubleLiteral": 7851 case tok!"floatLiteral": 7852 case tok!"idoubleLiteral": 7853 case tok!"ifloatLiteral": 7854 case tok!"intLiteral": 7855 case tok!"longLiteral": 7856 case tok!"realLiteral": 7857 case tok!"irealLiteral": 7858 case tok!"uintLiteral": 7859 case tok!"ulongLiteral": 7860 case tok!"stringLiteral": 7861 case tok!"wstringLiteral": 7862 case tok!"dstringLiteral": 7863 case tok!"characterLiteral": 7864 }; 7865 7866 enum string SPECIAL_CASES = q{ 7867 case tok!"__DATE__": 7868 case tok!"__EOF__": 7869 case tok!"__FILE__": 7870 case tok!"__FUNCTION__": 7871 case tok!"__LINE__": 7872 case tok!"__MODULE__": 7873 case tok!"__PRETTY_FUNCTION__": 7874 case tok!"__TIME__": 7875 case tok!"__TIMESTAMP__": 7876 case tok!"__VENDOR__": 7877 case tok!"__VERSION__": 7878 }; 7879 7880 enum string PARSE_INTERFACE_OR_CLASS = q{ 7881 auto ident = expect(tok!"identifier"); 7882 mixin(nullCheck!`ident`); 7883 node.name = *ident; 7884 node.comment = comment; 7885 comment = null; 7886 if (currentIs(tok!";")) 7887 goto emptyBody; 7888 if (currentIs(tok!"{")) 7889 goto structBody; 7890 templateStuff: if (currentIs(tok!"(")) 7891 { 7892 mixin(nullCheck!`node.templateParameters = parseTemplateParameters()`); 7893 if (currentIs(tok!";")) 7894 goto emptyBody; 7895 constraint: if (currentIs(tok!"if")) 7896 mixin(nullCheck!`node.constraint = parseConstraint()`); 7897 if (node.baseClassList !is null) 7898 { 7899 if (currentIs(tok!"{")) 7900 goto structBody; 7901 else if (currentIs(tok!";")) 7902 goto emptyBody; 7903 else 7904 { 7905 error("Struct body or ';' expected"); 7906 return null; 7907 } 7908 } 7909 if (currentIs(tok!":")) 7910 goto baseClassList; 7911 if (currentIs(tok!"if")) 7912 goto constraint; 7913 if (currentIs(tok!";")) 7914 goto emptyBody; 7915 } 7916 if (currentIs(tok!":")) 7917 { 7918 baseClassList: 7919 advance(); // : 7920 if ((node.baseClassList = parseBaseClassList()) is null) 7921 return null; 7922 if (currentIs(tok!"if")) 7923 goto constraint; 7924 } 7925 structBody: 7926 mixin(nullCheck!`node.structBody = parseStructBody()`); 7927 return node; 7928 emptyBody: 7929 advance(); 7930 return node; 7931 }; 7932 7933 const(Token)[] tokens; 7934 int suppressMessages; 7935 size_t index; 7936 int _traceDepth; 7937 string comment; 7938 } 7939