changeset 505:3bb94ba21490

Refactored a great amount of code. Changed many declaration types from Token* to Identifier*. Fix in parseStructInitializer(): append null to idents in else body. Fixed class Parameter and parseParameterList().
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Wed, 12 Dec 2007 02:25:42 +0100
parents 9076c4cea2a4
children 1b897a4536a4
files trunk/src/dil/Declarations.d trunk/src/dil/Expressions.d trunk/src/dil/Identifier.d trunk/src/dil/Parser.d trunk/src/dil/Settings.d trunk/src/dil/Statements.d trunk/src/dil/Types.d
diffstat 7 files changed, 318 insertions(+), 325 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/src/dil/Declarations.d	Tue Dec 11 17:02:42 2007 +0100
+++ b/trunk/src/dil/Declarations.d	Wed Dec 12 02:25:42 2007 +0100
@@ -209,10 +209,10 @@
 
 class EnumDeclaration : Declaration
 {
-  Token* name;
+  Identifier* name;
   Type baseType;
   EnumMember[] members;
-  this(Token* name, Type baseType, EnumMember[] members, bool hasBody)
+  this(Identifier* name, Type baseType, EnumMember[] members, bool hasBody)
   {
     super.hasBody = hasBody;
     mixin(set_kind);
@@ -227,9 +227,9 @@
 
 class EnumMember : Node
 {
-  Token* name;
+  Identifier* name;
   Expression value;
-  this(Token* name, Expression value)
+  this(Identifier* name, Expression value)
   {
     super(NodeCategory.Other);
     mixin(set_kind);
@@ -242,11 +242,11 @@
 
 class ClassDeclaration : Declaration
 {
-  Token* name;
+  Identifier* name;
   TemplateParameters tparams;
   BaseClass[] bases;
   Declarations decls;
-  this(Token* name, TemplateParameters tparams, BaseClass[] bases, Declarations decls)
+  this(Identifier* name, TemplateParameters tparams, BaseClass[] bases, Declarations decls)
   {
     super.hasBody = decls !is null;
     mixin(set_kind);
@@ -263,11 +263,11 @@
 
 class InterfaceDeclaration : Declaration
 {
-  Token* name;
+  Identifier* name;
   TemplateParameters tparams;
   BaseClass[] bases;
   Declarations decls;
-  this(Token* name, TemplateParameters tparams, BaseClass[] bases, Declarations decls)
+  this(Identifier* name, TemplateParameters tparams, BaseClass[] bases, Declarations decls)
   {
     super.hasBody = decls !is null;
     mixin(set_kind);
@@ -284,11 +284,11 @@
 
 class StructDeclaration : Declaration
 {
-  Token* name;
+  Identifier* name;
   TemplateParameters tparams;
   Declarations decls;
   uint alignSize;
-  this(Token* name, TemplateParameters tparams, Declarations decls)
+  this(Identifier* name, TemplateParameters tparams, Declarations decls)
   {
     super.hasBody = decls !is null;
     mixin(set_kind);
@@ -308,10 +308,10 @@
 
 class UnionDeclaration : Declaration
 {
-  Token* name;
+  Identifier* name;
   TemplateParameters tparams;
   Declarations decls;
-  this(Token* name, TemplateParameters tparams, Declarations decls)
+  this(Identifier* name, TemplateParameters tparams, Declarations decls)
   {
     super.hasBody = decls !is null;
     mixin(set_kind);
@@ -382,12 +382,12 @@
 class FunctionDeclaration : Declaration
 {
   Type returnType;
-  Token* funcName;
+  Identifier* funcName;
   TemplateParameters tparams;
   Parameters params;
   FunctionBody funcBody;
   LinkageType linkageType;
-  this(Type returnType, Token* funcName, TemplateParameters tparams,
+  this(Type returnType, Identifier* funcName, TemplateParameters tparams,
        Parameters params, FunctionBody funcBody)
   {
     super.hasBody = funcBody.funcBody !is null;
@@ -413,10 +413,10 @@
 class VariableDeclaration : Declaration
 {
   Type type;
-  Token*[] idents;
+  Identifier*[] idents;
   Expression[] values;
   LinkageType linkageType;
-  this(Type type, Token*[] idents, Expression[] values)
+  this(Type type, Identifier*[] idents, Expression[] values)
   {
     mixin(set_kind);
     addOptChild(type);
@@ -460,7 +460,7 @@
   }
 }
 
-class DebugDeclaration : Declaration
+abstract class ConditionalCompilationDeclaration : Declaration
 {
   Token* spec;
   Token* cond;
@@ -469,7 +469,6 @@
   this(Token* spec, Token* cond, Declaration decls, Declaration elseDecls)
   {
     super.hasBody = decls !is null;
-    mixin(set_kind);
     addOptChild(decls);
     addOptChild(elseDecls);
 
@@ -480,23 +479,21 @@
   }
 }
 
-class VersionDeclaration : Declaration
+class DebugDeclaration : ConditionalCompilationDeclaration
 {
-  Token* spec;
-  Token* cond;
-  Declaration decls, elseDecls;
-
   this(Token* spec, Token* cond, Declaration decls, Declaration elseDecls)
   {
-    super.hasBody = decls !is null;
+    super(spec, cond, decls, elseDecls);
     mixin(set_kind);
-    addOptChild(decls);
-    addOptChild(elseDecls);
+  }
+}
 
-    this.spec = spec;
-    this.cond = cond;
-    this.decls = decls;
-    this.elseDecls = elseDecls;
+class VersionDeclaration : ConditionalCompilationDeclaration
+{
+  this(Token* spec, Token* cond, Declaration decls, Declaration elseDecls)
+  {
+    super(spec, cond, decls, elseDecls);
+    mixin(set_kind);
   }
 }
 
@@ -535,10 +532,10 @@
 
 class TemplateDeclaration : Declaration
 {
-  Token* name;
+  Identifier* name;
   TemplateParameters tparams;
   Declarations decls;
-  this(Token* name, TemplateParameters tparams, Declarations decls)
+  this(Identifier* name, TemplateParameters tparams, Declarations decls)
   {
     super.hasBody = true;
     mixin(set_kind);
@@ -607,14 +604,6 @@
     mixin(set_kind);
     this.prot = prot;
   }
-
-  void semantic(Scope scop)
-  {
-//     auto saved_prot = scop.protection;
-//     scop.protection = this.prot;
-//     decls.semantic(scop);
-//     scop.protection = saved_prot;
-  }
 }
 
 class StorageClassDeclaration : AttributeDeclaration
@@ -654,9 +643,9 @@
 
 class PragmaDeclaration : AttributeDeclaration
 {
-  Token* ident;
+  Identifier* ident;
   Expression[] args;
-  this(Token* ident, Expression[] args, Declaration decls)
+  this(Identifier* ident, Expression[] args, Declaration decls)
   {
     addOptChildren(args); // Add args before calling super().
     super(TOK.Pragma, decls);
@@ -670,10 +659,10 @@
 class MixinDeclaration : Declaration
 {
   Expression[] templateIdents;
-  Token* mixinIdent;
+  Identifier* mixinIdent;
   Expression argument; // mixin ( AssignExpression )
 
-  this(Expression[] templateIdents, Token* mixinIdent)
+  this(Expression[] templateIdents, Identifier* mixinIdent)
   {
     mixin(set_kind);
     addChildren(templateIdents);
--- a/trunk/src/dil/Expressions.d	Tue Dec 11 17:02:42 2007 +0100
+++ b/trunk/src/dil/Expressions.d	Wed Dec 12 02:25:42 2007 +0100
@@ -583,8 +583,8 @@
 
 class IdentifierExpression : Expression
 {
-  Token* identifier;
-  this(Token* identifier)
+  Identifier* identifier;
+  this(Identifier* identifier)
   {
     mixin(set_kind);
     this.identifier = identifier;
@@ -633,9 +633,9 @@
 
 class TemplateInstanceExpression : Expression
 {
-  Token* ident;
+  Identifier* ident;
   TemplateArguments targs;
-  this(Token* ident, TemplateArguments targs)
+  this(Identifier* ident, TemplateArguments targs)
   {
     mixin(set_kind);
     addOptChild(targs);
@@ -828,8 +828,8 @@
 class TypeDotIdExpression : Expression
 {
   Type type;
-  Token* ident;
-  this(Type type, Token* ident)
+  Identifier* ident;
+  this(Type type, Identifier* ident)
   {
     mixin(set_kind);
     addChild(type);
@@ -852,11 +852,12 @@
 class IsExpression : Expression
 {
   Type type;
-  Token* ident;
+  Identifier* ident;
   Token* opTok, specTok;
   Type specType;
   TemplateParameters tparams; // D 2.0
-  this(Type type, Token* ident, Token* opTok, Token* specTok, Type specType, typeof(tparams) tparams)
+  this(Type type, Identifier* ident, Token* opTok, Token* specTok,
+       Type specType, typeof(tparams) tparams)
   {
     mixin(set_kind);
     addChild(type);
@@ -905,7 +906,7 @@
 {
 class TraitsExpression : Expression
 {
-  Token* ident;
+  Identifier* ident;
   TemplateArguments targs;
   this(typeof(ident) ident, typeof(targs) targs)
   {
@@ -945,9 +946,9 @@
 
 class StructInitializer : Expression
 {
-  Token*[] idents;
+  Identifier*[] idents;
   Expression[] values;
-  this(Token*[] idents, Expression[] values)
+  this(Identifier*[] idents, Expression[] values)
   {
     mixin(set_kind);
     addOptChildren(values);
--- a/trunk/src/dil/Identifier.d	Tue Dec 11 17:02:42 2007 +0100
+++ b/trunk/src/dil/Identifier.d	Wed Dec 12 02:25:42 2007 +0100
@@ -14,7 +14,15 @@
   TOK type;
   ID identID;
 
-  static Identifier* opCall(string str, TOK type, ID identID = ID.Null)
+  static Identifier* opCall(string str, TOK type)
+  {
+    auto id = new Identifier;
+    id.str = str;
+    id.type = type;
+    return id;
+  }
+
+  static Identifier* opCall(string str, TOK type, ID identID)
   {
     auto id = new Identifier;
     id.str = str;
--- a/trunk/src/dil/Parser.d	Tue Dec 11 17:02:42 2007 +0100
+++ b/trunk/src/dil/Parser.d	Wed Dec 12 02:25:42 2007 +0100
@@ -160,7 +160,7 @@
     do
     {
       nT();
-      moduleFQN ~= requireIdentifier("expected module identifier, not '{}'");
+      moduleFQN ~= requireIdentifier(MSG.ExpectedModuleIdentifier);
     } while (token.type == T.Dot)
     require(T.Semicolon);
     return set(new ModuleDeclaration(moduleFQN), begin);
@@ -366,7 +366,7 @@
               token.type != T.RBrace &&
               token.type != T.EOF)
       auto text = Token.textSpan(begin, this.prevToken);
-      error(begin, "illegal Declaration found: " ~ text);
+      error(begin, MSG.IllegalDeclaration ~ text);
     }
     decl.setProtection(this.protection);
     decl.setStorageClass(this.storageClass);
@@ -432,14 +432,14 @@
   {
     auto begin = token;
     Type type;
-    Token* ident;
+    Identifier* ident;
 
     // Check for AutoDeclaration: StorageClasses Identifier =
     if (testAutoDeclaration &&
         token.type == T.Identifier &&
         peekNext() == T.Assign)
     {
-      ident = token;
+      ident = token.ident;
       nT();
     }
     else
@@ -462,7 +462,7 @@
       }
       else
       {
-        ident = requireId();
+        ident = requireIdentifier(MSG.ExpectedFunctionName);
         // Type FunctionName ( ParameterList ) FunctionBody
         if (token.type == T.LParen)
         {
@@ -503,13 +503,13 @@
     }
 
     // It's a variable declaration.
-    Token*[] idents = [ident];
+    Identifier*[] idents = [ident];
     Expression[] values;
     goto LenterLoop; // We've already parsed an identifier. Jump to if statement and check for initializer.
     while (token.type == T.Comma)
     {
       nT();
-      idents ~= requireId();
+      idents ~= requireIdentifier(MSG.ExpectedVariableName);
     LenterLoop:
       if (token.type == T.Assign)
         nT(), (values ~= parseInitializer());
@@ -581,22 +581,22 @@
       //         { StructMemberInitializers }
       Expression parseStructInitializer()
       {
-        Token*[] idents;
+        Identifier*[] idents;
         Expression[] values;
 
         nT();
         while (token.type != T.RBrace)
         {
-          if (token.type == T.Identifier)
+          if (token.type == T.Identifier &&
+              // Peek for colon to see if this is a member identifier.
+              peekNext() == T.Colon)
           {
-            // Peek for colon to see if this is a member identifier.
-            if (peekNext() == T.Colon)
-            {
-              idents ~= token;
-              nT();
-              nT();
-            }
+            idents ~= token.ident;
+            nT(), nT(); // Skip Identifier :
           }
+          else
+            idents ~= null;
+
           // NonVoidInitializer
           values ~= parseNonVoidInitializer();
 
@@ -651,7 +651,7 @@
         if (token.type == T.LParen)
         {
           nT();
-          func.outIdent = requireId();
+          func.outIdent = requireIdentifier(MSG.ExpectedAnIdentifier);
           require(T.RParen);
         }
         func.outBody = parseStatements();
@@ -660,7 +660,7 @@
         nT();
         goto case T.LBrace;
       default:
-        error(MID.ExpectedButFound, "FunctionBody", token.srcText);
+        error(token, MSG.ExpectedFunctionBody, token.srcText);
       }
       break; // Exit loop.
     }
@@ -723,7 +723,7 @@
       prev_lt = lt;
     else
       // TODO: create new msg RedundantLinkageType.
-      error(begin, "redundant linkage type: " ~ Token.textSpan(begin, this.prevToken));
+      error(begin, MSG.RedundantLinkageType ~ Token.textSpan(begin, this.prevToken));
   }
 
   Declaration parseStorageAttribute()
@@ -867,30 +867,17 @@
       //     pragma ( Identifier )
       //     pragma ( Identifier , ExpressionList )
       nT();
-      Token* ident;
+      Identifier* ident;
       Expression[] args;
-      Declaration decls;
 
       require(T.LParen);
-      ident = requireId();
+      ident = requireIdentifier(MSG.ExpectedPragmaIdentifier);
 
       if (token.type == T.Comma)
-      {
-        nT();
-        args = parseExpressionList();
-      }
+        nT(), (args = parseExpressionList());
       require(T.RParen);
 
-      if (token.type == T.Semicolon)
-      {
-        nT();
-        // TODO: call set()?
-        decls = new EmptyDeclaration();
-      }
-      else
-        decls = parseDeclarationsBlock();
-
-      decl = new PragmaDeclaration(ident, args, decls);
+      decl = new PragmaDeclaration(ident, args, parseDeclarationsBlock());
       break;
     default:
       // Protection attributes
@@ -947,14 +934,14 @@
       // AliasName = ModuleName
       if (peekNext() == T.Assign)
       {
-        moduleAlias = requireIdentifier("expected alias module name, not '{}'");
+        moduleAlias = requireIdentifier(MSG.ExpectedAliasModuleName);
         nT(); // Skip =
       }
 
       // Identifier(.Identifier)*
       while (1)
       {
-        moduleFQN ~= requireIdentifier("expected module identifier, not '{}'");
+        moduleFQN ~= requireIdentifier(MSG.ExpectedModuleIdentifier);
         if (token.type != T.Dot)
           break;
         nT();
@@ -980,11 +967,11 @@
         // BindAlias = BindName
         if (peekNext() == T.Assign)
         {
-          bindAlias = requireIdentifier("expected alias name, not '{}'");
+          bindAlias = requireIdentifier(MSG.ExpectedAliasImportName);
           nT(); // Skip =
         }
         // Push identifiers.
-        bindNames ~= requireIdentifier("expected an identifier, not '{}'");
+        bindNames ~= requireIdentifier(MSG.ExpectedImportName);
         bindAliases ~= bindAlias;
       } while (token.type == T.Comma)
     }
@@ -998,18 +985,14 @@
   {
     assert(token.type == T.Enum);
 
-    Token* enumName;
+    Identifier* enumName;
     Type baseType;
     EnumMember[] members;
     bool hasBody;
 
     nT(); // Skip enum keyword.
 
-    if (token.type == T.Identifier)
-    {
-      enumName = token;
-      nT();
-    }
+    enumName = optionalIdentifier();
 
     if (token.type == T.Colon)
     {
@@ -1030,18 +1013,15 @@
       while (token.type != T.RBrace)
       {
         auto begin = token;
-        auto memberName = requireId();
+        auto name = requireIdentifier(MSG.ExpectedEnumMember);
         Expression value;
 
         if (token.type == T.Assign)
-        {
-          nT();
-          value = parseAssignExpression();
-        }
+          nT(), (value = parseAssignExpression());
         else
           value = null;
 
-        members ~= set(new EnumMember(memberName, value), begin);
+        members ~= set(new EnumMember(name, value), begin);
 
         if (token.type != T.Comma)
           break;
@@ -1050,7 +1030,7 @@
       require(T.RBrace);
     }
     else
-      error(MID.ExpectedButFound, "enum declaration", token.srcText);
+      error(token, MSG.ExpectedEnumBody, token.srcText);
 
     return new EnumDeclaration(enumName, baseType, members, hasBody);
   }
@@ -1059,13 +1039,13 @@
   {
     assert(token.type == T.Class);
 
-    Token* className;
+    Identifier* className;
     TemplateParameters tparams;
     BaseClass[] bases;
     Declarations decls;
 
     nT(); // Skip class keyword.
-    className = requireId();
+    className = requireIdentifier(MSG.ExpectedClassName);
 
     if (token.type == T.LParen)
       tparams = parseTemplateParameterList();
@@ -1082,7 +1062,7 @@
     else if (token.type == T.LBrace)
       decls = parseDeclarationDefinitionsBody();
     else
-      expected(T.LBrace); // TODO: better error msg
+      error(token, MSG.ExpectedClassBody, token.srcText);
 
     return new ClassDeclaration(className, tparams, bases, decls);
   }
@@ -1129,13 +1109,13 @@
   {
     assert(token.type == T.Interface);
 
-    Token* name;
+    Identifier* name;
     TemplateParameters tparams;
     BaseClass[] bases;
     Declarations decls;
 
     nT(); // Skip interface keyword.
-    name = requireId();
+    name = requireIdentifier(MSG.ExpectedInterfaceName);
 
     if (token.type == T.LParen)
       tparams = parseTemplateParameterList();
@@ -1152,7 +1132,7 @@
     else if (token.type == T.LBrace)
       decls = parseDeclarationDefinitionsBody();
     else
-      expected(T.LBrace); // TODO: better error msg
+      error(token, MSG.ExpectedInterfaceBody, token.srcText);
 
     return new InterfaceDeclaration(name, tparams, bases, decls);
   }
@@ -1163,19 +1143,16 @@
 
     TOK tok = token.type;
 
-    Token* name;
+    Identifier* name;
     TemplateParameters tparams;
     Declarations decls;
 
     nT(); // Skip struct or union keyword.
-    // name is optional.
-    if (token.type == T.Identifier)
-    {
-      name = token;
-      nT();
-      if (token.type == T.LParen)
-        tparams = parseTemplateParameterList();
-    }
+
+    name = optionalIdentifier();
+
+    if (name && token.type == T.LParen)
+      tparams = parseTemplateParameterList();
 
     if (token.type == T.Semicolon)
     {
@@ -1190,9 +1167,9 @@
 
     if (tok == T.Struct)
     {
-      auto d = new StructDeclaration(name, tparams, decls);
-      d.setAlignSize(this.alignSize);
-      return d;
+      auto sd = new StructDeclaration(name, tparams, decls);
+      sd.setAlignSize(this.alignSize);
+      return sd;
     }
     else
       return new UnionDeclaration(name, tparams, decls);
@@ -1427,7 +1404,7 @@
   {
     assert(token.type == T.Template);
     nT(); // Skip template keyword.
-    auto templateName = requireId();
+    auto templateName = requireIdentifier(MSG.ExpectedTemplateName);
     auto templateParams = parseTemplateParameterList();
     auto decls = parseDeclarationDefinitionsBody();
     return new TemplateDeclaration(templateName, templateParams, decls);
@@ -1512,17 +1489,18 @@
     while (1)
     {
       begin = token;
-      auto ident = requireId();
+      auto ident = requireIdentifier(MSG.ExpectedAnIdentifier);
       Expression e;
       if (token.type == T.Not && peekNext() == T.LParen) // Identifier !( TemplateArguments )
       {
         nT(); // Skip !.
-        e = set(new TemplateInstanceExpression(ident, parseTemplateArguments()), begin);
+        auto tparams = parseTemplateArguments();
+        e = new TemplateInstanceExpression(ident, tparams);
       }
       else // Identifier
-        e = set(new IdentifierExpression(ident), begin);
-
-      identList ~= e;
+        e = new IdentifierExpression(ident);
+
+      identList ~= set(e, begin);
 
     LnewExpressionLoop:
       if (token.type != T.Dot)
@@ -1575,15 +1553,18 @@
     while (1)
     {
       begin = token;
-      auto ident = requireId();
+      auto ident = requireIdentifier(MSG.ExpectedAnIdentifier);
+      Type t;
       // NB.: Currently Types can't be followed by "!=" so we don't need to peek for "(" when parsing TemplateInstances.
       if (token.type == T.Not/+ && peekNext() == T.LParen+/) // Identifier !( TemplateArguments )
       {
         nT(); // Skip !.
-        identList ~= set(new TemplateInstanceType(ident, parseTemplateArguments()), begin);
+        t = new TemplateInstanceType(ident, parseTemplateArguments());
       }
       else // Identifier
-        identList ~= set(new IdentifierType(ident), begin);
+        t = new IdentifierType(ident);
+
+      identList ~= set(t, begin);
 
       if (token.type != T.Dot)
         break;
@@ -1604,7 +1585,6 @@
   Class parseMixin(Class)()
   {
     assert(token.type == T.Mixin);
-    auto begin = token;
     nT(); // Skip mixin keyword.
 
   static if (is(Class == MixinDeclaration))
@@ -1620,8 +1600,9 @@
     }
   }
 
+    auto begin = token;
     Expression[] templateIdent;
-    Token* mixinIdent;
+    Identifier* mixinIdent;
 
     // This code is similar to parseDotListType().
     if (token.type == T.Dot)
@@ -1633,30 +1614,26 @@
     while (1)
     {
       begin = token;
-      auto ident = requireId();
+      auto ident = requireIdentifier(MSG.ExpectedAnIdentifier);
       Expression e;
       if (token.type == T.Not) // Identifier !( TemplateArguments )
       {
         // No need to peek for T.LParen. This must be a template instance.
         nT();
-        e = set(new TemplateInstanceExpression(ident, parseTemplateArguments()), begin);
+        auto tparams = parseTemplateArguments();
+        e = new TemplateInstanceExpression(ident, tparams);
       }
       else // Identifier
-        e = set(new IdentifierExpression(ident), begin);
-
-      templateIdent ~= e;
+        e = new IdentifierExpression(ident);
+
+      templateIdent ~= set(e, begin);
 
       if (token.type != T.Dot)
         break;
       nT();
     }
 
-    if (token.type == T.Identifier)
-    {
-      mixinIdent = token;
-      nT();
-    }
-
+    mixinIdent = optionalIdentifier();
     require(T.Semicolon);
 
     return new Class(templateIdent, mixinIdent);
@@ -1722,9 +1699,8 @@
     case T.Identifier:
       if (peekNext() == T.Colon)
       {
-        auto ident = token;
-        nT(); // Skip Identifier
-        nT(); // Skip :
+        auto ident = token.ident;
+        nT(), nT(); // Skip Identifier :
         s = new LabeledStatement(ident, parseNoScopeOrEmptyStatement());
         break;
       }
@@ -1934,7 +1910,7 @@
               token.type != T.RBrace &&
               token.type != T.EOF)
       auto text = Token.textSpan(begin, this.prevToken);
-      error(begin, "illegal Statement found: " ~ text);
+      error(begin, MSG.IllegalStatement ~ text);
     }
     assert(s !is null);
     set(s, begin);
@@ -1973,7 +1949,7 @@
     }
     else if (token.type == T.Semicolon)
     {
-      error(MID.ExpectedButFound, "non-empty statement", ";");
+      error(token, MSG.ExpectedNonEmptyStatement);
       nT();
       s = set(new EmptyStatement(), begin);
     }
@@ -2085,17 +2061,17 @@
 
     require(T.LParen);
 
-    Token* ident;
+    Identifier* ident;
     auto begin = token; // For start of AutoDeclaration or normal Declaration.
     // auto Identifier = Expression
     if (token.type == T.Auto)
     {
       nT();
-      ident = requireId();
+      ident = requireIdentifier(MSG.ExpectedVariableName);
       require(T.Assign);
       auto init = parseExpression();
       auto v = new VariableDeclaration(null, [ident], [init]);
-      set(v, ident);
+      set(v, begin.nextNWS);
       auto d = new StorageClassDeclaration(StorageClass.Auto, T.Auto, v);
       set(d, begin);
       variable = new DeclarationStatement(d);
@@ -2191,21 +2167,21 @@
     while (1)
     {
       auto paramBegin = token;
-      Token* stcTok;
+      StorageClass stc;
       Type type;
-      Token* ident;
+      Identifier* ident;
 
       switch (token.type)
       {
       case T.Ref, T.Inout:
-        stcTok = token;
+        stc = StorageClass.Ref;
         nT();
         // fall through
       case T.Identifier:
         auto next = peekNext();
         if (next == T.Comma || next == T.Semicolon || next == T.RParen)
         {
-          ident = token;
+          ident = requireIdentifier(MSG.ExpectedVariableName);
           nT();
           break;
         }
@@ -2214,7 +2190,7 @@
         type = parseDeclarator(ident);
       }
 
-      params ~= set(new Parameter(stcTok, type, ident, null), paramBegin);
+      params ~= set(new Parameter(stc, type, ident, null), paramBegin);
 
       if (token.type != T.Comma)
         break;
@@ -2293,12 +2269,7 @@
   {
     assert(token.type == T.Continue);
     nT();
-    Token* ident;
-    if (token.type == T.Identifier)
-    {
-      ident = token;
-      nT();
-    }
+    auto ident = optionalIdentifier();
     require(T.Semicolon);
     return new ContinueStatement(ident);
   }
@@ -2307,13 +2278,7 @@
   {
     assert(token.type == T.Break);
     nT();
-    Token* ident;
-    if (token.type == T.Identifier)
-    {
-      ident = token;
-      nT();
-    }
-    require(T.Semicolon);
+    auto ident = optionalIdentifier();
     return new BreakStatement(ident);
   }
 
@@ -2332,7 +2297,7 @@
   {
     assert(token.type == T.Goto);
     nT();
-    Token* ident;
+    Identifier* ident;
     Expression caseExpr;
     switch (token.type)
     {
@@ -2346,7 +2311,7 @@
       nT();
       break;
     default:
-      ident = requireId();
+      ident = requireIdentifier(MSG.ExpectedAnIdentifier);
     }
     require(T.Semicolon);
     return new GotoStatement(ident, caseExpr);
@@ -2394,9 +2359,9 @@
       {
         nT();
         auto begin = token;
-        Token* ident;
+        Identifier* ident;
         auto type = parseDeclarator(ident, true);
-        param = new Parameter(null, type, ident, null);
+        param = new Parameter(StorageClass.None, type, ident, null);
         set(param, begin);
         require(T.RParen);
       }
@@ -2436,16 +2401,15 @@
     nT();
     assert(token.type == T.LParen);
     nT();
-
-    Token* condition = requireId();
+    auto condition = requireIdentifier(MSG.ExpectedScopeIdentifier);
     if (condition)
-      switch (condition.ident.identID)
+      switch (condition.identID)
       {
       case ID.exit, ID.success, ID.failure:
         break;
       default:
         // TODO: create MID.InvalidScopeIdentifier
-        error(condition, "'exit', 'success', 'failure' are valid scope identifiers, but not '{}';", condition.srcText);
+        error(this.prevToken, MSG.InvalidScopeIdentifier, this.prevToken.srcText);
       }
     require(T.RParen);
     Statement scopeBody;
@@ -2475,12 +2439,12 @@
     assert(token.type == T.Pragma);
     nT();
 
-    Token* ident;
+    Identifier* ident;
     Expression[] args;
     Statement pragmaBody;
 
     require(T.LParen);
-    ident = requireId();
+    ident = requireIdentifier(MSG.ExpectedPragmaIdentifier);
 
     if (token.type == T.Comma)
     {
@@ -2664,16 +2628,16 @@
   {
     auto begin = token;
     Statement s;
-    typeof(token) ident;
+    Identifier* ident;
     switch (token.type)
     {
     // Keywords that are valid opcodes.
     case T.In, T.Int, T.Out:
-      ident = token;
+      ident = token.ident;
       nT();
       goto LOpcode;
     case T.Identifier:
-      ident = token;
+      ident = token.ident;
       nT(); // Skip Identifier
       if (token.type == T.Colon)
       {
@@ -2703,19 +2667,13 @@
       s = new AsmInstruction(ident, es);
       break;
     case T.Align:
+      // align Integer;
       nT();
-      auto number = token;
-      switch (token.type)
-      {
-      case T.Int32, T.Int64, T.Uint32, T.Uint64:
-        number = token; nT(); break;
-      default:
-        if (token.type != T.Semicolon)
-          nT();
-        number = null;
-        // TODO: report error: number expected after asm align statement.
-        error(token, "expected an integer after align, not '{}'", token.srcText);
-      }
+      int number = -1;
+      if (token.type == T.Int32)
+        (number = token.int_), nT();
+      else
+        error(token, MSG.ExpectedIntegerAfterAlign, token.srcText);
       require(T.Semicolon);
       s = new AsmAlignStatement(number);
       break;
@@ -2732,7 +2690,7 @@
               token.type != T.RBrace &&
               token.type != T.EOF)
       auto text = Token.textSpan(begin, this.prevToken);
-      error(begin, "illegal AsmInstruction found: " ~ text);
+      error(begin, MSG.IllegalAsmInstructino ~ text);
     }
     set(s, begin);
     return s;
@@ -3078,7 +3036,7 @@
         while (1)
         {
           auto begin2 = token;
-          auto ident = requireId();
+          auto ident = requireIdentifier(MSG.ExpectedAnIdentifier);
           e = new IdentifierExpression(ident);
           set(e, begin2);
           identList ~= e;
@@ -3511,7 +3469,7 @@
       auto type = try_(&parseType_, success);
       if (success)
       {
-        auto ident = requireId();
+        auto ident = requireIdentifier(MSG.ExpectedIdAfterTypeDot);
         e = new TypeDotIdExpression(type, ident);
         break;
       }
@@ -3671,7 +3629,7 @@
       requireNext(T.LParen);
 
       Type type, specType;
-      Token* ident; // optional Identifier
+      Identifier* ident; // optional Identifier
       Token* opTok, specTok;
 
       type = parseDeclarator(ident, true);
@@ -3746,7 +3704,7 @@
       nT();
       set(type, begin);
       require(T.Dot);
-      auto ident = requireId();
+      auto ident = requireIdentifier(MSG.ExpectedIdAfterTypeDot);
 
       e = new TypeDotIdExpression(type, ident);
       break;
@@ -3755,7 +3713,7 @@
     case T.Traits:
       nT();
       require(T.LParen);
-      auto id = requireId();
+      auto id = requireIdentifier(MSG.ExpectedAnIdentifier);
       TemplateArguments args;
       if (token.type == T.Comma)
         args = parseTemplateArguments2();
@@ -4014,7 +3972,7 @@
     return t;
   }
 
-  Type parseCFunctionPointerType(Type type, ref Token* ident, bool optionalParamList)
+  Type parseCFunctionPointerType(Type type, ref Identifier* ident, bool optionalParamList)
   {
     assert(token.type == T.LParen);
     assert(type !is null);
@@ -4029,7 +3987,7 @@
     else if (token.type == T.Identifier)
     {
       // The identifier of the function pointer and the declaration.
-      ident = token;
+      ident = token.ident;
       nT();
       type = parseDeclaratorSuffix(type);
     }
@@ -4045,7 +4003,7 @@
     return type;
   }
 
-  Type parseDeclarator(ref Token* ident, bool identOptional = false)
+  Type parseDeclarator(ref Identifier* ident, bool identOptional = false)
   {
     auto t = parseType();
 
@@ -4055,13 +4013,13 @@
     }
     else if (token.type == T.Identifier)
     {
-      ident = token;
+      ident = token.ident;
       nT();
       t = parseDeclaratorSuffix(t);
     }
 
     if (ident is null && !identOptional)
-      expected(T.Identifier);
+      error(token, MSG.ExpectedDeclaratorIdentifier, token.srcText);
 
     return t;
   }
@@ -4124,24 +4082,33 @@
       return set(params, begin);
     }
 
+  Loop:
     while (1)
     {
       auto paramBegin = token;
-      Token* stcTok;
       StorageClass stc, tmp;
+      Type type;
+      Identifier* ident;
+      Expression defValue;
+
+      void pushParameter()
+      {
+        params ~= set(new Parameter(stc, type, ident, defValue), paramBegin);
+      }
 
       if (token.type == T.Ellipses)
       {
         nT();
-        params ~= set(new Parameter(null, null, null, null), paramBegin);
-        break; // Exit loop.
+        stc = StorageClass.Variadic;
+        pushParameter(); // type, ident and defValue will be null.
+        break Loop;
       }
 
     Lstc_loop:
       switch (token.type)
       {
-      version(D2)
-      {
+    version(D2)
+    {
       case T.Invariant: // D2.0
         if (peekNext() == T.LParen)
           goto default;
@@ -4161,6 +4128,7 @@
       case T.Static: // D2.0
         tmp = StorageClass.Static;
         goto Lcommon;
+    }
       case T.In:
         tmp = StorageClass.In;
         goto Lcommon;
@@ -4174,53 +4142,36 @@
         tmp = StorageClass.Lazy;
         goto Lcommon;
       Lcommon:
+        // Check for redundancy.
         if (stc & tmp)
           error(MID.RedundantStorageClass, token.srcText);
         else
           stc |= tmp;
         nT();
+      version(D2)
         goto Lstc_loop;
-      }
-      else // else body of version(D2)
-      {
-      case T.In, T.Out, T.Inout, T.Ref, T.Lazy:
-        stcTok = token;
-        nT();
-        goto default;
-      }
+      else
+        goto default; // In D1.0 only one stc per parameter is allowed.
       default:
-      version(D2)
-      {
-        if (stc != StorageClass.None)
-          stcTok = begin;
-      }
-        Token* ident;
-        auto type = parseDeclarator(ident, true);
-
-        Expression assignExpr;
+        type = parseDeclarator(ident, true);
+
         if (token.type == T.Assign)
-        {
-          nT();
-          assignExpr = parseAssignExpression();
-        }
+          nT(), (defValue = parseAssignExpression());
 
         if (token.type == T.Ellipses)
         {
-          auto p = set(new Parameter(stcTok, type, ident, assignExpr), paramBegin);
-          p.stc |= StorageClass.Variadic;
-          params ~= p;
           nT();
-          break; // Exit loop.
+          stc |= StorageClass.Variadic;
+          pushParameter();
+          break Loop;
         }
 
-        params ~= set(new Parameter(stcTok, type, ident, assignExpr), paramBegin);
+        pushParameter();
 
         if (token.type != T.Comma)
-          break; // Exit loop.
+          break Loop;
         nT();
-        continue;
       }
-      break; // Exit loop.
     }
     require(T.RParen);
     return set(params, begin);
@@ -4231,7 +4182,7 @@
     TemplateArguments targs;
     require(T.LParen);
     if (token.type != T.RParen)
-     targs = parseTemplateArguments_();
+      targs = parseTemplateArguments_();
     require(T.RParen);
     return targs;
   }
@@ -4246,7 +4197,7 @@
     if (token.type != T.RParen)
       targs = parseTemplateArguments_();
     else
-      error(MID.ExpectedButFound, "Type/Expression", ")");
+      error(token, MSG.ExpectedTypeOrExpression);
     require(T.RParen);
     return targs;
   }
@@ -4305,7 +4256,7 @@
     if (token.type != T.RParen)
       tparams = parseTemplateParameterList_();
     else
-      error(MID.ExpectedButFound, "Type/Expression", ")");
+      error(token, MSG.ExpectedTemplateParameters);
     return tparams;
   }
 } // version(D2)
@@ -4319,7 +4270,7 @@
     {
       auto paramBegin = token;
       TemplateParameter tp;
-      Token* ident;
+      Identifier* ident;
       Type specType, defType;
 
       void parseSpecAndOrDefaultType()
@@ -4344,12 +4295,12 @@
         // TemplateAliasParameter:
         //         alias Identifier
         nT(); // Skip alias keyword.
-        ident = requireId();
+        ident = requireIdentifier(MSG.ExpectedAliasTemplateParam);
         parseSpecAndOrDefaultType();
         tp = new TemplateAliasParameter(ident, specType, defType);
         break;
       case T.Identifier:
-        ident = token;
+        ident = token.ident;
         switch (peekNext())
         {
         case T.Ellipses:
@@ -4381,7 +4332,7 @@
         // TemplateThisParameter
         //         this TemplateTypeParameter
         nT(); // Skip 'this' keyword.
-        ident = requireId();
+        ident = requireIdentifier(MSG.ExpectedNameForThisTempParam);
         parseSpecAndOrDefaultType();
         tp = new TemplateThisParameter(ident, specType, defType);
         break;
@@ -4438,6 +4389,14 @@
     require(tok);
   }
 
+  Identifier* optionalIdentifier()
+  {
+    Identifier* id;
+    if (token.type == T.Identifier)
+      (id = token.ident), nT();
+    return id;
+  }
+
   Identifier* requireIdentifier()
   {
     Identifier* id;
@@ -4485,6 +4444,16 @@
     return null;
   }
 
+  Token* requireIdToken(char[] errorMsg)
+  {
+    Token* idtok;
+    if (token.type == T.Identifier)
+      (idtok = token), nT();
+    else
+      error(token, errorMsg, token.srcText);
+    return idtok;
+  }
+
   /// Reports an error that has no message ID yet.
   void error(Token* token, char[] formatMsg, ...)
   {
@@ -4507,4 +4476,40 @@
     auto msg = Format(_arguments, _argptr, formatMsg);
     errors ~= new Information(InfoType.Parser, mid, location, msg);
   }
+
+  /// Collection of error messages with no MID yet.
+  private struct MSG
+  {
+  static:
+    auto ExpectedIdAfterTypeDot = "expected identifier after '(Type).', not '{}'";
+    auto ExpectedModuleIdentifier = "expected module identifier, not '{}'";
+    auto IllegalDeclaration = "illegal Declaration found: {}";
+    auto ExpectedFunctionName = "expected function name, not '{}'";
+    auto ExpectedVariableName = "expected variable name, not '{}'";
+    auto ExpectedFunctionBody = "expected function body, not '{}'";
+    auto RedundantLinkageType = "redundant linkage type: ";
+    auto ExpectedPragmaIdentifier = "expected pragma identifier, not '{}'";
+    auto ExpectedAliasModuleName = "expected alias module name, not '{}'";
+    auto ExpectedAliasImportName = "expected alias name, not '{}'";
+    auto ExpectedImportName = "expected an identifier, not '{}'";
+    auto ExpectedEnumMember = "expected enum member, not '{}'";
+    auto ExpectedEnumBody = "expected enum body, not '{}'";
+    auto ExpectedClassName = "expected class name, not '{}'";
+    auto ExpectedClassBody = "expected class body, not '{}'";
+    auto ExpectedInterfaceName = "expected interface name, not '{}'";
+    auto ExpectedInterfaceBody = "expected interface body, not '{}'";
+    auto ExpectedTemplateName = "expected template name, not '{}'";
+    auto ExpectedAnIdentifier = "expected an identifier, not '{}'";
+    auto IllegalStatement = "illegal Statement found: ";
+    auto ExpectedNonEmptyStatement = "didn't expect ';', use { } instead";
+    auto ExpectedScopeIdentifier = "expected 'exit', 'success' or 'failure', not '{}'";
+    auto InvalidScopeIdentifier = "'exit', 'success', 'failure' are valid scope identifiers, but not '{}';";
+    auto ExpectedIntegerAfterAlign = "expected an integer after align, not '{}'";
+    auto IllegalAsmInstructino = "illegal AsmInstruction found: ";
+    auto ExpectedDeclaratorIdentifier = "expected declarator identifier, not '{}'";
+    auto ExpectedTemplateParameters = "expected one or more template parameters not ')'";
+    auto ExpectedTypeOrExpression = "expected a type or and expression not ')'";
+    auto ExpectedAliasTemplateParam = "expected name for alias template parameter, not '{}'";
+    auto ExpectedNameForThisTempParam = "expected name for 'this' template parameter, not '{}'";
+  }
 }
--- a/trunk/src/dil/Settings.d	Tue Dec 11 17:02:42 2007 +0100
+++ b/trunk/src/dil/Settings.d	Wed Dec 12 02:25:42 2007 +0100
@@ -33,7 +33,7 @@
       auto v = Cast!(VariableDeclaration)(decl);
       if (v is null)
         continue;
-      auto vname = v.idents[0].srcText;
+      auto vname = v.idents[0].str;
       if (vname == "langfile")
       {
         auto e = v.values[0];
@@ -76,7 +76,7 @@
       auto v = Cast!(VariableDeclaration)(decl);
       if (v is null)
         continue;
-      if (v.idents[0].srcText == "messages")
+      if (v.idents[0].str == "messages")
       {
         auto e = v.values[0];
         if (!e)
@@ -92,7 +92,7 @@
         else
           throw new Exception("messages variable is set to "~e.classinfo.name~" instead of an ArrayInitializer.");
       }
-      else if(v.idents[0].srcText == "lang_code")
+      else if(v.idents[0].str == "lang_code")
       {
         auto e = v.values[0];
         if (!e)
--- a/trunk/src/dil/Statements.d	Tue Dec 11 17:02:42 2007 +0100
+++ b/trunk/src/dil/Statements.d	Wed Dec 12 02:25:42 2007 +0100
@@ -8,6 +8,7 @@
 import dil.Declarations;
 import dil.Types;
 import dil.Token;
+import dil.Identifier;
 
 abstract class Statement : Node
 {
@@ -49,7 +50,7 @@
 class FunctionBody : Node
 {
   Statement funcBody, inBody, outBody;
-  Token* outIdent;
+  Identifier* outIdent;
   this()
   {
     super(NodeCategory.Other);
@@ -77,9 +78,9 @@
 
 class LabeledStatement : Statement
 {
-  Token* label;
+  Identifier* label;
   Statement s;
-  this(Token* label, Statement s)
+  this(Identifier* label, Statement s)
   {
     mixin(set_kind);
     addChild(s);
@@ -272,8 +273,8 @@
 
 class ContinueStatement : Statement
 {
-  Token* ident;
-  this(Token* ident)
+  Identifier* ident;
+  this(Identifier* ident)
   {
     mixin(set_kind);
     this.ident = ident;
@@ -282,8 +283,8 @@
 
 class BreakStatement : Statement
 {
-  Token* ident;
-  this(Token* ident)
+  Identifier* ident;
+  this(Identifier* ident)
   {
     mixin(set_kind);
     this.ident = ident;
@@ -303,9 +304,9 @@
 
 class GotoStatement : Statement
 {
-  Token* ident;
+  Identifier* ident;
   Expression caseExpr;
-  this(Token* ident, Expression caseExpr)
+  this(Identifier* ident, Expression caseExpr)
   {
     mixin(set_kind);
     addOptChild(caseExpr);
@@ -389,9 +390,9 @@
 
 class ScopeGuardStatement : Statement
 {
-  Token* condition;
+  Identifier* condition;
   Statement scopeBody;
-  this(Token* condition, Statement scopeBody)
+  this(Identifier* condition, Statement scopeBody)
   {
     mixin(set_kind);
     addChild(scopeBody);
@@ -435,9 +436,9 @@
 
 class AsmInstruction : Statement
 {
-  Token* ident;
+  Identifier* ident;
   Expression[] operands;
-  this(Token* ident, Expression[] operands)
+  this(Identifier* ident, Expression[] operands)
   {
     mixin(set_kind);
     addOptChildren(operands);
@@ -448,8 +449,8 @@
 
 class AsmAlignStatement : Statement
 {
-  Token* number;
-  this(Token* number)
+  int number;
+  this(int number)
   {
     mixin(set_kind);
     this.number = number;
@@ -466,10 +467,10 @@
 
 class PragmaStatement : Statement
 {
-  Token* ident;
+  Identifier* ident;
   Expression[] args;
   Statement pragmaBody;
-  this(Token* ident, Expression[] args, Statement pragmaBody)
+  this(Identifier* ident, Expression[] args, Statement pragmaBody)
   {
     mixin(set_kind);
     addOptChildren(args);
@@ -484,8 +485,8 @@
 class MixinStatement : Statement
 {
   Expression[] templateIdents;
-  Token* mixinIdent;
-  this(Expression[] templateIdents, Token* mixinIdent)
+  Identifier* mixinIdent;
+  this(Expression[] templateIdents, Identifier* mixinIdent)
   {
     mixin(set_kind);
     addChildren(templateIdents);
@@ -523,32 +524,34 @@
   }
 }
 
-class DebugStatement : Statement
+abstract class ConditionalCompilationStatement : Statement
 {
   Token* cond;
-  Statement debugBody, elseBody;
-  this(Token* cond, Statement debugBody, Statement elseBody)
+  Statement mainBody, elseBody;
+  this(Token* cond, Statement mainBody, Statement elseBody)
   {
-    mixin(set_kind);
-    addChild(debugBody);
+    addChild(mainBody);
     addOptChild(elseBody);
     this.cond = cond;
-    this.debugBody = debugBody;
+    this.mainBody = mainBody;
     this.elseBody = elseBody;
   }
 }
 
-class VersionStatement : Statement
+class DebugStatement : ConditionalCompilationStatement
 {
-  Token* cond;
-  Statement versionBody, elseBody;
+  this(Token* cond, Statement debugBody, Statement elseBody)
+  {
+    super(cond, debugBody, elseBody);
+    mixin(set_kind);
+  }
+}
+
+class VersionStatement : ConditionalCompilationStatement
+{
   this(Token* cond, Statement versionBody, Statement elseBody)
   {
+    super(cond, versionBody, elseBody);
     mixin(set_kind);
-    addChild(versionBody);
-    addOptChild(elseBody);
-    this.cond = cond;
-    this.versionBody = versionBody;
-    this.elseBody = elseBody;
   }
 }
--- a/trunk/src/dil/Types.d	Tue Dec 11 17:02:42 2007 +0100
+++ b/trunk/src/dil/Types.d	Wed Dec 12 02:25:42 2007 +0100
@@ -7,16 +7,17 @@
 import dil.Token;
 import dil.Expressions;
 import dil.Enums;
+import dil.Identifier;
 
 class Parameter : Node
 {
   StorageClass stc;
   Token* stcTok;
   Type type;
-  Token* ident;
+  Identifier* ident;
   Expression assignExpr;
 
-  this(Token* stcTok, Type type, Token* ident, Expression assignExpr)
+  this(StorageClass stc, Type type, Identifier* ident, Expression assignExpr)
   {
     super(NodeCategory.Other);
     mixin(set_kind);
@@ -24,39 +25,23 @@
     addOptChild(type);
     addOptChild(assignExpr);
 
-    StorageClass stc;
-    if (stcTok !is null)
-    {
-      // NB: In D 2.0 StorageClass.In means final/scope/const
-      switch (stcTok.type)
-      {
-      // TODO: D 2.0 invariant/const/final/scope
-      case TOK.In:   stc = StorageClass.In;   break;
-      case TOK.Out:  stc = StorageClass.Out;  break;
-      case TOK.Inout:
-      case TOK.Ref:  stc = StorageClass.Ref;  break;
-      case TOK.Lazy: stc = StorageClass.Lazy; break;
-      case TOK.Ellipses:
-        stc = StorageClass.Variadic;
-      default:
-      }
-    }
-
     this.stc = stc;
-    this.stcTok = stcTok;
     this.type = type;
     this.ident = ident;
     this.assignExpr = assignExpr;
   }
 
+  /// func(...) or func(int[] values ...)
   bool isVariadic()
   {
     return !!(stc & StorageClass.Variadic);
   }
 
+  /// func(...)
   bool isOnlyVariadic()
   {
-    return stc == StorageClass.Variadic;
+    return stc == StorageClass.Variadic &&
+           type is null && ident is null;
   }
 }
 
@@ -101,18 +86,20 @@
 
 abstract class TemplateParameter : Node
 {
-  this()
+  Identifier* ident;
+  this(Identifier* ident)
   {
     super(NodeCategory.Other);
+    this.ident = ident;
   }
 }
 
 class TemplateAliasParameter : TemplateParameter
 {
-  Token* ident;
   Type specType, defType;
-  this(Token* ident, Type specType, Type defType)
+  this(Identifier* ident, Type specType, Type defType)
   {
+    super(ident);
     mixin(set_kind);
     addOptChild(specType);
     addOptChild(defType);
@@ -124,10 +111,10 @@
 
 class TemplateTypeParameter : TemplateParameter
 {
-  Token* ident;
   Type specType, defType;
-  this(Token* ident, Type specType, Type defType)
+  this(Identifier* ident, Type specType, Type defType)
   {
+    super(ident);
     mixin(set_kind);
     addOptChild(specType);
     addOptChild(defType);
@@ -141,10 +128,10 @@
 {
 class TemplateThisParameter : TemplateParameter
 {
-  Token* ident;
   Type specType, defType;
-  this(Token* ident, Type specType, Type defType)
+  this(Identifier* ident, Type specType, Type defType)
   {
+    super(ident);
     mixin(set_kind);
     addOptChild(specType);
     addOptChild(defType);
@@ -158,10 +145,10 @@
 class TemplateValueParameter : TemplateParameter
 {
   Type valueType;
-  Token* ident;
   Expression specValue, defValue;
-  this(Type valueType, Token* ident, Expression specValue, Expression defValue)
+  this(Type valueType, Identifier* ident, Expression specValue, Expression defValue)
   {
+    super(ident);
     mixin(set_kind);
     addChild(valueType);
     addOptChild(specValue);
@@ -175,9 +162,9 @@
 
 class TemplateTupleParameter : TemplateParameter
 {
-  Token* ident;
-  this(Token* ident)
+  this(Identifier* ident)
   {
+    super(ident);
     mixin(set_kind);
     this.ident = ident;
   }
@@ -307,8 +294,8 @@
 
 class IdentifierType : Type
 {
-  Token* ident;
-  this(Token* ident)
+  Identifier* ident;
+  this(Identifier* ident)
   {
     super(TID.Identifier);
     mixin(set_kind);
@@ -349,9 +336,9 @@
 
 class TemplateInstanceType : Type
 {
-  Token* ident;
+  Identifier* ident;
   TemplateArguments targs;
-  this(Token* ident, TemplateArguments targs)
+  this(Identifier* ident, TemplateArguments targs)
   {
     super(TID.TemplateInstance);
     mixin(set_kind);