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