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