1 // This file is part of Visual D 2 // 3 // Visual D integrates the D programming language into Visual Studio 4 // Copyright (c) 2010-2011 by Rainer Schuetze, All Rights Reserved 5 // 6 // Distributed under the Boost Software License, Version 1.0. 7 // See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt 8 9 module vdc.parser.aggr; 10 11 import vdc.util; 12 import vdc.lexer; 13 import vdc.parser.engine; 14 import vdc.parser.mod; 15 import vdc.parser.tmpl; 16 import vdc.parser.decl; 17 import vdc.parser.misc; 18 import vdc.parser.stmt; 19 20 import ast = vdc.ast.all; 21 22 import stdext.util; 23 24 //-- GRAMMAR_BEGIN -- 25 //AggregateDeclaration: 26 // struct Identifier StructBody 27 // union Identifier StructBody 28 // struct Identifier ; 29 // union Identifier ; 30 // StructTemplateDeclaration 31 // UnionTemplateDeclaration 32 // ClassDeclaration 33 // InterfaceDeclaration 34 // 35 //StructTemplateDeclaration: 36 // struct Identifier ( TemplateParameterList ) Constraint_opt StructBody 37 // 38 //UnionTemplateDeclaration: 39 // union Identifier ( TemplateParameterList ) Constraint_opt StructBody 40 // 41 //ClassDeclaration: 42 // class Identifier BaseClassList_opt ClassBody 43 // ClassTemplateDeclaration 44 // 45 //BaseClassList: 46 // : SuperClass 47 // : SuperClass , InterfaceClasses 48 // : InterfaceClass 49 // 50 //SuperClass: 51 // GlobalIdentifierList 52 // Protection GlobalIdentifierList 53 // 54 //InterfaceClasses: 55 // InterfaceClass 56 // InterfaceClass , InterfaceClasses 57 // 58 //InterfaceClass: 59 // GlobalIdentifierList 60 // Protection GlobalIdentifierList 61 // 62 //InterfaceDeclaration: 63 // interface Identifier BaseInterfaceList_opt InterfaceBody 64 // InterfaceTemplateDeclaration 65 // 66 //BaseInterfaceList: 67 // : InterfaceClasses 68 // 69 //StructBody: 70 // { DeclDefs_opt } 71 // 72 //ClassBody: 73 // { DeclDefs_opt } 74 // 75 //InterfaceBody: 76 // { DeclDefs_opt } 77 // 78 //Protection: 79 // private 80 // package 81 // public 82 // export 83 class AggregateDeclaration 84 { 85 static Action enter(Parser p) 86 { 87 switch(p.tok.id) 88 { 89 case TOK_union: 90 p.pushState(&shiftUnion); 91 return Accept; 92 case TOK_struct: 93 p.pushState(&shiftStruct); 94 return Accept; 95 case TOK_class: 96 p.pushState(&shiftClass); 97 return Accept; 98 case TOK_interface: 99 p.pushState(&shiftInterface); 100 return Accept; 101 default: 102 return p.parseError("class, struct or union expected"); 103 } 104 } 105 106 static Action shiftStruct(Parser p) 107 { 108 switch(p.tok.id) 109 { 110 case TOK_Identifier: 111 p.pushNode(new ast.Struct(p.tok)); 112 p.pushState(&shiftIdentifier); 113 return Accept; 114 115 case TOK_lcurly: 116 case TOK_lparen: 117 p.pushNode(new ast.Struct(p.tok.span)); 118 return shiftIdentifier(p); 119 120 default: 121 return p.parseError("struct identifier expected"); 122 } 123 } 124 125 static Action shiftUnion(Parser p) 126 { 127 switch(p.tok.id) 128 { 129 case TOK_Identifier: 130 p.pushNode(new ast.Union(p.tok)); 131 p.pushState(&shiftIdentifier); 132 return Accept; 133 134 case TOK_lcurly: 135 case TOK_lparen: 136 p.pushNode(new ast.Union(p.tok.span)); 137 return shiftIdentifier(p); 138 139 default: 140 return p.parseError("union identifier expected"); 141 } 142 } 143 144 static Action shiftClass(Parser p) 145 { 146 switch(p.tok.id) 147 { 148 case TOK_Identifier: 149 p.pushNode(new ast.Class(p.tok)); 150 p.pushState(&shiftIdentifier); 151 return Accept; 152 default: 153 return p.parseError("class identifier expected"); 154 } 155 } 156 157 static Action shiftInterface(Parser p) 158 { 159 switch(p.tok.id) 160 { 161 case TOK_Identifier: 162 p.pushNode(new ast.Intrface(p.tok)); 163 p.pushState(&shiftIdentifier); 164 return Accept; 165 default: 166 return p.parseError("interface identifier expected"); 167 } 168 } 169 170 static Action shiftIdentifier(Parser p) 171 { 172 switch(p.tok.id) 173 { 174 case TOK_semicolon: 175 p.topNode!(ast.Aggregate).hasBody = false; 176 return Accept; 177 case TOK_lcurly: 178 return shiftLcurly(p); 179 case TOK_lparen: 180 p.pushState(&shiftLparen); 181 return Accept; 182 183 case TOK_colon: 184 if(!cast(ast.Class) p.topNode() && !cast(ast.Intrface) p.topNode()) 185 return p.parseError("only classes and interfaces support inheritance"); 186 p.pushState(&shiftColon); 187 return Accept; 188 189 default: 190 return p.parseError("';', '(' or '{' expected after struct or union identifier"); 191 } 192 } 193 194 // NewArguments ClassArguments $ BaseClassList_opt ClassBody 195 static Action enterAnonymousClass(Parser p) 196 { 197 p.pushNode(new ast.AnonymousClass(p.tok)); 198 switch(p.tok.id) 199 { 200 case TOK_lparen: 201 p.pushState(&shiftLparen); 202 return Accept; 203 case TOK_lcurly: 204 return shiftLcurly(p); 205 default: 206 return shiftColon(p); 207 } 208 } 209 210 static Action shiftColon(Parser p) 211 { 212 switch(p.tok.id) 213 { 214 case TOK_dot: 215 case TOK_Identifier: 216 p.pushNode(new ast.BaseClass(TOK_public, p.tok.span)); 217 p.pushState(&shiftBaseClass); 218 return GlobalIdentifierList.enter(p); 219 case TOK_private: 220 case TOK_package: 221 case TOK_public: 222 case TOK_export: 223 p.pushToken(p.tok); 224 p.pushState(&shiftProtection); 225 return Accept; 226 default: 227 return p.parseError("identifier or protection attribute expected"); 228 } 229 } 230 231 static Action shiftProtection(Parser p) 232 { 233 Token tok = p.popToken(); 234 switch(p.tok.id) 235 { 236 case TOK_dot: 237 case TOK_Identifier: 238 p.pushNode(new ast.BaseClass(tok.id, tok.span)); 239 p.pushState(&shiftBaseClass); 240 return GlobalIdentifierList.enter(p); 241 default: 242 return p.parseError("identifier expected after protection attribute"); 243 } 244 } 245 246 static Action shiftBaseClass(Parser p) 247 { 248 p.popAppendTopNode(); 249 auto bc = p.popNode!(ast.BaseClass)(); 250 p.topNode!(ast.InheritingAggregate).addBaseClass(bc); 251 switch(p.tok.id) 252 { 253 case TOK_comma: 254 p.pushState(&shiftColon); 255 return Accept; 256 case TOK_lcurly: 257 return shiftLcurly(p); 258 default: 259 return p.parseError("'{' expected after base class list"); 260 } 261 } 262 263 static Action shiftLparen(Parser p) 264 { 265 p.pushState(&shiftTemplateParameterList); 266 return TemplateParameterList.enter(p); 267 } 268 269 static Action shiftTemplateParameterList(Parser p) 270 { 271 switch(p.tok.id) 272 { 273 case TOK_rparen: 274 p.popAppendTopNode!(ast.Aggregate)(); 275 p.topNode!(ast.Aggregate).hasTemplArgs = true; 276 p.pushState(&shiftRparen); 277 return Accept; 278 default: 279 return p.parseError("')' expected after template parameter list"); 280 } 281 } 282 283 static Action shiftRparen(Parser p) 284 { 285 switch(p.tok.id) 286 { 287 case TOK_semicolon: 288 p.topNode!(ast.Aggregate).hasBody = false; 289 return Accept; 290 case TOK_colon: 291 if(!cast(ast.Class) p.topNode() && !cast(ast.Intrface) p.topNode()) 292 return p.parseError("only classes and interfaces support inheritance"); 293 p.pushState(&shiftColon); 294 return Accept; 295 case TOK_if: 296 p.pushState(&shiftConstraint); 297 return Constraint.enter(p); 298 case TOK_lcurly: 299 return shiftLcurly(p); 300 default: 301 return p.parseError("'{' expected after template parameter list"); 302 } 303 } 304 305 static Action shiftConstraint(Parser p) 306 { 307 p.popAppendTopNode!(ast.Aggregate)(); 308 p.topNode!(ast.Aggregate).hasConstraint = true; 309 switch(p.tok.id) 310 { 311 case TOK_semicolon: 312 p.topNode!(ast.Aggregate).hasBody = false; 313 return Accept; 314 case TOK_lcurly: 315 return shiftLcurly(p); 316 case TOK_colon: 317 if(!cast(ast.Class) p.topNode() && !cast(ast.Intrface) p.topNode()) 318 return p.parseError("only classes and interfaces support inheritance"); 319 p.pushState(&shiftColon); 320 return Accept; 321 default: 322 return p.parseError("'{' expected after constraint"); 323 } 324 } 325 326 static Action shiftLcurly(Parser p) 327 { 328 assert(p.tok.id == TOK_lcurly); 329 330 p.pushNode(new ast.StructBody(p.tok)); 331 p.pushState(&shiftDeclDefs); 332 p.pushState(&DeclDefs.enter); 333 return Accept; 334 } 335 336 static Action shiftDeclDefs(Parser p) 337 { 338 switch(p.tok.id) 339 { 340 case TOK_rcurly: 341 p.popAppendTopNode!(ast.Aggregate)(); 342 return Accept; 343 default: 344 return p.parseError("closing curly brace expected to terminate aggregate body"); 345 } 346 } 347 } 348 349 //-- GRAMMAR_BEGIN -- 350 //Constructor: 351 // this TemplateParameters_opt Parameters MemberFunctionAttributes_opt Constraint_opt FunctionBody 352 // this ( this ) Constraint_opt FunctionBody 353 class Constructor 354 { 355 mixin stateAppendClass!(FunctionBody, Parser.forward) stateFunctionBody; 356 ////////////////////////////////////////////////////////////// 357 358 mixin stateAppendClass!(Constraint, stateFunctionBody.shift) stateConstraint; 359 360 static Action stateMemberFunctionAttributes(Parser p) 361 { 362 switch(p.tok.id) 363 { 364 mixin(case_TOKs_MemberFunctionAttribute); 365 { 366 auto ctor = p.topNode!(ast.Constructor); 367 auto list = static_cast!(ast.ParameterList)(ctor.members[$-1]); 368 if(auto attr = tokenToAttribute(p.tok.id)) 369 p.combineAttributes(list.attr, attr); 370 if(auto annot = tokenToAnnotation(p.tok.id)) 371 p.combineAnnotations(list.annotation, annot); 372 373 p.pushState(&stateMemberFunctionAttributes); 374 return Accept; 375 } 376 case TOK_if: 377 return stateConstraint.shift(p); 378 default: 379 return stateFunctionBody.shift(p); 380 } 381 } 382 383 mixin stateAppendClass!(Parameters, stateMemberFunctionAttributes) stateParametersTemplate; 384 385 mixin stateAppendClass!(TemplateParameters, stateParametersTemplate.shift) stateTemplateParameterList; 386 387 ////////////////////////////////////////////////////////////// 388 static Action shiftRparen(Parser p) 389 { 390 switch(p.tok.id) 391 { 392 case TOK_lparen: 393 return Reject; // retry with template arguments 394 default: 395 p.popRollback(); 396 return stateMemberFunctionAttributes(p); 397 } 398 } 399 400 static Action shiftParameters(Parser p) 401 { 402 p.popAppendTopNode!(ast.Constructor)(); 403 switch(p.tok.id) 404 { 405 case TOK_rparen: 406 p.pushState(&shiftRparen); 407 return Accept; 408 default: 409 return p.parseError("')' expected"); 410 } 411 } 412 413 static Action gotoParameters(Parser p) 414 { 415 switch(p.tok.id) 416 { 417 case TOK_rparen: 418 p.topNode!(ast.Constructor)().addMember(new ast.ParameterList(p.tok)); 419 p.pushState(&shiftRparen); 420 return Accept; 421 default: 422 p.pushState(&shiftParameters); 423 return ParameterList.enter(p); 424 } 425 } 426 427 mixin stateShiftToken!(TOK_rparen, stateFunctionBody.shift) stateThis; 428 429 static Action gotoThis(Parser p) 430 { 431 p.popRollback(); 432 return stateThis.shift(p); 433 } 434 435 mixin stateShiftToken!(TOK_this, gotoThis, 436 -1, gotoParameters) stateParameters; 437 438 static Action rollbackParameters(Parser p) 439 { 440 p.topNode!(ast.Constructor)().reinit(); 441 442 assert(p.tok.id == TOK_lparen); 443 return stateTemplateParameterList.shift(p); 444 } 445 446 static Action stateLparen(Parser p) 447 { 448 switch(p.tok.id) 449 { 450 case TOK_lparen: 451 p.pushRollback(&rollbackParameters); 452 p.pushState(&stateParameters.shift); 453 return Accept; 454 default: 455 return p.parseError("'(' expected in constructor"); 456 } 457 } 458 459 mixin stateEnterToken!(TOK_this, ast.Constructor, stateLparen); 460 } 461 462 //-- GRAMMAR_BEGIN -- 463 //Destructor: 464 // ~ this ( ) FunctionBody 465 class Destructor 466 { 467 mixin SequenceNode!(ast.Destructor, TOK_tilde, TOK_this, TOK_lparen, TOK_rparen, FunctionBody); 468 } 469 470 //-- GRAMMAR_BEGIN -- 471 //StaticConstructor: 472 // static this ( ) FunctionBody 473 // 474 //StaticDestructor: 475 // static ~ this ( ) FunctionBody 476 // 477 //SharedStaticConstructor: 478 // shared static this ( ) FunctionBody 479 // 480 //SharedStaticDestructor: 481 // shared static ~ this ( ) FunctionBody 482 // 483 // 484 //StructAllocator: 485 // ClassAllocator 486 // 487 //StructDeallocator: 488 // ClassDeallocator 489 // 490 //StructConstructor: 491 // this ( ParameterList ) FunctionBody 492 // 493 //StructPostblit: 494 // this ( this ) FunctionBody 495 // 496 //StructDestructor: 497 // ~ this ( ) FunctionBody 498 // 499 // 500 //Invariant: 501 // invariant ( ) BlockStatement 502 class Invariant 503 { 504 mixin SequenceNode!(ast.Unittest, TOK_invariant, TOK_lparen, TOK_rparen, BlockStatement); 505 } 506 507 //-- GRAMMAR_BEGIN -- 508 //ClassAllocator: 509 // new Parameters FunctionBody 510 class ClassAllocator 511 { 512 mixin SequenceNode!(ast.ClassAllocator, TOK_new, Parameters, FunctionBody); 513 } 514 515 //-- GRAMMAR_BEGIN -- 516 //ClassDeallocator: 517 // delete Parameters FunctionBody 518 class ClassDeallocator 519 { 520 mixin SequenceNode!(ast.ClassDeallocator, TOK_delete, Parameters, FunctionBody); 521 }