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