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.tmpl; 10 11 import vdc.util; 12 import vdc.lexer; 13 import vdc.parser.engine; 14 import vdc.parser.decl; 15 import vdc.parser.expr; 16 import vdc.parser.mod; 17 import ast = vdc.ast.all; 18 19 //-- GRAMMAR_BEGIN -- 20 //TemplateDeclaration: 21 // template TemplateIdentifier ( TemplateParameterList ) Constraint_opt { DeclDefs } 22 class TemplateDeclaration 23 { 24 mixin SequenceNode!(ast.TemplateDeclaration, TOK_template, Identifier, TOK_lparen, 25 TemplateParameterList, TOK_rparen, Opt!(Constraint, TOK_if), DeclDefsBlock); 26 } 27 28 class DeclDefsBlock 29 { 30 mixin SequenceNode!(ast.DeclarationBlock, TOK_lcurly, DeclDefs, TOK_rcurly); 31 } 32 33 //-- GRAMMAR_BEGIN -- 34 //TemplateIdentifier: 35 // Identifier 36 // 37 //TemplateParameters: 38 // ( TemplateParameterList ) 39 class TemplateParameters 40 { 41 mixin SequenceNode!(NoASTNode, TOK_lparen, TemplateParameterList, TOK_rparen); 42 } 43 44 //-- GRAMMAR_BEGIN -- 45 //TemplateParameterList: 46 // TemplateParameter 47 // TemplateParameter , 48 // TemplateParameter , TemplateParameterList 49 class TemplateParameterList 50 { 51 mixin ListNode!(ast.TemplateParameterList, TemplateParameter, TOK_comma, true, true); 52 } 53 54 //-- GRAMMAR_BEGIN -- 55 //TemplateParameter: 56 // TemplateTypeParameter 57 // TemplateValueParameter 58 // TemplateAliasParameter 59 // TemplateTupleParameter 60 // TemplateThisParameter 61 // 62 //TemplateTupleParameter: 63 // Identifier ... 64 class TemplateParameter 65 { 66 static Action enter(Parser p) 67 { 68 switch(p.tok.id) 69 { 70 case TOK_Identifier: 71 p.pushToken(p.tok); 72 p.pushState(&shiftIdentifier); 73 return Accept; 74 75 case TOK_this: 76 return TemplateThisParameter.enter(p); 77 case TOK_alias: 78 return TemplateAliasParameter.enter(p); 79 default: 80 return TemplateValueParameter.enter(p); 81 } 82 } 83 84 static Action shiftIdentifier(Parser p) 85 { 86 switch(p.tok.id) 87 { 88 case TOK_comma: 89 case TOK_rparen: 90 Token tok = p.popToken(); 91 p.pushNode(new ast.TemplateTypeParameter(tok)); 92 return Forward; 93 94 case TOK_colon: 95 case TOK_assign: 96 return TemplateTypeParameter!false.enterIdentifier(p); 97 98 case TOK_dotdotdot: 99 Token tok = p.popToken(); 100 p.pushNode(new ast.TemplateTupleParameter(tok)); 101 return Accept; 102 103 default: 104 return TemplateValueParameter.enterIdentifier(p); 105 } 106 } 107 } 108 109 //-- GRAMMAR_BEGIN -- 110 //IdentifierOrTemplateInstance: 111 // Identifier 112 // TemplateInstance 113 // 114 //TemplateInstance: 115 // TemplateIdentifier ! ( TemplateArgumentList ) 116 // TemplateIdentifier ! TemplateSingleArgument 117 class IdentifierOrTemplateInstance 118 { 119 static Action enter(Parser p) 120 { 121 switch(p.tok.id) 122 { 123 case TOK_Identifier: 124 p.pushToken(p.tok); 125 p.pushState(&shiftIdentifier); 126 return Accept; 127 default: 128 return p.parseError("identifier expected"); 129 } 130 } 131 132 // assumes identifier token on the info stack 133 static Action enterIdentifier(Parser p) 134 { 135 return shiftIdentifier(p); 136 } 137 138 static Action shiftIdentifier(Parser p) 139 { 140 auto tok = p.popToken(); 141 switch(p.tok.id) 142 { 143 case TOK_not: 144 p.pushNode(new ast.TemplateInstance(tok)); 145 p.pushState(&shiftNot); 146 return Accept; 147 default: 148 p.pushNode(new ast.Identifier(tok)); 149 return Forward; 150 } 151 } 152 153 static Action shiftNot(Parser p) 154 { 155 switch(p.tok.id) 156 { 157 case TOK_lparen: 158 p.pushState(&shiftArgumentList); 159 p.pushState(&TemplateArgumentList.enter); 160 return Accept; 161 162 mixin(case_TOKs_TemplateSingleArgument); 163 p.pushNode(new ast.TemplateArgumentList(p.tok)); 164 p.pushState(&shiftSingleArgument); 165 return PrimaryExpression.enter(p); 166 167 case TOK___vector: 168 mixin(case_TOKs_BasicTypeX); 169 auto n = new ast.TemplateArgumentList(p.tok); 170 n.addMember(new ast.BasicType(p.tok)); 171 p.topNode!(ast.TemplateInstance).addMember(n); 172 return Accept; 173 174 default: 175 return p.parseError("'(' or single argument template expected after '!'"); 176 } 177 } 178 179 static Action shiftArgumentList(Parser p) 180 { 181 p.popAppendTopNode!(ast.TemplateInstance); 182 switch(p.tok.id) 183 { 184 case TOK_rparen: 185 return Accept; 186 default: 187 return p.parseError("closing parenthesis expected"); 188 } 189 } 190 191 static Action shiftSingleArgument(Parser p) 192 { 193 p.popAppendTopNode!(ast.TemplateArgumentList); 194 p.popAppendTopNode!(ast.TemplateInstance); 195 return Forward; 196 } 197 } 198 199 //-- GRAMMAR_BEGIN -- 200 //TemplateArgumentList: 201 // TemplateArgument 202 // TemplateArgument , 203 // TemplateArgument , TemplateArgumentList 204 // 205 //TemplateArgument: 206 // Type 207 // AssignExpression 208 // Symbol /* same as IdentifierList, so already in Type and AssignExpression */ 209 210 //Symbol: 211 // SymbolTail 212 // . SymbolTail 213 // 214 //// identical to IdentifierList 215 //SymbolTail: 216 // Identifier 217 // Identifier . SymbolTail 218 // TemplateInstance 219 // TemplateInstance . SymbolTail 220 class TemplateArgumentList 221 { 222 mixin ListNode!(ast.TemplateArgumentList, TypeOrExpression!(TOK_comma, TOK_rparen), TOK_comma, true, true); 223 } 224 225 //-- GRAMMAR_BEGIN -- 226 //TemplateSingleArgument: 227 // Identifier 228 // BasicTypeX 229 // CharacterLiteral 230 // StringLiteral 231 // IntegerLiteral 232 // FloatLiteral 233 // true 234 // false 235 // null 236 // __FILE__ 237 // __LINE__ 238 239 //-- GRAMMAR_BEGIN -- 240 //TemplateTypeParameter: 241 // Identifier 242 // Identifier TemplateTypeParameterSpecialization 243 // Identifier TemplateTypeParameterDefault 244 // Identifier TemplateTypeParameterSpecialization TemplateTypeParameterDefault 245 // 246 //TemplateTypeParameterSpecialization: 247 // : Type 248 // 249 //TemplateTypeParameterDefault: 250 // = Type 251 class TemplateTypeParameter(bool exprDefault = false) 252 { 253 static Action enter(Parser p) 254 { 255 switch(p.tok.id) 256 { 257 case TOK_Identifier: 258 p.pushNode(new ast.TemplateTypeParameter(p.tok)); 259 p.pushState(&shiftIdentifier); 260 return Accept; 261 default: 262 return p.parseError("identifier expected"); 263 } 264 } 265 266 static Action enterIdentifier(Parser p) 267 { 268 Token tok = p.popToken(); 269 p.pushNode(new ast.TemplateTypeParameter(tok)); 270 return shiftIdentifier(p); 271 } 272 273 static Action shiftIdentifier(Parser p) 274 { 275 switch(p.tok.id) 276 { 277 case TOK_colon: 278 p.pushState(&shiftSpecialization); 279 p.pushState(&Type.enter); 280 return Accept; 281 case TOK_assign: 282 p.pushState(&shiftDefault); 283 static if(exprDefault) 284 p.pushState(&TypeOrExpression!(TOK_rparen, TOK_comma).enter); 285 else 286 p.pushState(&Type.enter); 287 return Accept; 288 default: 289 return Forward; 290 } 291 } 292 293 static Action shiftSpecialization(Parser p) 294 { 295 auto special = p.popNode!(ast.Type)(); 296 auto param = p.topNode!(ast.TemplateTypeParameter); 297 param.specialization = special; 298 param.addMember(special); 299 300 switch(p.tok.id) 301 { 302 case TOK_assign: 303 p.pushState(&shiftDefault); 304 static if(exprDefault) 305 p.pushState(&TypeOrExpression!(TOK_rparen, TOK_comma).enter); 306 else 307 p.pushState(&Type.enter); 308 return Accept; 309 default: 310 return Forward; 311 } 312 } 313 314 static Action shiftDefault(Parser p) 315 { 316 auto def = p.popNode(); 317 auto param = p.topNode!(ast.TemplateTypeParameter); 318 param.def = def; 319 param.addMember(def); 320 return Forward; 321 } 322 } 323 324 //TemplateThisParameter: 325 // this TemplateTypeParameter 326 class TemplateThisParameter 327 { 328 mixin SequenceNode!(ast.TemplateThisParameter, TOK_this, TemplateTypeParameter!false); 329 } 330 331 //-- GRAMMAR_BEGIN -- 332 //TemplateValueParameter: 333 // TemplateValueDeclaration 334 // TemplateValueDeclaration TemplateValueParameterSpecialization 335 // TemplateValueDeclaration TemplateValueParameterDefault 336 // TemplateValueDeclaration TemplateValueParameterSpecialization TemplateValueParameterDefault 337 // 338 //TemplateValueDeclaration: 339 // ParameterDeclarator /* without storage classes */ 340 // 341 //TemplateValueParameterSpecialization: 342 // : ConditionalExpression 343 // 344 //TemplateValueParameterDefault: 345 // = __FILE__ /* already part of ConditionalExpression */ 346 // = __LINE__ /* already part of ConditionalExpression */ 347 // = ConditionalExpression 348 class TemplateValueParameter 349 { 350 static Action enter(Parser p) 351 { 352 p.pushNode(new ast.TemplateValueParameter(p.tok)); 353 p.pushState(&shiftDecl); 354 return ParameterDeclarator.enter(p); 355 } 356 357 static Action enterIdentifier(Parser p) 358 { 359 p.pushNode(new ast.TemplateValueParameter(p.tok)); 360 p.pushState(&shiftDecl); 361 return ParameterDeclarator.enterTypeIdentifier(p); 362 } 363 364 static Action shiftDecl(Parser p) 365 { 366 p.popAppendTopNode!(ast.TemplateValueParameter)(); 367 switch(p.tok.id) 368 { 369 case TOK_colon: 370 p.pushState(&shiftSpecialization); 371 p.pushState(&ConditionalExpression.enter); 372 return Accept; 373 case TOK_assign: 374 p.pushState(&shiftDefault); 375 p.pushState(&ConditionalExpression.enter); 376 return Accept; 377 default: 378 return Forward; 379 } 380 } 381 382 static Action shiftSpecialization(Parser p) 383 { 384 auto special = p.popNode!(ast.Expression)(); 385 auto param = p.topNode!(ast.TemplateValueParameter); 386 param.specialization = special; 387 param.addMember(special); 388 389 switch(p.tok.id) 390 { 391 case TOK_assign: 392 p.pushState(&shiftDefault); 393 p.pushState(&ConditionalExpression.enter); 394 return Accept; 395 default: 396 return Forward; 397 } 398 } 399 400 static Action shiftDefault(Parser p) 401 { 402 auto def = p.popNode!(ast.Expression)(); 403 auto param = p.topNode!(ast.TemplateValueParameter); 404 param.def = def; 405 param.addMember(def); 406 return Forward; 407 } 408 } 409 410 //-- GRAMMAR_BEGIN -- 411 //TemplateAliasParameter: 412 // alias Type_opt Identifier TemplateAliasParameterSpecialization_opt TemplateAliasParameterDefault_opt 413 // 414 //TemplateAliasParameterSpecialization: 415 // : Type 416 // 417 //TemplateAliasParameterDefault: 418 // = TypeOrExpression 419 class TemplateAliasParameter 420 { 421 mixin SequenceNode!(ast.TemplateAliasParameter, TOK_alias, TemplateTypeParameter!true); 422 } 423 424 //-- GRAMMAR_BEGIN -- 425 //ClassTemplateDeclaration: 426 // class Identifier ( TemplateParameterList ) Constraint_opt BaseClassList_opt ClassBody 427 // 428 //InterfaceTemplateDeclaration: 429 // interface Identifier ( TemplateParameterList ) Constraint_opt BaseInterfaceList_opt InterfaceBody 430 // 431 //TemplateMixinDeclaration: 432 // mixin template TemplateIdentifier ( TemplateParameterList ) Constraint_opt { DeclDefs } 433 class TemplateMixinDeclaration 434 { 435 static Action enter(Parser p) 436 { 437 switch(p.tok.id) 438 { 439 case TOK_mixin: 440 p.pushState(&shiftTemplateDeclaration); 441 p.pushState(&TemplateDeclaration.enter); 442 return Accept; 443 default: 444 return p.parseError("mixin expected in mixin template declaration"); 445 } 446 } 447 448 static Action enterAfterMixin(Parser p) 449 { 450 p.pushState(&shiftTemplateDeclaration); 451 return TemplateDeclaration.enter(p); 452 } 453 454 static Action shiftTemplateDeclaration(Parser p) 455 { 456 p.topNode!(ast.TemplateDeclaration).id = TOK_mixin; 457 return Forward; 458 } 459 } 460 461 //TemplateMixin: 462 // mixin TemplateIdentifier ; 463 // mixin TemplateIdentifier MixinIdentifier ; 464 // mixin TemplateIdentifier ! ( TemplateArgumentList ) ; 465 // mixin TemplateIdentifier ! ( TemplateArgumentList ) MixinIdentifier ; 466 // 467 //MixinIdentifier: 468 // Identifier 469 // 470 // translated to 471 //-- GRAMMAR_BEGIN -- 472 //TemplateMixin: 473 // mixin GlobalIdentifierList MixinIdentifier_opt ; 474 // mixin Typeof . IdentifierList MixinIdentifier_opt ; 475 class TemplateMixin 476 { 477 mixin SequenceNode!(ast.TemplateMixin, TOK_mixin, GlobalIdentifierList, Opt!(Identifier, TOK_Identifier), TOK_semicolon); 478 479 static Action enterAfterMixin(Parser p) 480 { 481 p.pushNode(new ast.TemplateMixin(p.tok)); 482 switch(p.tok.id) 483 { 484 case TOK_typeof: 485 p.pushState(&shiftTypeof); 486 return PostfixExpression.enter(p); 487 default: 488 return shift1.shift(p); 489 } 490 } 491 492 static Action shiftTypeof(Parser p) 493 { 494 // already in shift2.shift(): p.popAppendTopNode!(ast.TemplateMixin)(); 495 return shift2.shift(p); 496 } 497 } 498 499 //-- GRAMMAR_BEGIN -- 500 //Constraint: 501 // if ( ConstraintExpression ) 502 // 503 //ConstraintExpression: 504 // Expression 505 class Constraint 506 { 507 mixin SequenceNode!(ast.Constraint, TOK_if, TOK_lparen, Expression, TOK_rparen); 508 }