changeset 325:540ec3753263

- Moved some source files to src/dil/.
author aziz
date Tue, 21 Aug 2007 16:28:05 +0000
parents c1820da1ca53
children 4a7359b88c11
files trunk/src/Declarations.d trunk/src/Expressions.d trunk/src/HtmlEntities.d trunk/src/Identifier.d trunk/src/Information.d trunk/src/Keywords.d trunk/src/Lexer.d trunk/src/Messages.d trunk/src/Parser.d trunk/src/Settings.d trunk/src/Statements.d trunk/src/SyntaxTree.d trunk/src/Token.d trunk/src/Types.d trunk/src/dil/Declarations.d trunk/src/dil/Expressions.d trunk/src/dil/HtmlEntities.d trunk/src/dil/Identifier.d trunk/src/dil/Information.d trunk/src/dil/Keywords.d trunk/src/dil/Lexer.d trunk/src/dil/Messages.d trunk/src/dil/Parser.d trunk/src/dil/Settings.d trunk/src/dil/Statements.d trunk/src/dil/SyntaxTree.d trunk/src/dil/Token.d trunk/src/dil/Types.d
diffstat 28 files changed, 9639 insertions(+), 9639 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/src/Declarations.d	Tue Aug 21 16:18:02 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,526 +0,0 @@
-/++
-  Author: Aziz Köksal
-  License: GPL3
-+/
-module Declarations;
-import SyntaxTree;
-import Expressions;
-import Types;
-import Statements;
-import Token;
-
-abstract class Declaration : Node
-{
-  bool hasBody;
-  this(bool hasBody)
-  {
-    super(NodeCategory.Declaration);
-    this.hasBody = hasBody;
-  }
-}
-
-class Declarations : Declaration
-{
-  this()
-  {
-    super(true);
-    mixin(set_kind);
-  }
-
-  void opCatAssign(Declaration d)
-  {
-    this.children ~= d;
-  }
-
-  void opCatAssign(Declarations ds)
-  {
-    this.children ~= ds.children;
-  }
-}
-
-class EmptyDeclaration : Declaration
-{
-  this()
-  {
-    super(false);
-    mixin(set_kind);
-  }
-}
-
-class IllegalDeclaration : Declaration
-{
-  Token* token;
-  this(Token* token)
-  {
-    super(false);
-    mixin(set_kind);
-    this.token = token;
-  }
-}
-
-alias Token*[] ModuleName; // Identifier(.Identifier)*
-
-class ModuleDeclaration : Declaration
-{
-  ModuleName moduleName; // module name sits at end of array
-  this(ModuleName moduleName)
-  {
-    super(false);
-    mixin(set_kind);
-    this.moduleName = moduleName;
-  }
-}
-
-class ImportDeclaration : Declaration
-{
-  ModuleName[] moduleNames;
-  Token*[] moduleAliases;
-  Token*[] bindNames;
-  Token*[] bindAliases;
-  this(ModuleName[] moduleNames, Token*[] moduleAliases, Token*[] bindNames, Token*[] bindAliases)
-  {
-    super(false);
-    mixin(set_kind);
-    this.moduleNames = moduleNames;
-    this.moduleAliases = moduleAliases;
-    this.bindNames = bindNames;
-    this.bindAliases = bindAliases;
-  }
-}
-
-class AliasDeclaration : Declaration
-{
-  Declaration decl;
-  this(Declaration decl)
-  {
-    super(false);
-    mixin(set_kind);
-    this.children = [decl];
-    this.decl = decl;
-  }
-}
-
-class TypedefDeclaration : Declaration
-{
-  Declaration decl;
-  this(Declaration decl)
-  {
-    super(false);
-    mixin(set_kind);
-    this.children = [decl];
-    this.decl = decl;
-  }
-}
-
-class EnumDeclaration : Declaration
-{
-  Token* name;
-  Type baseType;
-  Token*[] members;
-  Expression[] values;
-  this(Token* name, Type baseType, Token*[] members, Expression[] values, bool hasBody)
-  {
-    super(hasBody);
-    mixin(set_kind);
-    if (baseType)
-      this.children = [baseType];
-    foreach(value; values)
-      if (value)
-        this.children ~= value;
-    this.name = name;
-    this.baseType = baseType;
-    this.members = members;
-    this.values = values;
-  }
-}
-
-class ClassDeclaration : Declaration
-{
-  Token* name;
-  TemplateParameters tparams;
-  BaseClass[] bases;
-  Declarations decls;
-  this(Token* name, TemplateParameters tparams, BaseClass[] bases, Declarations decls, bool hasBody)
-  {
-    super(hasBody);
-    mixin(set_kind);
-    if (tparams)
-      this.children = [tparams];
-    if (bases.length)
-      this.children ~= bases;
-    this.children ~= decls;
-
-    this.name = name;
-    this.tparams = tparams;
-    this.bases = bases;
-    this.decls = decls;
-  }
-}
-
-class InterfaceDeclaration : Declaration
-{
-  Token* name;
-  TemplateParameters tparams;
-  BaseClass[] bases;
-  Declarations decls;
-  this(Token* name, TemplateParameters tparams, BaseClass[] bases, Declarations decls, bool hasBody)
-  {
-    super(hasBody);
-    mixin(set_kind);
-    if (tparams)
-      this.children = [tparams];
-    if (bases.length)
-      this.children ~= bases;
-    this.children ~= decls;
-
-    this.name = name;
-    this.tparams = tparams;
-    this.bases = bases;
-    this.decls = decls;
-  }
-}
-
-class StructDeclaration : Declaration
-{
-  Token* name;
-  TemplateParameters tparams;
-  Declarations decls;
-  this(Token* name, TemplateParameters tparams, Declarations decls, bool hasBody)
-  {
-    super(hasBody);
-    mixin(set_kind);
-    if (tparams)
-      this.children = [tparams];
-    this.children ~= decls;
-
-    this.name = name;
-    this.tparams = tparams;
-    this.decls = decls;
-  }
-}
-
-class UnionDeclaration : Declaration
-{
-  Token* name;
-  TemplateParameters tparams;
-  Declarations decls;
-  this(Token* name, TemplateParameters tparams, Declarations decls, bool hasBody)
-  {
-    super(hasBody);
-    mixin(set_kind);
-    if (tparams)
-      this.children = [tparams];
-    this.children ~= decls;
-
-    this.name = name;
-    this.tparams = tparams;
-    this.decls = decls;
-  }
-}
-
-class ConstructorDeclaration : Declaration
-{
-  Parameters parameters;
-  FunctionBody funcBody;
-  this(Parameters parameters, FunctionBody funcBody)
-  {
-    super(true);
-    mixin(set_kind);
-    this.children = [cast(Node)parameters, funcBody];
-    this.parameters = parameters;
-    this.funcBody = funcBody;
-  }
-}
-
-class StaticConstructorDeclaration : Declaration
-{
-  FunctionBody funcBody;
-  this(FunctionBody funcBody)
-  {
-    super(true);
-    mixin(set_kind);
-    this.children = [funcBody];
-    this.funcBody = funcBody;
-  }
-}
-
-class DestructorDeclaration : Declaration
-{
-  FunctionBody funcBody;
-  this(FunctionBody funcBody)
-  {
-    super(true);
-    mixin(set_kind);
-    this.children = [funcBody];
-    this.funcBody = funcBody;
-  }
-}
-
-class StaticDestructorDeclaration : Declaration
-{
-  FunctionBody funcBody;
-  this(FunctionBody funcBody)
-  {
-    super(true);
-    mixin(set_kind);
-    this.children = [funcBody];
-    this.funcBody = funcBody;
-  }
-}
-
-class FunctionDeclaration : Declaration
-{
-  Type returnType;
-  Token* funcName;
-  TemplateParameters tparams;
-  Parameters params;
-  FunctionBody funcBody;
-  this(Type returnType, Token* funcName, TemplateParameters tparams, Parameters params, FunctionBody funcBody)
-  {
-    assert(returnType !is null);
-    super(funcBody.funcBody !is null);
-    mixin(set_kind);
-    this.children = [returnType];
-    if (tparams)
-      this.children ~= tparams;
-    this.children ~= [cast(Node)params, funcBody];
-    this.returnType = returnType;
-    this.funcName = funcName;
-    this.tparams = tparams;
-    this.params = params;
-    this.funcBody = funcBody;
-  }
-}
-
-class VariableDeclaration : Declaration
-{
-  Type type;
-  Token*[] idents;
-  Expression[] values;
-  this(Type type, Token*[] idents, Expression[] values)
-  {
-    super(false);
-    mixin(set_kind);
-    if (type)
-      this.children = [type];
-    foreach(value; values)
-      if (value)
-        this.children ~= value;
-    this.type = type;
-    this.idents = idents;
-    this.values = values;
-  }
-}
-
-class InvariantDeclaration : Declaration
-{
-  FunctionBody funcBody;
-  this(FunctionBody funcBody)
-  {
-    super(true);
-    mixin(set_kind);
-    this.children = [funcBody];
-    this.funcBody = funcBody;
-  }
-}
-
-class UnittestDeclaration : Declaration
-{
-  FunctionBody funcBody;
-  this(FunctionBody funcBody)
-  {
-    super(true);
-    mixin(set_kind);
-    this.children = [funcBody];
-    this.funcBody = funcBody;
-  }
-}
-
-class DebugDeclaration : Declaration
-{
-  Token* spec;
-  Token* cond;
-  Declaration decls, elseDecls;
-
-  this(Token* spec, Token* cond, Declaration decls, Declaration elseDecls)
-  {
-    super(true /+decls.length != 0+/);
-    mixin(set_kind);
-    if (decls)
-      this.children = [decls];
-    if (elseDecls)
-      this.children ~= elseDecls;
-    this.spec = spec;
-    this.cond = cond;
-    this.decls = decls;
-    this.elseDecls = elseDecls;
-  }
-}
-
-class VersionDeclaration : Declaration
-{
-  Token* spec;
-  Token* cond;
-  Declaration decls, elseDecls;
-
-  this(Token* spec, Token* cond, Declaration decls, Declaration elseDecls)
-  {
-    super(true /+decls.length != 0+/);
-    mixin(set_kind);
-    if (decls)
-      this.children = [decls];
-    if (elseDecls)
-      this.children ~= elseDecls;
-    this.spec = spec;
-    this.cond = cond;
-    this.decls = decls;
-    this.elseDecls = elseDecls;
-  }
-}
-
-class StaticIfDeclaration : Declaration
-{
-  Expression condition;
-  Declaration ifDecls, elseDecls;
-  this(Expression condition, Declaration ifDecls, Declaration elseDecls)
-  {
-    super(true);
-    mixin(set_kind);
-    this.children = [cast(Node)condition, ifDecls, elseDecls];
-    this.condition = condition;
-    this.ifDecls = ifDecls;
-    this.elseDecls = elseDecls;
-  }
-}
-
-class StaticAssertDeclaration : Declaration
-{
-  Expression condition, message;
-  this(Expression condition, Expression message)
-  {
-    super(true);
-    mixin(set_kind);
-    this.children = [condition];
-    if (message)
-      this.children ~= message;
-    this.condition = condition;
-    this.message = message;
-  }
-}
-
-class TemplateDeclaration : Declaration
-{
-  Token* name;
-  TemplateParameters tparams;
-  Declarations decls;
-  this(Token* name, TemplateParameters tparams, Declarations decls)
-  {
-    super(true);
-    mixin(set_kind);
-    this.children = [cast(Node)tparams, decls];
-    this.name = name;
-    this.tparams = tparams;
-    this.decls = decls;
-  }
-}
-
-class NewDeclaration : Declaration
-{
-  Parameters parameters;
-  FunctionBody funcBody;
-  this(Parameters parameters, FunctionBody funcBody)
-  {
-    super(true);
-    mixin(set_kind);
-    this.children = [cast(Node)parameters, funcBody];
-    this.parameters = parameters;
-    this.funcBody = funcBody;
-  }
-}
-
-class DeleteDeclaration : Declaration
-{
-  Parameters parameters;
-  FunctionBody funcBody;
-  this(Parameters parameters, FunctionBody funcBody)
-  {
-    super(true);
-    mixin(set_kind);
-    this.children = [cast(Node)parameters, funcBody];
-    this.parameters = parameters;
-    this.funcBody = funcBody;
-  }
-}
-
-class AttributeDeclaration : Declaration
-{
-  TOK attribute;
-  Declaration decls;
-  this(TOK attribute, Declaration decls)
-  {
-    super(true);
-    mixin(set_kind);
-    this.children = [decls];
-    this.attribute = attribute;
-    this.decls = decls;
-  }
-}
-
-class ExternDeclaration : AttributeDeclaration
-{
-  Linkage linkage;
-  this(Linkage linkage, Declaration decls)
-  {
-    super(TOK.Extern, decls);
-    mixin(set_kind);
-    this.linkage = linkage;
-  }
-}
-
-class AlignDeclaration : AttributeDeclaration
-{
-  int size;
-  this(int size, Declaration decls)
-  {
-    super(TOK.Align, decls);
-    mixin(set_kind);
-    this.size = size;
-  }
-}
-
-class PragmaDeclaration : AttributeDeclaration
-{
-  Token* ident;
-  Expression[] args;
-  this(Token* ident, Expression[] args, Declaration decls)
-  {
-    super(TOK.Pragma, decls);
-    mixin(set_kind);
-    if (args.length)
-      this.children ~= args;
-    this.ident = ident;
-    this.args = args;
-  }
-}
-
-class MixinDeclaration : Declaration
-{
-  Expression[] templateIdents;
-  Token* mixinIdent;
-  Expression argument; // mixin ( AssignExpression )
-  this(Expression[] templateIdents, Token* mixinIdent)
-  {
-    super(false);
-    mixin(set_kind);
-    this.children = templateIdents;
-    this.templateIdents = templateIdents;
-    this.mixinIdent = mixinIdent;
-  }
-  this(Expression argument)
-  {
-    super(false);
-    mixin(set_kind);
-    this.children = [argument];
-    this.argument = argument;
-  }
-}
--- a/trunk/src/Expressions.d	Tue Aug 21 16:18:02 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,988 +0,0 @@
-/++
-  Author: Aziz Köksal
-  License: GPL3
-+/
-module Expressions;
-import SyntaxTree;
-import Token;
-import Types;
-import Declarations;
-import Statements;
-
-abstract class Expression : Node
-{
-  this()
-  {
-    super(NodeCategory.Expression);
-  }
-}
-
-class EmptyExpression : Expression
-{
-  this()
-  {
-    mixin(set_kind);
-  }
-}
-
-abstract class BinaryExpression : Expression
-{
-  Expression left, right;
-  Token* tok;
-  this(Expression left, Expression right, Token* tok)
-  {
-    this.children = [left, right];
-    this.left = left;
-    this.right = right;
-    this.tok = tok;
-  }
-}
-
-class CondExpression : BinaryExpression
-{
-  Expression condition;
-  this(Expression condition, Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-    this.children ~= [condition];
-    this.condition = condition;
-  }
-}
-
-class CommaExpression : BinaryExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class OrOrExpression : BinaryExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class AndAndExpression : BinaryExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class OrExpression : BinaryExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class XorExpression : BinaryExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class AndExpression : BinaryExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-abstract class CmpExpression : BinaryExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-  }
-}
-
-class EqualExpression : CmpExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class IdentityExpression : CmpExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class RelExpression : CmpExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class InExpression : BinaryExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class LShiftExpression : BinaryExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class RShiftExpression : BinaryExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class URShiftExpression : BinaryExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class PlusExpression : BinaryExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class MinusExpression : BinaryExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class CatExpression : BinaryExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class MulExpression : BinaryExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class DivExpression : BinaryExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class ModExpression : BinaryExpression
-{
-  this(Expression left, Expression right, Token* tok)
-  {
-    super(left, right, tok);
-    mixin(set_kind);
-  }
-}
-
-class AssignExpression : BinaryExpression
-{
-  this(Expression left, Expression right)
-  {
-    super(left, right, null);
-    mixin(set_kind);
-  }
-}
-class LShiftAssignExpression : BinaryExpression
-{
-  this(Expression left, Expression right)
-  {
-    super(left, right, null);
-    mixin(set_kind);
-  }
-}
-class RShiftAssignExpression : BinaryExpression
-{
-  this(Expression left, Expression right)
-  {
-    super(left, right, null);
-    mixin(set_kind);
-  }
-}
-class URShiftAssignExpression : BinaryExpression
-{
-  this(Expression left, Expression right)
-  {
-    super(left, right, null);
-    mixin(set_kind);
-  }
-}
-class OrAssignExpression : BinaryExpression
-{
-  this(Expression left, Expression right)
-  {
-    super(left, right, null);
-    mixin(set_kind);
-  }
-}
-class AndAssignExpression : BinaryExpression
-{
-  this(Expression left, Expression right)
-  {
-    super(left, right, null);
-    mixin(set_kind);
-  }
-}
-class PlusAssignExpression : BinaryExpression
-{
-  this(Expression left, Expression right)
-  {
-    super(left, right, null);
-    mixin(set_kind);
-  }
-}
-class MinusAssignExpression : BinaryExpression
-{
-  this(Expression left, Expression right)
-  {
-    super(left, right, null);
-    mixin(set_kind);
-  }
-}
-class DivAssignExpression : BinaryExpression
-{
-  this(Expression left, Expression right)
-  {
-    super(left, right, null);
-    mixin(set_kind);
-  }
-}
-class MulAssignExpression : BinaryExpression
-{
-  this(Expression left, Expression right)
-  {
-    super(left, right, null);
-    mixin(set_kind);
-  }
-}
-class ModAssignExpression : BinaryExpression
-{
-  this(Expression left, Expression right)
-  {
-    super(left, right, null);
-    mixin(set_kind);
-  }
-}
-class XorAssignExpression : BinaryExpression
-{
-  this(Expression left, Expression right)
-  {
-    super(left, right, null);
-    mixin(set_kind);
-  }
-}
-class CatAssignExpression : BinaryExpression
-{
-  this(Expression left, Expression right)
-  {
-    super(left, right, null);
-    mixin(set_kind);
-  }
-}
-
-abstract class UnaryExpression : Expression
-{
-  Expression e;
-  this(Expression e)
-  {
-    this.children ~= e;
-    this.e = e;
-  }
-}
-
-class AddressExpression : UnaryExpression
-{
-  this(Expression e)
-  {
-    super(e);
-    mixin(set_kind);
-  }
-}
-
-class PreIncrExpression : UnaryExpression
-{
-  this(Expression e)
-  {
-    super(e);
-    mixin(set_kind);
-  }
-}
-
-class PreDecrExpression : UnaryExpression
-{
-  this(Expression e)
-  {
-    super(e);
-    mixin(set_kind);
-  }
-}
-
-class PostIncrExpression : UnaryExpression
-{
-  this(Expression e)
-  {
-    super(e);
-    mixin(set_kind);
-  }
-}
-
-class PostDecrExpression : UnaryExpression
-{
-  this(Expression e)
-  {
-    super(e);
-    mixin(set_kind);
-  }
-}
-
-class DerefExpression : UnaryExpression
-{
-  this(Expression e)
-  {
-    super(e);
-    mixin(set_kind);
-  }
-}
-
-class SignExpression : UnaryExpression
-{
-  this(Expression e)
-  {
-    super(e);
-    mixin(set_kind);
-  }
-}
-
-class NotExpression : UnaryExpression
-{
-  this(Expression e)
-  {
-    super(e);
-    mixin(set_kind);
-  }
-}
-
-class CompExpression : UnaryExpression
-{
-  this(Expression e)
-  {
-    super(e);
-    mixin(set_kind);
-  }
-}
-/+
-class DotIdExpression : UnaryExpression
-{
-  string ident;
-  this(Expression e, string ident)
-  {
-    super(e);
-    this.ident = ident;
-  }
-}
-+/
-/+
-class DotTemplateInstanceExpression : UnaryExpression
-{
-  string ident;
-  TemplateArguments targs;
-  this(Expression e, string ident, TemplateArguments targs)
-  {
-    super(e);
-    this.ident = ident;
-    this.targs = targs;
-  }
-}
-+/
-class PostDotListExpression : UnaryExpression
-{
-  DotListExpression dotList;
-  this(Expression e, DotListExpression dotList)
-  {
-    super(e);
-    mixin(set_kind);
-    this.children ~= [dotList];
-    this.dotList = dotList;
-  }
-}
-
-class CallExpression : UnaryExpression
-{
-  Expression[] args;
-  this(Expression e, Expression[] args)
-  {
-    super(e);
-    mixin(set_kind);
-    this.children ~= args;
-    this.args = args;
-  }
-}
-
-class NewExpression : /*Unary*/Expression
-{
-  Expression[] newArgs;
-  Type type;
-  Expression[] ctorArgs;
-  this(/*Expression e, */Expression[] newArgs, Type type, Expression[] ctorArgs)
-  {
-    /*super(e);*/
-    mixin(set_kind);
-    if (newArgs.length)
-      this.children ~= newArgs;
-    this.children ~= type;
-    if (ctorArgs.length)
-      this.children ~= ctorArgs;
-    this.newArgs = newArgs;
-    this.type = type;
-    this.ctorArgs = ctorArgs;
-  }
-}
-
-class NewAnonClassExpression : /*Unary*/Expression
-{
-  Expression[] newArgs;
-  BaseClass[] bases;
-  Expression[] ctorArgs;
-  Declarations decls;
-  this(/*Expression e, */Expression[] newArgs, BaseClass[] bases, Expression[] ctorArgs, Declarations decls)
-  {
-    /*super(e);*/
-    mixin(set_kind);
-    if (newArgs.length)
-      this.children ~= newArgs;
-    if (bases.length)
-      this.children ~= bases;
-    if (ctorArgs.length)
-      this.children ~= ctorArgs;
-    this.children ~= decls;
-
-    this.newArgs = newArgs;
-    this.bases = bases;
-    this.ctorArgs = ctorArgs;
-    this.decls = decls;
-  }
-}
-
-class DeleteExpression : UnaryExpression
-{
-  this(Expression e)
-  {
-    super(e);
-    mixin(set_kind);
-  }
-}
-
-class CastExpression : UnaryExpression
-{
-  Type type;
-  this(Expression e, Type type)
-  {
-    this.children = [type];
-    super(e);
-    mixin(set_kind);
-    this.type = type;
-  }
-}
-
-class IndexExpression : UnaryExpression
-{
-  Expression[] args;
-  this(Expression e, Expression[] args)
-  {
-    super(e);
-    mixin(set_kind);
-    this.children ~= args;
-    this.args = args;
-  }
-}
-
-class SliceExpression : UnaryExpression
-{
-  Expression left, right;
-  this(Expression e, Expression left, Expression right)
-  {
-    super(e);
-    mixin(set_kind);
-    this.children ~= [left, right];
-    this.left = left;
-    this.right = right;
-  }
-}
-
-/*
-class PrimaryExpression
-{
-
-}
-*/
-
-class IdentifierExpression : Expression
-{
-  Token* identifier;
-  this(Token* identifier)
-  {
-    mixin(set_kind);
-    this.identifier = identifier;
-  }
-}
-
-class SpecialTokenExpression : Expression
-{
-  Token* special;
-  this(Token* special)
-  {
-    mixin(set_kind);
-    this.special = special;
-  }
-}
-
-/*
-class IdentifierListExpression : Expression
-{
-  Expression[] identList;
-  this(Expression[] identList)
-  {
-    this.identList = identList;
-  }
-}
-*/
-class DotListExpression : Expression
-{
-  Expression[] items;
-  this(Expression[] items)
-  {
-    mixin(set_kind);
-    this.children = items;
-    this.items = items;
-  }
-}
-
-class TemplateInstanceExpression : Expression
-{
-  Token* ident;
-  TemplateArguments targs;
-  this(Token* ident, TemplateArguments targs)
-  {
-    mixin(set_kind);
-    this.children = [targs];
-    this.ident = ident;
-    this.targs = targs;
-  }
-}
-
-class ThisExpression : Expression
-{
-  this()
-  {
-    mixin(set_kind);
-  }
-}
-
-class SuperExpression : Expression
-{
-  this()
-  {
-    mixin(set_kind);
-  }
-}
-
-class NullExpression : Expression
-{
-  this()
-  {
-    mixin(set_kind);
-  }
-}
-
-class DollarExpression : Expression
-{
-  this()
-  {
-    mixin(set_kind);
-  }
-}
-
-class BoolExpression : Expression
-{
-  this()
-  {
-    mixin(set_kind);
-  }
-}
-
-class IntNumberExpression : Expression
-{
-  TOK type;
-  ulong number;
-  this(TOK type, ulong number)
-  {
-    mixin(set_kind);
-    this.number = number;
-    this.type = type;
-  }
-}
-
-class RealNumberExpression : Expression
-{
-  TOK type;
-  real number;
-  this(TOK type, real number)
-  {
-    mixin(set_kind);
-    this.number = number;
-    this.type = type;
-  }
-}
-
-class CharLiteralExpression : Expression
-{
-  this()
-  {
-    mixin(set_kind);
-  }
-}
-
-class StringLiteralsExpression : Expression
-{
-  Token*[] strings;
-  this(Token*[] strings)
-  {
-    mixin(set_kind);
-    this.strings = strings;
-  }
-
-  string getString()
-  {
-    char[] buffer;
-    foreach (strTok; strings)
-    {
-      buffer ~= strTok.str[0..$-1];
-    }
-    return buffer;
-  }
-}
-
-class ArrayLiteralExpression : Expression
-{
-  Expression[] values;
-  this(Expression[] values)
-  {
-    mixin(set_kind);
-    this.children = values;
-    this.values = values;
-  }
-}
-
-class AssocArrayLiteralExpression : Expression
-{
-  Expression[] keys, values;
-  this(Expression[] keys, Expression[] values)
-  {
-    assert(keys.length == values.length);
-    mixin(set_kind);
-    foreach (i, key; keys)
-      this.children ~= [key, values[i]];
-    this.keys = keys;
-    this.values = values;
-  }
-}
-
-class AssertExpression : Expression
-{
-  Expression expr, msg;
-  this(Expression expr, Expression msg)
-  {
-    mixin(set_kind);
-    this.children = [expr];
-    if (msg)
-      this.children ~= msg;
-    this.expr = expr;
-    this.msg = msg;
-  }
-}
-
-class MixinExpression : Expression
-{
-  Expression expr;
-  this(Expression expr)
-  {
-    mixin(set_kind);
-    this.children = [expr];
-    this.expr = expr;
-  }
-}
-
-class ImportExpression : Expression
-{
-  Expression expr;
-  this(Expression expr)
-  {
-    mixin(set_kind);
-    this.children = [expr];
-    this.expr = expr;
-  }
-}
-
-class TypeofExpression : Expression
-{
-  Type type;
-  this(Type type)
-  {
-    mixin(set_kind);
-    this.children = [type];
-    this.type = type;
-  }
-}
-
-class TypeDotIdExpression : Expression
-{
-  Type type;
-  Token* ident;
-  this(Type type, Token* ident)
-  {
-    mixin(set_kind);
-    this.children = [type];
-    this.type = type;
-    this.ident = ident;
-  }
-}
-
-class TypeidExpression : Expression
-{
-  Type type;
-  this(Type type)
-  {
-    mixin(set_kind);
-    this.children = [type];
-    this.type = type;
-  }
-}
-
-class IsExpression : Expression
-{
-  Type type;
-  Token* ident;
-  Token* opTok, specTok;
-  Type specType;
-  this(Type type, Token* ident, Token* opTok, Token* specTok, Type specType)
-  {
-    mixin(set_kind);
-    this.children = [type];
-    if (specType)
-      this.children ~= specType;
-    this.type = type;
-    this.ident = ident;
-    this.opTok = opTok;
-    this.specTok = specTok;
-    this.specType = specType;
-  }
-}
-
-class FunctionLiteralExpression : Expression
-{
-  Type returnType;
-  Parameters parameters;
-  FunctionBody funcBody;
-
-  this()
-  {
-    mixin(set_kind);
-    if (returnType)
-      this.children ~= returnType;
-    if (parameters)
-      this.children ~= parameters;
-    this.children ~= funcBody;
-  }
-
-  this(Type returnType, Parameters parameters, FunctionBody funcBody)
-  {
-    this.returnType = returnType;
-    this.parameters = parameters;
-    this.funcBody = funcBody;
-    this();
-  }
-
-  this(FunctionBody funcBody)
-  {
-    this.funcBody = funcBody;
-    this();
-  }
-}
-
-version(D2)
-{
-class TraitsExpression : Expression
-{
-  Token* ident;
-  TemplateArguments targs;
-  this(typeof(ident) ident, typeof(targs) targs)
-  {
-    mixin(set_kind);
-    this.children = [targs];
-    this.ident = ident;
-    this.targs = targs;
-  }
-}
-}
-
-class VoidInitializer : Expression
-{
-  this()
-  {
-    mixin(set_kind);
-  }
-}
-
-class ArrayInitializer : Expression
-{
-  Expression[] keys;
-  Expression[] values;
-  this(Expression[] keys, Expression[] values)
-  {
-    assert(keys.length == values.length);
-    mixin(set_kind);
-    foreach (i, key; keys)
-    {
-      if (key)
-        this.children ~= key;
-      if (values[i])
-        this.children ~= values[i];
-    }
-    this.keys = keys;
-    this.values = values;
-  }
-}
-
-class StructInitializer : Expression
-{
-  Token*[] idents;
-  Expression[] values;
-  this(Token*[] idents, Expression[] values)
-  {
-    mixin(set_kind);
-    this.children = values;
-    this.idents = idents;
-    this.values = values;
-  }
-}
-
-class AsmTypeExpression : UnaryExpression
-{
-  this(Expression e)
-  {
-    super(e);
-    mixin(set_kind);
-  }
-}
-
-class AsmOffsetExpression : UnaryExpression
-{
-  this(Expression e)
-  {
-    super(e);
-    mixin(set_kind);
-  }
-}
-
-class AsmSegExpression : UnaryExpression
-{
-  this(Expression e)
-  {
-    super(e);
-    mixin(set_kind);
-  }
-}
-
-class AsmPostBracketExpression : UnaryExpression
-{
-  this(Expression e)
-  {
-    super(e);
-    mixin(set_kind);
-  }
-}
-
-class AsmBracketExpression : Expression
-{
-  Expression e;
-  this(Expression e)
-  {
-    mixin(set_kind);
-    this.children = [e];
-    this.e = e;
-  }
-}
-
-class AsmLocalSizeExpression : Expression
-{
-  this()
-  {
-    mixin(set_kind);
-  }
-}
-
-class AsmRegisterExpression : Expression
-{
-  Token* register;
-  Token* number; // ST(0) - ST(7)
-  this(Token* register, Token* number = null)
-  {
-    mixin(set_kind);
-    this.register = register;
-    this.number = number;
-  }
-}
--- a/trunk/src/HtmlEntities.d	Tue Aug 21 16:18:02 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,277 +0,0 @@
-/++
-  Author: Aziz Köksal
-  License: GPL3
-+/
-module HtmlEntities;
-
-private const dchar[char[]] entities_table;
-
-static this()
-{
-  entities_table = [
-    "Aacute"[] : '\u00C1',
-    "aacute" : '\u00E1',
-    "Acirc" : '\u00C2',
-    "acirc" : '\u00E2',
-    "acute" : '\u00B4',
-    "AElig" : '\u00C6',
-    "aelig" : '\u00E6',
-    "Agrave" : '\u00C0',
-    "agrave" : '\u00E0',
-    "alefsym" : '\u2135',
-    "Alpha" : '\u0391',
-    "alpha" : '\u03B1',
-    "amp" : '\u0026',
-    "and" : '\u2227',
-    "ang" : '\u2220',
-    "Aring" : '\u00C5',
-    "aring" : '\u00E5',
-    "asymp" : '\u2248',
-    "Atilde" : '\u00C3',
-    "atilde" : '\u00E3',
-    "Auml" : '\u00C4',
-    "auml" : '\u00E4',
-    "bdquo" : '\u201E',
-    "Beta" : '\u0392',
-    "beta" : '\u03B2',
-    "brvbar" : '\u00A6',
-    "bull" : '\u2022',
-    "cap" : '\u2229',
-    "Ccedil" : '\u00C7',
-    "ccedil" : '\u00E7',
-    "cedil" : '\u00B8',
-    "cent" : '\u00A2',
-    "Chi" : '\u03A7',
-    "chi" : '\u03C7',
-    "circ" : '\u02C6',
-    "clubs" : '\u2663',
-    "cong" : '\u2245',
-    "copy" : '\u00A9',
-    "crarr" : '\u21B5',
-    "cup" : '\u222A',
-    "curren" : '\u00A4',
-    "Dagger" : '\u2021',
-    "dagger" : '\u2020',
-    "dArr" : '\u21D3',
-    "darr" : '\u2193',
-    "deg" : '\u00B0',
-    "Delta" : '\u0394',
-    "delta" : '\u03B4',
-    "diams" : '\u2666',
-    "divide" : '\u00F7',
-    "Eacute" : '\u00C9',
-    "eacute" : '\u00E9',
-    "Ecirc" : '\u00CA',
-    "ecirc" : '\u00EA',
-    "Egrave" : '\u00C8',
-    "egrave" : '\u00E8',
-    "empty" : '\u2205',
-    "emsp" : '\u2003',
-    "ensp" : '\u2002',
-    "Epsilon" : '\u0395',
-    "epsilon" : '\u03B5',
-    "equiv" : '\u2261',
-    "Eta" : '\u0397',
-    "eta" : '\u03B7',
-    "ETH" : '\u00D0',
-    "eth" : '\u00F0',
-    "Euml" : '\u00CB',
-    "euml" : '\u00EB',
-    "euro" : '\u20AC',
-    "exist" : '\u2203',
-    "fnof" : '\u0192',
-    "forall" : '\u2200',
-    "frac12" : '\u00BD',
-    "frac14" : '\u00BC',
-    "frac34" : '\u00BE',
-    "frasl" : '\u2044',
-    "Gamma" : '\u0393',
-    "gamma" : '\u03B3',
-    "ge" : '\u2265',
-    "gt" : '\u003E',
-    "hArr" : '\u21D4',
-    "harr" : '\u2194',
-    "hearts" : '\u2665',
-    "hellip" : '\u2026',
-    "Iacute" : '\u00CD',
-    "iacute" : '\u00ED',
-    "Icirc" : '\u00CE',
-    "icirc" : '\u00EE',
-    "iexcl" : '\u00A1',
-    "Igrave" : '\u00CC',
-    "igrave" : '\u00EC',
-    "image" : '\u2111',
-    "infin" : '\u221E',
-    "int" : '\u222B',
-    "Iota" : '\u0399',
-    "iota" : '\u03B9',
-    "iquest" : '\u00BF',
-    "isin" : '\u2208',
-    "Iuml" : '\u00CF',
-    "iuml" : '\u00EF',
-    "Kappa" : '\u039A',
-    "kappa" : '\u03BA',
-    "Lambda" : '\u039B',
-    "lambda" : '\u03BB',
-    "lang" : '\u2329',
-    "laquo" : '\u00AB',
-    "lArr" : '\u21D0',
-    "larr" : '\u2190',
-    "lceil" : '\u2308',
-    "ldquo" : '\u201C',
-    "le" : '\u2264',
-    "lfloor" : '\u230A',
-    "lowast" : '\u2217',
-    "loz" : '\u25CA',
-    "lrm" : '\u200E',
-    "lsaquo" : '\u2039',
-    "lsquo" : '\u2018',
-    "lt" : '\u003C',
-    "macr" : '\u00AF',
-    "mdash" : '\u2014',
-    "micro" : '\u00B5',
-    "middot" : '\u00B7',
-    "minus" : '\u2212',
-    "Mu" : '\u039C',
-    "mu" : '\u03BC',
-    "nabla" : '\u2207',
-    "nbsp" : '\u00A0',
-    "ndash" : '\u2013',
-    "ne" : '\u2260',
-    "ni" : '\u220B',
-    "not" : '\u00AC',
-    "notin" : '\u2209',
-    "nsub" : '\u2284',
-    "Ntilde" : '\u00D1',
-    "ntilde" : '\u00F1',
-    "Nu" : '\u039D',
-    "nu" : '\u03BD',
-    "Oacute" : '\u00D3',
-    "oacute" : '\u00F3',
-    "Ocirc" : '\u00D4',
-    "ocirc" : '\u00F4',
-    "OElig" : '\u0152',
-    "oelig" : '\u0153',
-    "Ograve" : '\u00D2',
-    "ograve" : '\u00F2',
-    "oline" : '\u203E',
-    "Omega" : '\u03A9',
-    "omega" : '\u03C9',
-    "Omicron" : '\u039F',
-    "omicron" : '\u03BF',
-    "oplus" : '\u2295',
-    "or" : '\u2228',
-    "ordf" : '\u00AA',
-    "ordm" : '\u00BA',
-    "Oslash" : '\u00D8',
-    "oslash" : '\u00F8',
-    "Otilde" : '\u00D5',
-    "otilde" : '\u00F5',
-    "otimes" : '\u2297',
-    "Ouml" : '\u00D6',
-    "ouml" : '\u00F6',
-    "para" : '\u00B6',
-    "part" : '\u2202',
-    "permil" : '\u2030',
-    "perp" : '\u22A5',
-    "Phi" : '\u03A6',
-    "phi" : '\u03C6',
-    "Pi" : '\u03A0',
-    "pi" : '\u03C0',
-    "piv" : '\u03D6',
-    "plusmn" : '\u00B1',
-    "pound" : '\u00A3',
-    "Prime" : '\u2033',
-    "prime" : '\u2032',
-    "prod" : '\u220F',
-    "prop" : '\u221D',
-    "Psi" : '\u03A8',
-    "psi" : '\u03C8',
-    "quot" : '\u0022',
-    "radic" : '\u221A',
-    "rang" : '\u232A',
-    "raquo" : '\u00BB',
-    "rArr" : '\u21D2',
-    "rarr" : '\u2192',
-    "rceil" : '\u2309',
-    "rdquo" : '\u201D',
-    "real" : '\u211C',
-    "reg" : '\u00AE',
-    "rfloor" : '\u230B',
-    "Rho" : '\u03A1',
-    "rho" : '\u03C1',
-    "rlm" : '\u200F',
-    "rsaquo" : '\u203A',
-    "rsquo" : '\u2019',
-    "sbquo" : '\u201A',
-    "Scaron" : '\u0160',
-    "scaron" : '\u0161',
-    "sdot" : '\u22C5',
-    "sect" : '\u00A7',
-    "shy" : '\u00AD',
-    "Sigma" : '\u03A3',
-    "sigma" : '\u03C3',
-    "sigmaf" : '\u03C2',
-    "sim" : '\u223C',
-    "spades" : '\u2660',
-    "sub" : '\u2282',
-    "sube" : '\u2286',
-    "sum" : '\u2211',
-    "sup" : '\u2283',
-    "sup1" : '\u00B9',
-    "sup2" : '\u00B2',
-    "sup3" : '\u00B3',
-    "supe" : '\u2287',
-    "szlig" : '\u00DF',
-    "Tau" : '\u03A4',
-    "tau" : '\u03C4',
-    "there4" : '\u2234',
-    "Theta" : '\u0398',
-    "theta" : '\u03B8',
-    "thetasym" : '\u03D1',
-    "thinsp" : '\u2009',
-    "THORN" : '\u00DE',
-    "thorn" : '\u00FE',
-    "tilde" : '\u02DC',
-    "times" : '\u00D7',
-    "trade" : '\u2122',
-    "Uacute" : '\u00DA',
-    "uacute" : '\u00FA',
-    "uArr" : '\u21D1',
-    "uarr" : '\u2191',
-    "Ucirc" : '\u00DB',
-    "ucirc" : '\u00FB',
-    "Ugrave" : '\u00D9',
-    "ugrave" : '\u00F9',
-    "uml" : '\u00A8',
-    "upsih" : '\u03D2',
-    "Upsilon" : '\u03A5',
-    "upsilon" : '\u03C5',
-    "Uuml" : '\u00DC',
-    "uuml" : '\u00FC',
-    "weierp" : '\u2118',
-    "Xi" : '\u039E',
-    "xi" : '\u03BE',
-    "Yacute" : '\u00DD',
-    "yacute" : '\u00FD',
-    "yen" : '\u00A5',
-    "Yuml" : '\u0178',
-    "yuml" : '\u00FF',
-    "Zeta" : '\u0396',
-    "zeta" : '\u03B6',
-    "zwj" : '\u200D',
-    "zwnj" : '\u200C'
-  ];
-}
-
-/++
-  Converts a named HTML entity into its equivalent Unicode codepoint.
-  Returns 0xFFFF if entity doesn't exist.
-+/
-dchar entity2Unicode(char[] entity)
-{
-  auto d = entity in entities_table;
-  if (d)
-    return *d;
-  return 0xFFFF;
-}
\ No newline at end of file
--- a/trunk/src/Identifier.d	Tue Aug 21 16:18:02 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/++
-  Author: Aziz Köksal
-  License: GPL3
-+/
-module Identifier;
-import Token;
-
-struct Identifier
-{
-  TOK type;
-  string str;
-
-  static Identifier opCall(TOK type, string str)
-  {
-    Identifier i;
-    i.type = type;
-    i.str = str;
-    return i;
-  }
-
-  uint toHash()
-  {
-    uint hash;
-    foreach(c; str) {
-      hash *= 9;
-      hash += c;
-    }
-    return hash;
-  }
-}
--- a/trunk/src/Information.d	Tue Aug 21 16:18:02 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/++
-  Author: Aziz Köksal
-  License: GPL3
-+/
-module Information;
-import Messages;
-import std.stdarg;
-
-enum InfoType
-{
-  Lexer,
-  Parser,
-  Semantic
-}
-
-class Information
-{
-  MID id;
-  InfoType type;
-  uint loc;
-  string[] arguments;
-
-  this(InfoType type, MID id, uint loc, string[] arguments)
-  {
-    this.id = id;
-    this.type = type;
-    this.loc = loc;
-    this.arguments = arguments;
-  }
-
-  string getMsg()
-  {
-    return format_args(GetMsg(id), arguments);
-  }
-}
--- a/trunk/src/Keywords.d	Tue Aug 21 16:18:02 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/++
-  Author: Aziz Köksal
-  License: GPL3
-+/
-module Keywords;
-import Token;
-import Identifier;
-
-static const Identifier[] keywords = [
-  {TOK.Abstract, "abstract"},
-  {TOK.Alias, "alias"},
-  {TOK.Align, "align"},
-  {TOK.Asm, "asm"},
-  {TOK.Assert, "assert"},
-  {TOK.Auto, "auto"},
-  {TOK.Body, "body"},
-  {TOK.Bool, "bool"},
-  {TOK.Break, "break"},
-  {TOK.Byte, "byte"},
-  {TOK.Case, "case"},
-  {TOK.Cast, "cast"},
-  {TOK.Catch, "catch"},
-  {TOK.Cdouble, "cdouble"},
-  {TOK.Cent, "cent"},
-  {TOK.Cfloat, "cfloat"},
-  {TOK.Char, "char"},
-  {TOK.Class, "class"},
-  {TOK.Const, "const"},
-  {TOK.Continue, "continue"},
-  {TOK.Creal, "creal"},
-  {TOK.Dchar, "dchar"},
-  {TOK.Debug, "debug"},
-  {TOK.Default, "default"},
-  {TOK.Delegate, "delegate"},
-  {TOK.Delete, "delete"},
-  {TOK.Deprecated, "deprecated"},
-  {TOK.Do, "do"},
-  {TOK.Double, "double"},
-  {TOK.Else, "else"},
-  {TOK.Enum, "enum"},
-  {TOK.Export, "export"},
-  {TOK.Extern, "extern"},
-  {TOK.False, "false"},
-  {TOK.Final, "final"},
-  {TOK.Finally, "finally"},
-  {TOK.Float, "float"},
-  {TOK.For, "for"},
-  {TOK.Foreach, "foreach"},
-  {TOK.Foreach_reverse, "foreach_reverse"},
-  {TOK.Function, "function"},
-  {TOK.Goto, "goto"},
-  {TOK.Idouble, "idouble"},
-  {TOK.If, "if"},
-  {TOK.Ifloat, "ifloat"},
-  {TOK.Import, "import"},
-  {TOK.In, "in"},
-  {TOK.Inout, "inout"},
-  {TOK.Int, "int"},
-  {TOK.Interface, "interface"},
-  {TOK.Invariant, "invariant"},
-  {TOK.Ireal, "ireal"},
-  {TOK.Is, "is"},
-  {TOK.Lazy, "lazy"},
-  {TOK.Long, "long"},
-  {TOK.Macro, "macro"}, // D2.0
-  {TOK.Mixin, "mixin"},
-  {TOK.Module, "module"},
-  {TOK.New, "new"},
-  {TOK.Null, "null"},
-  {TOK.Out, "out"},
-  {TOK.Override, "override"},
-  {TOK.Package, "package"},
-  {TOK.Pragma, "pragma"},
-  {TOK.Private, "private"},
-  {TOK.Protected, "protected"},
-  {TOK.Public, "public"},
-  {TOK.Real, "real"},
-  {TOK.Ref, "ref"},
-  {TOK.Return, "return"},
-  {TOK.Scope, "scope"},
-  {TOK.Short, "short"},
-  {TOK.Static, "static"},
-  {TOK.Struct, "struct"},
-  {TOK.Super, "super"},
-  {TOK.Switch, "switch"},
-  {TOK.Synchronized, "synchronized"},
-  {TOK.Template, "template"},
-  {TOK.This, "this"},
-  {TOK.Throw, "throw"},
-  {TOK.Traits, "__traits"}, // D2.0
-  {TOK.True, "true"},
-  {TOK.Try, "try"},
-  {TOK.Typedef, "typedef"},
-  {TOK.Typeid, "typeid"},
-  {TOK.Typeof, "typeof"},
-  {TOK.Ubyte, "ubyte"},
-  {TOK.Ucent, "ucent"},
-  {TOK.Uint, "uint"},
-  {TOK.Ulong, "ulong"},
-  {TOK.Union, "union"},
-  {TOK.Unittest, "unittest"},
-  {TOK.Ushort, "ushort"},
-  {TOK.Version, "version"},
-  {TOK.Void, "void"},
-  {TOK.Volatile, "volatile"},
-  {TOK.Wchar, "wchar"},
-  {TOK.While, "while"},
-  {TOK.With, "with"},
-  // Special tokens:
-  {TOK.Special, "__FILE__"},
-  {TOK.Special, "__LINE__"},
-  {TOK.Special, "__DATE__"},
-  {TOK.Special, "__TIME__"},
-  {TOK.Special, "__TIMESTAMP__"},
-  {TOK.Special, "__VENDOR__"},
-  {TOK.Special, "__VERSION__"},
-];
--- a/trunk/src/Lexer.d	Tue Aug 21 16:18:02 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1773 +0,0 @@
-/++
-  Author: Aziz Köksal
-  License: GPL3
-+/
-module Lexer;
-import Token;
-import Information;
-import Keywords;
-import Identifier;
-import Messages;
-import HtmlEntities;
-import std.stdio;
-import std.utf;
-import std.uni;
-import std.c.stdlib;
-import std.string;
-
-const char[3] LS = \u2028;
-const char[3] PS = \u2029;
-
-const dchar LSd = 0x2028;
-const dchar PSd = 0x2029;
-
-const uint _Z_ = 26; /// Control+Z
-
-class Lexer
-{
-  Token* head; /// The head of the doubly linked token list.
-  Token* token; /// Points to the current token in the token list.
-  string text;
-  char* p; /// Points to the current character in the source text.
-  char* end; /// Points one character past the end of the source text.
-
-  uint loc = 1; /// line of code
-
-  char[] fileName;
-
-  Information[] errors;
-
-//   bool reportErrors;
-
-  Identifier[string] idtable;
-
-  this(string text, string fileName)
-  {
-    this.fileName = fileName;
-
-    this.text = text;
-    if (text[$-1] != 0)
-    {
-      this.text.length = this.text.length + 1;
-      this.text[$-1] = 0;
-    }
-
-    this.p = this.text.ptr;
-    this.end = this.p + this.text.length;
-//     this.reportErrors = true;
-    loadKeywords();
-
-    this.head = new Token;
-    this.head.type = TOK.HEAD;
-    this.token = this.head;
-    scanShebang();
-  }
-
-  void scanShebang()
-  {
-    if (*p == '#' && p[1] == '!')
-    {
-      Token* t = new Token;
-      t.start = p;
-      t.type = TOK.Shebang;
-      ++p;
-      while (1)
-      {
-        switch (*++p)
-        {
-        case '\r':
-          if (p[1] == '\n')
-            ++p;
-        case '\n':
-          ++loc;
-          if (p[-1] == '\r')
-            t.end = p-1;
-          else
-            t.end = p;
-          break;
-        case LS[0]:
-          t.end = p;
-          if (p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2]))
-          {
-            ++p; ++p;
-            ++loc;
-          }
-          break;
-        case 0, _Z_:
-          t.end = p;
-          break;
-        default:
-          continue;
-        }
-        break; // Exit loop.
-      }
-      this.head.next = t;
-      t.prev = this.head;
-    }
-  }
-
-  public void scan(out Token t)
-  in
-  {
-    assert(text.ptr <= p && p < end);
-  }
-  out
-  {
-    assert(text.ptr <= t.start && t.start < end);
-    assert(text.ptr < t.end && t.end <= end, std.string.format(t.type));
-  }
-  body
-  {
-    uint c = *p;
-
-    while (1)
-    {
-      t.start = p;
-
-      if (c == 0 || c == _Z_)
-      {
-        assert(*p == 0 || *p == _Z_);
-        t.type = TOK.EOF;
-        t.end = p;
-        assert(t.start == t.end);
-        return;
-      }
-
-      if (c == '\n')
-      {
-        c = *++p;
-        ++loc;
-        continue;
-      }
-      else if (c == '\r')
-      {
-        c = *++p;
-        if (c != '\n')
-          ++loc;
-        continue;
-      }
-      else if (c == LS[0] && p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2]))
-      {
-        p += 3;
-        c = *p;
-        continue;
-      }
-
-      if (isidbeg(c))
-      {
-        if (c == 'r' && p[1] == '"' && ++p)
-          return scanRawStringLiteral(t);
-        if (c == 'x' && p[1] == '"')
-          return scanHexStringLiteral(t);
-      Lidentifier:
-        do
-        { c = *++p; }
-        while (isident(c) || c & 128 && isUniAlpha(decodeUTF8()))
-
-        t.end = p;
-
-        string str = t.srcText;
-        Identifier* id = str in idtable;
-
-        if (!id)
-        {
-          idtable[str] = Identifier.Identifier(TOK.Identifier, str);
-          id = str in idtable;
-        }
-        assert(id);
-        t.type = id.type;
-        return;
-      }
-
-      if (isdigit(c))
-        return scanNumber(t);
-
-      if (c == '/')
-      {
-        c = *++p;
-        switch(c)
-        {
-        case '=':
-          ++p;
-          t.type = TOK.DivAssign;
-          t.end = p;
-          return;
-        case '+':
-          uint level = 1;
-          while (1)
-          {
-            c = *++p;
-          LswitchNC: // only jumped to from default case of next switch(c)
-            switch (c)
-            {
-            case '\r':
-              if (p[1] == '\n')
-                ++p;
-            case '\n':
-              ++loc;
-              continue;
-            case 0, _Z_:
-              error(MID.UnterminatedNestedComment);
-              goto LreturnNC;
-            default:
-            }
-
-            c <<= 8;
-            c |= *++p;
-            switch (c)
-            {
-            case 0x2F2B: // /+
-              ++level;
-              continue;
-            case 0x2B2F: // +/
-              if (--level == 0)
-              {
-                ++p;
-              LreturnNC:
-                t.type = TOK.Comment;
-                t.end = p;
-                return;
-              }
-              continue;
-            case 0xE280: // LS[0..1] || PS[0..1]
-              if (p[1] == LS[2] || p[1] == PS[2])
-              {
-                ++loc;
-                ++p;
-              }
-              continue;
-            default:
-              c &= char.max;
-              goto LswitchNC;
-            }
-          }
-        case '*':
-          while (1)
-          {
-            c = *++p;
-          LswitchBC: // only jumped to from default case of next switch(c)
-            switch (c)
-            {
-            case '\r':
-              if (p[1] == '\n')
-                ++p;
-            case '\n':
-              ++loc;
-              continue;
-            case 0, _Z_:
-              error(MID.UnterminatedBlockComment);
-              goto LreturnBC;
-            default:
-            }
-
-            c <<= 8;
-            c |= *++p;
-            switch (c)
-            {
-            case 0x2A2F: // */
-              ++p;
-            LreturnBC:
-              t.type = TOK.Comment;
-              t.end = p;
-              return;
-            case 0xE280: // LS[0..1] || PS[0..1]
-              if (p[1] == LS[2] || p[1] == PS[2])
-              {
-                ++loc;
-                ++p;
-              }
-              continue;
-            default:
-              c &= char.max;
-              goto LswitchBC;
-            }
-          }
-          assert(0);
-        case '/':
-          while (1)
-          {
-            c = *++p;
-            switch (c)
-            {
-            case '\r':
-              if (p[1] == '\n')
-                ++p;
-            case '\n':
-            case 0, _Z_:
-              break;
-            case LS[0]:
-              if (p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2]))
-                break;
-              continue;
-            default:
-              continue;
-            }
-            t.type = TOK.Comment;
-            t.end = p;
-            return;
-          }
-        default:
-          t.type = TOK.Div;
-          t.end = p;
-          return;
-        }
-      }
-
-      switch (c)
-      {
-      case '\'':
-        return scanCharacterLiteral(t);
-      case '`':
-        return scanRawStringLiteral(t);
-      case '"':
-        return scanNormalStringLiteral(t);
-      case '\\':
-        char[] buffer;
-        do
-        {
-          ++p;
-          c = scanEscapeSequence();
-          if (c < 128)
-            buffer ~= c;
-          else
-            encodeUTF8(buffer, c);
-        } while (*p == '\\')
-        buffer ~= 0;
-        t.type = TOK.String;
-        t.str = buffer;
-        t.end = p;
-        return;
-      case '>': /* >  >=  >>  >>=  >>>  >>>= */
-        c = *++p;
-        switch (c)
-        {
-        case '=':
-          t.type = TOK.GreaterEqual;
-          goto Lcommon;
-        case '>':
-          if (p[1] == '>')
-          {
-            ++p;
-            if (p[1] == '=')
-            { ++p;
-              t.type = TOK.URShiftAssign;
-            }
-            else
-              t.type = TOK.URShift;
-          }
-          else if (p[1] == '=')
-          {
-            ++p;
-            t.type = TOK.RShiftAssign;
-          }
-          else
-            t.type = TOK.RShift;
-          goto Lcommon;
-        default:
-          t.type = TOK.Greater;
-          goto Lcommon2;
-        }
-        assert(0);
-      case '<': /* <  <=  <>  <>=  <<  <<= */
-        c = *++p;
-        switch (c)
-        {
-        case '=':
-          t.type = TOK.LessEqual;
-          goto Lcommon;
-        case '<':
-          if (p[1] == '=') {
-            ++p;
-            t.type = TOK.LShiftAssign;
-          }
-          else
-            t.type = TOK.LShift;
-          goto Lcommon;
-        case '>':
-          if (p[1] == '=') {
-            ++p;
-            t.type = TOK.LorEorG;
-          }
-          else
-            t.type = TOK.LorG;
-          goto Lcommon;
-        default:
-          t.type = TOK.Less;
-          goto Lcommon2;
-        }
-        assert(0);
-      case '!': /* !  !<  !>  !<=  !>=  !<>  !<>= */
-        c = *++p;
-        switch (c)
-        {
-        case '<':
-          c = *++p;
-          if (c == '>')
-          {
-            if (p[1] == '=') {
-              ++p;
-              t.type = TOK.Unordered;
-            }
-            else
-              t.type = TOK.UorE;
-          }
-          else if (c == '=')
-          {
-            t.type = TOK.UorG;
-          }
-          else {
-            t.type = TOK.UorGorE;
-            goto Lcommon2;
-          }
-          goto Lcommon;
-        case '>':
-          if (p[1] == '=')
-          {
-            ++p;
-            t.type = TOK.UorL;
-          }
-          else
-            t.type = TOK.UorLorE;
-          goto Lcommon;
-        case '=':
-          t.type = TOK.NotEqual;
-          goto Lcommon;
-        default:
-          t.type = TOK.Not;
-          goto Lcommon2;
-        }
-        assert(0);
-      case '.': /* .  .[0-9]  ..  ... */
-        if (p[1] == '.')
-        {
-          ++p;
-          if (p[1] == '.') {
-            ++p;
-            t.type = TOK.Ellipses;
-          }
-          else
-            t.type = TOK.Slice;
-        }
-        else if (isdigit(p[1]))
-        {
-          return scanReal(t);
-        }
-        else
-          t.type = TOK.Dot;
-        goto Lcommon;
-      case '|': /* |  ||  |= */
-        c = *++p;
-        if (c == '=')
-          t.type = TOK.OrAssign;
-        else if (c == '|')
-          t.type = TOK.OrLogical;
-        else {
-          t.type = TOK.OrBinary;
-          goto Lcommon2;
-        }
-        goto Lcommon;
-      case '&': /* &  &&  &= */
-        c = *++p;
-        if (c == '=')
-          t.type = TOK.AndAssign;
-        else if (c == '&')
-          t.type = TOK.AndLogical;
-        else {
-          t.type = TOK.AndBinary;
-          goto Lcommon2;
-        }
-        goto Lcommon;
-      case '+': /* +  ++  += */
-        c = *++p;
-        if (c == '=')
-          t.type = TOK.PlusAssign;
-        else if (c == '+')
-          t.type = TOK.PlusPlus;
-        else {
-          t.type = TOK.Plus;
-          goto Lcommon2;
-        }
-        goto Lcommon;
-      case '-': /* -  --  -= */
-        c = *++p;
-        if (c == '=')
-          t.type = TOK.MinusAssign;
-        else if (c == '-')
-          t.type = TOK.MinusMinus;
-        else {
-          t.type = TOK.Minus;
-          goto Lcommon2;
-        }
-        goto Lcommon;
-      case '=': /* =  == */
-        if (p[1] == '=') {
-          ++p;
-          t.type = TOK.Equal;
-        }
-        else
-          t.type = TOK.Assign;
-        goto Lcommon;
-      case '~': /* ~  ~= */
-         if (p[1] == '=') {
-           ++p;
-           t.type = TOK.CatAssign;
-         }
-         else
-           t.type = TOK.Tilde;
-         goto Lcommon;
-      case '*': /* *  *= */
-         if (p[1] == '=') {
-           ++p;
-           t.type = TOK.MulAssign;
-         }
-         else
-           t.type = TOK.Mul;
-         goto Lcommon;
-      case '^': /* ^  ^= */
-         if (p[1] == '=') {
-           ++p;
-           t.type = TOK.XorAssign;
-         }
-         else
-           t.type = TOK.Xor;
-         goto Lcommon;
-      case '%': /* %  %= */
-         if (p[1] == '=') {
-           ++p;
-           t.type = TOK.ModAssign;
-         }
-         else
-           t.type = TOK.Mod;
-         goto Lcommon;
-      // Single character tokens:
-      case '(':
-        t.type = TOK.LParen;
-        goto Lcommon;
-      case ')':
-        t.type = TOK.RParen;
-        goto Lcommon;
-      case '[':
-        t.type = TOK.LBracket;
-        goto Lcommon;
-      case ']':
-        t.type = TOK.RBracket;
-        goto Lcommon;
-      case '{':
-        t.type = TOK.LBrace;
-        goto Lcommon;
-      case '}':
-        t.type = TOK.RBrace;
-        goto Lcommon;
-      case ':':
-        t.type = TOK.Colon;
-        goto Lcommon;
-      case ';':
-        t.type = TOK.Semicolon;
-        goto Lcommon;
-      case '?':
-        t.type = TOK.Question;
-        goto Lcommon;
-      case ',':
-        t.type = TOK.Comma;
-        goto Lcommon;
-      case '$':
-        t.type = TOK.Dollar;
-      Lcommon:
-        ++p;
-      Lcommon2:
-        t.end = p;
-        return;
-      case '#':
-        return scanSpecialToken(t);
-      default:
-      }
-
-      if (c & 128 && isUniAlpha(decodeUTF8()))
-        goto Lidentifier;
-      c = *++p;
-    }
-  }
-
-  void scanNormalStringLiteral(ref Token t)
-  {
-    assert(*p == '"');
-    ++p;
-    char[] buffer;
-    t.type = TOK.String;
-    while (1)
-    {
-      switch (*p)
-      {
-      case '"':
-        ++p;
-      Lreturn:
-        buffer ~= 0;
-        t.str = buffer;
-        t.pf = scanPostfix();
-        t.end = p;
-        return;
-      case '\\':
-        ++p;
-        dchar d = scanEscapeSequence();
-        if (d < 128)
-          buffer ~= d;
-        else
-          encodeUTF8(buffer, d);
-        continue;
-      case '\r':
-        if (p[1] == '\n')
-          ++p;
-      case '\n':
-        ++p;
-        ++loc;
-        buffer ~= '\n'; // Convert EndOfLine to \n.
-        continue;
-      case 0, _Z_:
-        error(MID.UnterminatedString);
-        goto Lreturn;
-      default:
-        if (*p & 128)
-        {
-//           char* begin = p;
-          dchar d = decodeUTF8();
-          if (d == LSd || d == PSd)
-            goto case '\n';
-
-          // We don't copy per pointer because we might include
-          // invalid, skipped utf-8 sequences. See decodeUTF8().
-//           ++p;
-//           buffer ~= begin[0 .. p - begin];
-          ++p;
-          encodeUTF8(buffer, d);
-          continue;
-        }
-        // Copy ASCII character.
-        buffer ~= *p++;
-      }
-    }
-    assert(0);
-  }
-
-  void scanCharacterLiteral(ref Token t)
-  {
-    assert(*p == '\'');
-    MID id = MID.UnterminatedCharacterLiteral;
-    ++p;
-    TOK type = TOK.CharLiteral;
-    switch (*p)
-    {
-    case '\\':
-      ++p;
-      switch (*p)
-      {
-      case 'u':
-        type = TOK.WCharLiteral; break;
-      case 'U':
-        type = TOK.DCharLiteral; break;
-      default:
-      }
-      t.dchar_ = scanEscapeSequence();
-      break;
-    case '\'':
-      ++p;
-      id = MID.EmptyCharacterLiteral;
-    case '\n', '\r', 0, _Z_:
-      goto Lerr;
-    default:
-      uint c = *p;
-      if (c & 128)
-      {
-        c = decodeUTF8();
-        if (c == LSd || c == PSd)
-          goto Lerr;
-        if (c <= 0xFFFF)
-          type = TOK.WCharLiteral;
-        else
-          type = TOK.DCharLiteral;
-      }
-      t.dchar_ = c;
-      ++p;
-    }
-
-    if (*p == '\'')
-      ++p;
-    else
-    Lerr:
-      error(id);
-    t.type = type;
-    t.end = p;
-  }
-
-  char scanPostfix()
-  {
-    switch (*p)
-    {
-    case 'c':
-    case 'w':
-    case 'd':
-      return *p++;
-    default:
-      return 0;
-    }
-    assert(0);
-  }
-
-  void scanRawStringLiteral(ref Token t)
-  {
-    uint delim = *p;
-    assert(delim == '`' || delim == '"' && p[-1] == 'r');
-    t.type = TOK.String;
-    char[] buffer;
-    uint c;
-    while (1)
-    {
-      c = *++p;
-      switch (c)
-      {
-      case '\r':
-        if (p[1] == '\n')
-          ++p;
-        c = '\n'; // Convert '\r' and '\r\n' to '\n'
-      case '\n':
-        ++loc;
-        break;
-      case '`':
-      case '"':
-        if (c == delim)
-        {
-          ++p;
-          t.pf = scanPostfix();
-        Lreturn:
-          t.str = buffer ~ '\0';
-          t.end = p;
-          return;
-        }
-        break;
-      case LS[0]:
-        if (p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2]))
-        {
-          c = '\n';
-          ++p; ++p;
-          ++loc;
-        }
-        break;
-      case 0, _Z_:
-        if (delim == 'r')
-          error(MID.UnterminatedRawString);
-        else
-          error(MID.UnterminatedBackQuoteString);
-        goto Lreturn;
-      default:
-      }
-      buffer ~= c; // copy character to buffer
-    }
-    assert(0);
-  }
-
-  void scanHexStringLiteral(ref Token t)
-  {
-    assert(p[0] == 'x' && p[1] == '"');
-    t.type = TOK.String;
-
-    uint c;
-    ubyte[] buffer;
-    ubyte h; // hex number
-    uint n; // number of hex digits
-
-    ++p;
-    while (1)
-    {
-      c = *++p;
-      switch (c)
-      {
-      case '"':
-        ++p;
-        if (n & 1)
-          error(MID.OddNumberOfDigitsInHexString);
-        t.pf = scanPostfix();
-      Lreturn:
-        buffer ~= 0;
-        t.str = cast(string) buffer;
-        t.end = p;
-        return;
-      case '\r':
-        if (p[1] == '\n')
-          ++p;
-      case '\n':
-        ++loc;
-        continue;
-      default:
-        if (ishexad(c))
-        {
-          if (c <= '9')
-            c -= '0';
-          else if (c <= 'F')
-            c -= 'A' - 10;
-          else
-            c -= 'a' - 10;
-
-          if (n & 1)
-          {
-            h <<= 4;
-            h |= c;
-            buffer ~= h;
-          }
-          else
-            h = cast(ubyte)c;
-          ++n;
-          continue;
-        }
-        else if (isspace(c))
-          continue;
-
-        if (c >= 128)
-        {
-          c = decodeUTF8();
-          if (c == LSd || c == PSd)
-          {
-            ++p; ++p;
-            ++loc;
-            continue;
-          }
-        }
-        else if (c == 0 || c == _Z_)
-        {
-          error(MID.UnterminatedHexString);
-          t.pf = 0;
-          goto Lreturn;
-        }
-        error(MID.NonHexCharInHexString, cast(dchar)c);
-      }
-    }
-    assert(0);
-  }
-
-  dchar scanEscapeSequence()
-  {
-    uint c = char2ev(*p);
-    if (c)
-    {
-      ++p;
-      return c;
-    }
-    uint digits = 2;
-
-    switch (*p)
-    {
-    case 'x':
-      c = 0;
-      while (1)
-      {
-        ++p;
-        if (ishexad(*p))
-        {
-          c *= 16;
-          if (*p <= '9')
-            c += *p - '0';
-          else if (*p <= 'F')
-            c += *p - 'A' + 10;
-          else
-            c += *p - 'a' + 10;
-
-          if (!--digits)
-          {
-            ++p;
-            break;
-          }
-        }
-        else
-        {
-          error(MID.InsufficientHexDigits);
-          break;
-        }
-      }
-      if (!isValidDchar(c))
-        error(MID.InvalidUnicodeCharacter);
-      break;
-    case 'u':
-      digits = 4;
-      goto case 'x';
-    case 'U':
-      digits = 8;
-      goto case 'x';
-    default:
-      if (isoctal(*p))
-      {
-        c = 0;
-        c += *p - '0';
-        ++p;
-        if (!isoctal(*p))
-          return c;
-        c *= 8;
-        c += *p - '0';
-        ++p;
-        if (!isoctal(*p))
-          return c;
-        c *= 8;
-        c += *p - '0';
-        ++p;
-      }
-      else if(*p == '&')
-      {
-        if (isalpha(*++p))
-        {
-          auto begin = p;
-          while (isalnum(*++p))
-          {}
-
-          if (*p == ';')
-          {
-            c = entity2Unicode(begin[0..p - begin]);
-            ++p;
-            if (c == 0xFFFF)
-              error(MID.UndefinedHTMLEntity, (begin-1)[0..p-(begin-1)]);
-          }
-          else
-            error(MID.UnterminatedHTMLEntity);
-        }
-        else
-          error(MID.InvalidBeginHTMLEntity);
-      }
-      else
-        error(MID.UndefinedEscapeSequence);
-    }
-
-    return c;
-  }
-
-  /*
-    IntegerLiteral:= (Dec|Hex|Bin|Oct)Suffix?
-    Dec:= (0|[1-9][0-9_]*)
-    Hex:= 0[xX] HexDigits
-    Bin:= 0[bB][01_]+
-    Oct:= 0[0-7_]+
-    Suffix:= (L[uU]?|[uU]L?)
-    HexDigits:= [0-9a-zA-Z_]+
-
-    Invalid: "0b_", "0x_", "._"
-  */
-  void scanNumber(ref Token t)
-  {
-    ulong ulong_;
-    bool overflow;
-    bool isDecimal;
-    size_t digits;
-
-    if (*p != '0')
-      goto LscanInteger;
-    ++p; // skip zero
-    // check for xX bB ...
-    switch (*p)
-    {
-    case 'x','X':
-      goto LscanHex;
-    case 'b','B':
-      goto LscanBin;
-    case 'L':
-      if (p[1] == 'i')
-        goto LscanReal;
-    case '.':
-      if (p[1] == '.')
-        break;
-    case 'i','f','F', 'e', 'E': // Imaginary and float literal suffix
-      goto LscanReal;
-    default:
-      if (*p == '_' || isoctal(*p))
-        goto LscanOct;
-    }
-
-    // Number 0
-    assert(p[-1] == '0');
-    assert(ulong_ == 0);
-    isDecimal = true;
-    goto Lfinalize;
-
-  LscanInteger:
-    assert(*p != 0 && isdigit(*p));
-    isDecimal = true;
-    goto Lenter_loop_int;
-    while (1)
-    {
-      if (*++p == '_')
-        continue;
-      if (!isdigit(*p))
-        break;
-    Lenter_loop_int:
-      if (ulong_ < ulong.max/10 || (ulong_ == ulong.max/10 && *p <= '5'))
-      {
-        ulong_ *= 10;
-        ulong_ += *p - '0';
-        continue;
-      }
-      // Overflow: skip following digits.
-      overflow = true;
-      while (isdigit(*++p)) {}
-      break;
-    }
-
-    // The number could be a float, so check overflow below.
-    switch (*p)
-    {
-    case '.':
-      if (p[1] != '.')
-        goto LscanReal;
-      break;
-    case 'L':
-      if (p[1] != 'i')
-        break;
-    case 'i', 'f', 'F', 'e', 'E':
-      goto LscanReal;
-    default:
-    }
-
-    if (overflow)
-      error(MID.OverflowDecimalNumber);
-
-    assert((isdigit(p[-1]) || p[-1] == '_') && !isdigit(*p) && *p != '_');
-    goto Lfinalize;
-
-  LscanHex:
-    assert(digits == 0);
-    assert(*p == 'x');
-    while (1)
-    {
-      if (*++p == '_')
-        continue;
-      if (!ishexad(*p))
-        break;
-      ++digits;
-      ulong_ *= 16;
-      if (*p <= '9')
-        ulong_ += *p - '0';
-      else if (*p <= 'F')
-        ulong_ += *p - 'A' + 10;
-      else
-        ulong_ += *p - 'a' + 10;
-    }
-
-    switch (*p)
-    {
-    case '.':
-      if (p[1] != '.')
-        goto LscanHexReal;
-      break;
-    case 'L':
-      if (p[1] != 'i')
-        break;
-    case 'i', 'p', 'P':
-      goto LscanHexReal;
-    default:
-    }
-    if (digits == 0)
-      error(MID.NoDigitsInHexNumber);
-    else if (digits > 16)
-    {
-      // Overflow: skip following digits.
-      error(MID.OverflowHexNumber);
-      while (ishexad(*++p)) {}
-    }
-    goto Lfinalize;
-  LscanHexReal:
-    return scanHexReal(t);
-
-  LscanBin:
-    assert(digits == 0);
-    assert(*p == 'b');
-    while (1)
-    {
-      if (*++p == '0')
-      {
-        ++digits;
-        ulong_ *= 2;
-      }
-      if (*p == '1')
-      {
-        ++digits;
-        ulong_ *= 2;
-        ulong_ += *p - '0';
-      }
-      if (*p == '_')
-        continue;
-      break;
-    }
-
-    if (digits == 0)
-      error(MID.NoDigitsInBinNumber);
-
-    if (digits > 64)
-      error(MID.OverflowBinaryNumber);
-    assert((p[-1] == '0' || p[-1] == '1' || p[-1] == '_') && !(*p == '0' || *p == '1' || *p == '_'));
-    goto Lfinalize;
-
-  LscanOct:
-    assert(*p == '_' || isoctal(*p));
-    if (*p != '_')
-      goto Lenter_loop_oct;
-    while (1)
-    {
-      if (*++p == '_')
-        continue;
-      if (!isoctal(*p))
-        break;
-    Lenter_loop_oct:
-      if (ulong_ < ulong.max/2 || (ulong_ == ulong.max/2 && *p <= '1'))
-      {
-        ulong_ *= 8;
-        ulong_ += *p - '0';
-        ++p;
-        continue;
-      }
-      // Overflow: skip following digits.
-      overflow = true;
-      while (isdigit(*++p)) {}
-      break;
-    }
-
-    bool hasDecimalDigits;
-    if (isdigit(*p))
-    {
-      hasDecimalDigits = true;
-      while (isdigit(*++p)) {}
-    }
-
-    // The number could be a float, so check errors below.
-    switch (*p)
-    {
-    case '.':
-      if (p[1] != '.')
-        goto LscanReal;
-      break;
-    case 'L':
-      if (p[1] != 'i')
-        break;
-    case 'i', 'f', 'F', 'e', 'E':
-      goto LscanReal;
-    default:
-    }
-
-    if (hasDecimalDigits)
-      error(MID.OctalNumberHasDecimals);
-    if (overflow)
-      error(MID.OverflowOctalNumber);
-//     goto Lfinalize;
-
-  Lfinalize:
-    enum Suffix
-    {
-      None     = 0,
-      Unsigned = 1,
-      Long     = 2
-    }
-
-    Suffix suffix;
-    while (1)
-    {
-      switch (*p)
-      {
-      case 'L':
-        if (suffix & Suffix.Long)
-          break;
-        suffix |= Suffix.Long;
-        ++p;
-        continue;
-      case 'u', 'U':
-        if (suffix & Suffix.Unsigned)
-          break;
-        suffix |= Suffix.Unsigned;
-        ++p;
-        continue;
-      default:
-        break;
-      }
-      break;
-    }
-
-    switch (suffix)
-    {
-    case Suffix.None:
-      if (ulong_ & 0x8000000000000000)
-      {
-        if (isDecimal)
-          error(MID.OverflowDecimalSign);
-        t.type = TOK.Uint64;
-      }
-      else if (ulong_ & 0xFFFFFFFF00000000)
-        t.type = TOK.Int64;
-      else if (ulong_ & 0x80000000)
-        t.type = isDecimal ? TOK.Int64 : TOK.Uint32;
-      else
-        t.type = TOK.Int32;
-      break;
-    case Suffix.Unsigned:
-      if (ulong_ & 0xFFFFFFFF00000000)
-        t.type = TOK.Uint64;
-      else
-        t.type = TOK.Uint32;
-      break;
-    case Suffix.Long:
-      if (ulong_ & 0x8000000000000000)
-      {
-        if (isDecimal)
-          error(MID.OverflowDecimalSign);
-        t.type = TOK.Uint64;
-      }
-      else
-        t.type = TOK.Int64;
-      break;
-    case Suffix.Unsigned | Suffix.Long:
-      t.type = TOK.Uint64;
-      break;
-    default:
-      assert(0);
-    }
-    t.ulong_ = ulong_;
-    t.end = p;
-    return;
-  LscanReal:
-    scanReal(t);
-    return;
-  }
-
-  /*
-    FloatLiteral:= Float[fFL]?i?
-    Float:= DecFloat | HexFloat
-    DecFloat:= ([0-9][0-9_]*[.][0-9_]*DecExponent?) | [.][0-9][0-9_]*DecExponent? | [0-9][0-9_]*DecExponent
-    DecExponent:= [eE][+-]?[0-9][0-9_]*
-    HexFloat:= 0[xX](HexDigits[.]HexDigits | [.][0-9a-zA-Z]HexDigits? | HexDigits)HexExponent
-    HexExponent:= [pP][+-]?[0-9][0-9_]*
-  */
-  void scanReal(ref Token t)
-  {
-    if (*p == '.')
-      // This function was called by scan() or scanNumber().
-      while (isdigit(*++p) || *p == '_') {}
-    else
-    {
-      // This function was called by scanNumber().
-      debug switch (*p)
-      {
-      case 'L':
-        if (p[1] != 'i')
-          assert(0);
-      case 'i', 'f', 'F', 'e', 'E': break;
-      default: assert(0);
-      }
-    }
-
-    // Scan exponent.
-    if (*p == 'e' || *p == 'E')
-    {
-      ++p;
-      if (*p == '-' || *p == '+')
-        ++p;
-      if (!isdigit(*p))
-        error(MID.FloatExponentDigitExpected);
-      else
-        while (isdigit(*++p) || *p == '_') {}
-    }
-
-    // Copy string to buffer ignoring underscores.
-    char[] buffer;
-    char* end = p;
-    p = t.start;
-    do
-    {
-      if (*p == '_')
-      {
-        ++p;
-        continue;
-      }
-      buffer ~= *p;
-      ++p;
-    } while (p != end)
-    buffer ~= 0;
-    finalizeFloat(t, buffer);
-  }
-
-  void scanHexReal(ref Token t)
-  {
-    assert(*p == '.' || *p == 'i' || *p == 'p' || *p == 'P' || (*p == 'L' && p[1] == 'i'));
-    MID mid;
-    if (*p == '.')
-      while (ishexad(*++p) || *p == '_') {}
-    if (*p != 'p' && *p != 'P')
-    {
-      mid = MID.HexFloatExponentRequired;
-      goto Lerr;
-    }
-    // Copy mantissa to a buffer ignoring underscores.
-    char* end = p;
-    p = t.start;
-    char[] buffer;
-    do
-    {
-      if (*p == '_')
-      {
-        ++p;
-        continue;
-      }
-      buffer ~= *p;
-      ++p;
-    } while (p != end)
-
-    assert(p == end && (*p == 'p' || *p == 'P'));
-    // Scan and copy the exponent.
-    buffer ~= 'p';
-    size_t bufflen = buffer.length;
-    while (1)
-    {
-      if (*++p == '_')
-        continue;
-      if (isdigit(*p))
-        buffer ~= *p;
-      else
-        break;
-    }
-    // When the buffer length hasn't changed, no digits were copied.
-    if (bufflen == buffer.length) {
-      mid = MID.HexFloatMissingExpDigits;
-      goto Lerr;
-    }
-    buffer ~= 0; // Terminate for C functions.
-    finalizeFloat(t, buffer);
-    return;
-  Lerr:
-    t.type = TOK.Float32;
-    t.end = p;
-    error(mid);
-  }
-
-  void finalizeFloat(ref Token t, string buffer)
-  {
-    // Float number is well-formed. Check suffixes and do conversion.
-    switch (*p)
-    {
-    case 'f', 'F':
-      t.type = TOK.Float32;
-      t.float_ = strtof(buffer.ptr, null);
-      ++p;
-      break;
-    case 'L':
-      t.type = TOK.Float80;
-      t.real_ = strtold(buffer.ptr, null);
-      ++p;
-      break;
-    default:
-      t.type = TOK.Float64;
-      t.double_ = strtod(buffer.ptr, null);
-      break;
-    }
-    if (*p == 'i')
-    {
-      ++p;
-      t.type += 3; // Switch to imaginary counterpart.
-    }
-    if (getErrno == ERANGE)
-      error(MID.OverflowFloatNumber);
-    t.end = p;
-  }
-
-  /// Scan special token: #line Integer [Filespec] EndOfLine
-  void scanSpecialToken(ref Token t)
-  {
-    assert(*p == '#');
-
-    t.type = TOK.HashLine;
-
-    MID mid;
-
-    ++p;
-    if (p[0] != 'l' || p[1] != 'i' || p[2] != 'n' || p[3] != 'e')
-    {
-      mid = MID.ExpectedNumberAfterSTLine;
-      goto Lerr;
-    }
-    p += 3;
-
-    enum State
-    { Number, Filespec, End }
-
-    State state;
-
-  Loop:
-    while (1)
-    {
-      switch (*++p)
-      {
-      case '\r':
-        if (p[1] == '\n')
-          ++p;
-      case '\n', 0, _Z_:
-        break Loop;
-      case LS[0]:
-        if (p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2]))
-        {
-          ++p; ++p;
-          break Loop;
-        }
-        goto default;
-      default:
-        if (isspace(*p))
-          continue;
-        if (state == State.Number)
-        {
-          if (!isdigit(*p))
-          {
-            mid = MID.ExpectedNumberAfterSTLine;
-            goto Lerr;
-          }
-          t.line_num = new Token;
-          scan(*t.line_num);
-          --p;
-          state = State.Filespec;
-        }
-        else if (state == State.Filespec)
-        {
-          if (*p != '"')
-          {
-            mid = MID.ExpectedFilespec;
-            goto Lerr;
-          }
-          t.line_filespec = new Token;
-          t.line_filespec.start = p;
-          t.line_filespec.type = TOK.Filespec;
-          while (1)
-          {
-            switch (*++p)
-            {
-            case '"':
-              break;
-            case LS[0]:
-              if (!(p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2])))
-                goto default;
-            case '\r', '\n', 0, _Z_:
-              mid = MID.UnterminatedFilespec;
-              t.line_filespec.end = p;
-              goto Lerr;
-            default:
-              if (*p & 128)
-                decodeUTF8();
-              continue;
-            }
-            break; // Exit loop.
-          }
-          auto start = t.line_filespec.start +1; // +1 skips '"'
-          t.line_filespec.str = start[0 .. p - start];
-          t.line_filespec.end = p + 1;
-          state = State.End;
-        }
-        else/+ if (state == State.End)+/
-        {
-          mid = MID.UnterminatedSpecialToken;
-          goto Lerr;
-        }
-      }
-    }
-
-    if (state == State.Number)
-    {
-      mid = MID.ExpectedNumberAfterSTLine;
-      goto Lerr;
-    }
-
-    this.loc = t.line_num.uint_ - 1;
-    if (t.line_filespec)
-      this.fileName = t.line_filespec.str;
-    t.end = p;
-
-    return;
-  Lerr:
-    t.end = p;
-    error(mid);
-  }
-
-  dchar decodeUTF8()
-  {
-    assert(*p & 128, "check for ASCII char before calling decodeUTF8().");
-    size_t idx;
-    dchar d;
-    try
-    {
-      d = std.utf.decode(p[0 .. end-p], idx);
-      p += idx -1;
-    }
-    catch (UtfException e)
-    {
-      error(MID.InvalidUTF8Sequence);
-      // Skip to next valid utf-8 sequence
-      while (UTF8stride[*++p] != 0xFF) {}
-      --p;
-    }
-    return d;
-  }
-
-  void loadKeywords()
-  {
-    foreach(k; keywords)
-      idtable[k.str] = k;
-  }
-/+
-  struct State
-  {
-    Lexer lexer;
-    Token token;
-    char* scanPointer;
-    int loc;
-    string fileName;
-    size_t errorLen;
-    static State opCall(Lexer lx)
-    {
-      State s;
-      s.lexer = lx;
-      s.token = lx.token;
-      s.scanPointer = lx.p;
-      s.loc = lx.loc;
-      s.fileName = lx.fileName;
-      s.errorLen = lx.errors.length;
-      return s;
-    }
-    void restore()
-    {
-      lexer.p = scanPointer;
-      lexer.token = token;
-      lexer.loc = loc;
-      lexer.fileName = fileName;
-      lexer.errors = lexer.errors[0..errorLen];
-    }
-  }
-
-  State getState()
-  {
-    return State(this);
-  }
-+/
-
-  private void scanNext(ref Token* t)
-  {
-    assert(t !is null);
-    if (t.next)
-      t = t.next;
-    else if (t.type != TOK.EOF)
-    {
-      Token* new_t = new Token;
-      scan(*new_t);
-      new_t.prev = t;
-      t.next = new_t;
-      t = new_t;
-    }
-  }
-
-  void peek(ref Token* t)
-  {
-    scanNext(t);
-  }
-
-  TOK nextToken()
-  {
-    scanNext(this.token);
-    return this.token.type;
-  }
-
-  void error(MID id, ...)
-  {
-//     if (reportErrors)
-    errors ~= new Information(InfoType.Lexer, id, loc, arguments(_arguments, _argptr));
-  }
-
-  unittest
-  {
-    string sourceText = "unittest { }";
-    auto lx = new Lexer(sourceText, null);
-
-    Token next;
-    lx.peek(next);
-    assert(next == TOK.Unittest);
-    lx.peek(next);
-    assert(next == TOK.LBrace);
-    lx.peek(next);
-    assert(next == TOK.RBrace);
-    lx.peek(next);
-    assert(next == TOK.EOF);
-    writefln("end of peek() unittest");
-  }
-
-  Token* getTokens()
-  {
-    while (nextToken() != TOK.EOF)
-    {}
-    return head;
-  }
-
-  private void encodeUTF8(inout char[] str, dchar d)
-  {
-    char[6] b;
-    assert(d > 0x7F, "check for ASCII char before calling encodeUTF8().");
-    if (d < 0x800)
-    {
-      b[0] = 0xC0 | (d >> 6);
-      b[1] = 0x80 | (d & 0x3F);
-      str ~= b[0..2];
-    }
-    else if (d < 0x10000)
-    {
-      b[0] = 0xE0 | (d >> 12);
-      b[1] = 0x80 | ((d >> 6) & 0x3F);
-      b[2] = 0x80 | (d & 0x3F);
-      str ~= b[0..3];
-    }
-    else if (d < 0x200000)
-    {
-      b[0] = 0xF0 | (d >> 18);
-      b[1] = 0x80 | ((d >> 12) & 0x3F);
-      b[2] = 0x80 | ((d >> 6) & 0x3F);
-      b[3] = 0x80 | (d & 0x3F);
-      str ~= b[0..4];
-    }
-    else if (d < 0x4000000)
-    {
-      b[0] = 0xF8 | (d >> 24);
-      b[1] = 0x80 | ((d >> 18) & 0x3F);
-      b[2] = 0x80 | ((d >> 12) & 0x3F);
-      b[3] = 0x80 | ((d >> 6) & 0x3F);
-      b[4] = 0x80 | (d & 0x3F);
-      str ~= b[0..5];
-    }
-    else if (d < 0x80000000)
-    {
-      b[0] = 0xFC | (d >> 30);
-      b[1] = 0x80 | ((d >> 24) & 0x3F);
-      b[2] = 0x80 | ((d >> 18) & 0x3F);
-      b[3] = 0x80 | ((d >> 12) & 0x3F);
-      b[4] = 0x80 | ((d >> 6) & 0x3F);
-      b[5] = 0x80 | (d & 0x3F);
-      str ~= b[0..6];
-    }
-    else
-      error(MID.InvalidUnicodeCharacter);
-  }
-}
-
-unittest
-{
-  string[] toks = [
-    ">",    ">=", ">>",  ">>=", ">>>", ">>>=", "<",   "<=",  "<>",
-    "<>=",  "<<", "<<=", "!",   "!<",  "!>",   "!<=", "!>=", "!<>",
-    "!<>=", ".",  "..",  "...", "&",   "&&",   "&=",  "+",   "++",
-    "+=",   "-",  "--",  "-=",  "=",   "==",   "~",   "~=",  "*",
-    "*=",   "/",  "/=",  "^",   "^=",  "%",    "%=",  "(",   ")",
-    "[",    "]",  "{",   "}",   ":",   ";",    "?",   ",",   "$"
-  ];
-
-  char[] src;
-
-  foreach (op; toks)
-    src ~= op ~ " ";
-
-  auto lx = new Lexer(src, "");
-  auto tokens = lx.getTokens();
-
-  tokens = tokens[0..$-1]; // exclude TOK.EOF
-
-  assert(tokens.length == toks.length );
-
-  foreach (i, t; tokens)
-    assert(t.srcText == toks[i], std.string.format("Lexed '%s' but expected '%s'", t.srcText, toks[i]));
-}
-
-unittest
-{
-  // Numbers unittest
-  // 0L 0ULi 0_L 0_UL 0x0U 0x0p2 0_Fi 0_e2 0_F 0_i
-  // 0u 0U 0uL 0UL 0L 0LU 0Lu
-  // 0Li 0f 0F 0fi 0Fi 0i
-  // 0b_1_LU 0b1000u
-  // 0x232Lu
-}
-
-/// ASCII character properties table.
-static const int ptable[256] = [
- 0, 0, 0, 0, 0, 0, 0, 0, 0,32, 0,32,32, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-32, 0, 0x2200, 0, 0, 0, 0, 0x2700, 0, 0, 0, 0, 0, 0, 0, 0,
- 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 0, 0, 0, 0, 0, 0x3f00,
- 0,12,12,12,12,12,12, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0x5c00, 0, 0,16,
- 0, 0x70c, 0x80c,12,12,12, 0xc0c, 8, 8, 8, 8, 8, 8, 8, 0xa08, 8,
- 8, 8, 0xd08, 8, 0x908, 8, 0xb08, 8, 8, 8, 8, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-];
-
-enum CProperty
-{
-       Octal = 1,
-       Digit = 1<<1,
-         Hex = 1<<2,
-       Alpha = 1<<3,
-  Underscore = 1<<4,
-  Whitespace = 1<<5
-}
-
-const uint EVMask = 0xFF00; // Bit mask for escape value
-
-private alias CProperty CP;
-int isoctal(char c) { return ptable[c] & CP.Octal; }
-int isdigit(char c) { return ptable[c] & CP.Digit; }
-int ishexad(char c) { return ptable[c] & CP.Hex; }
-int isalpha(char c) { return ptable[c] & CP.Alpha; }
-int isalnum(char c) { return ptable[c] & (CP.Alpha | CP.Digit); }
-int isidbeg(char c) { return ptable[c] & (CP.Alpha | CP.Underscore); }
-int isident(char c) { return ptable[c] & (CP.Alpha | CP.Underscore | CP.Digit); }
-int isspace(char c) { return ptable[c] & CP.Whitespace; }
-int char2ev(char c) { return ptable[c] >> 8; /*(ptable[c] & EVMask) >> 8;*/ }
-
-version(gen_ptable)
-static this()
-{
-  alias ptable p;
-  // Initialize character properties table.
-  for (int i; i < p.length; ++i)
-  {
-    p[i] = 0;
-    if ('0' <= i && i <= '7')
-      p[i] |= CP.Octal;
-    if ('0' <= i && i <= '9')
-      p[i] |= CP.Digit;
-    if (isdigit(i) || 'a' <= i && i <= 'f' || 'A' <= i && i <= 'F')
-      p[i] |= CP.Hex;
-    if ('a' <= i && i <= 'z' || 'A' <= i && i <= 'Z')
-      p[i] |= CP.Alpha;
-    if (i == '_')
-      p[i] |= CP.Underscore;
-    if (i == ' ' || i == '\t' || i == '\v' || i == '\f')
-      p[i] |= CP.Whitespace;
-  }
-  // Store escape sequence values in second byte.
-  assert(CProperty.max <= ubyte.max, "character property flags and escape value byte overlap.");
-  p['\''] |= 39 << 8;
-  p['"'] |= 34 << 8;
-  p['?'] |= 63 << 8;
-  p['\\'] |= 92 << 8;
-  p['a'] |= 7 << 8;
-  p['b'] |= 8 << 8;
-  p['f'] |= 12 << 8;
-  p['n'] |= 10 << 8;
-  p['r'] |= 13 << 8;
-  p['t'] |= 9 << 8;
-  p['v'] |= 11 << 8;
-  // Print a formatted array literal.
-  char[] array = "[\n";
-  for (int i; i < p.length; ++i)
-  {
-    int c = p[i];
-    array ~= std.string.format(c>255?" 0x%x,":"%2d,", c, ((i+1) % 16) ? "":"\n");
-  }
-  array[$-2..$] = "\n]";
-  writefln(array);
-}
--- a/trunk/src/Messages.d	Tue Aug 21 16:18:02 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/++
-  Author: Aziz Köksal
-  License: GPL3
-+/
-module Messages;
-import Settings;
-import std.stdarg;
-
-/// Index into table of compiler messages.
-enum MID
-{
-  // Lexer messages:
-  InvalidUnicodeCharacter,
-  InvalidUTF8Sequence,
-  // ''
-  UnterminatedCharacterLiteral,
-  EmptyCharacterLiteral,
-  // #line
-  ExpectedIdentifierSTLine,
-  ExpectedNumberAfterSTLine,
-  ExpectedFilespec,
-  UnterminatedFilespec,
-  UnterminatedSpecialToken,
-  // ""
-  UnterminatedString,
-  // x""
-  NonHexCharInHexString,
-  OddNumberOfDigitsInHexString,
-  UnterminatedHexString,
-  // /* */ /+ +/
-  UnterminatedBlockComment,
-  UnterminatedNestedComment,
-  // `` r""
-  UnterminatedRawString,
-  UnterminatedBackQuoteString,
-  // \x \u \U
-  UndefinedEscapeSequence,
-  InsufficientHexDigits,
-  // \&[a-zA-Z][a-zA-Z0-9]+;
-  UndefinedHTMLEntity,
-  UnterminatedHTMLEntity,
-  InvalidBeginHTMLEntity,
-  // integer overflows
-  OverflowDecimalSign,
-  OverflowDecimalNumber,
-  OverflowHexNumber,
-  OverflowBinaryNumber,
-  OverflowOctalNumber,
-  OverflowFloatNumber,
-  OctalNumberHasDecimals,
-  NoDigitsInHexNumber,
-  NoDigitsInBinNumber,
-  HexFloatExponentRequired,
-  HexFloatMissingExpDigits,
-  FloatExponentDigitExpected,
-
-  // Parser messages:
-  ExpectedButFound,
-  RedundantStorageClass,
-
-  // Help messages:
-  HelpMain,
-}
-
-string GetMsg(MID mid)
-{
-  assert(mid < GlobalSettings.messages.length);
-  return GlobalSettings.messages[mid];
-}
-
-char[] format(MID mid, ...)
-{
-  auto args = arguments(_arguments, _argptr);
-  return format_args(GetMsg(mid), args);
-}
-
-char[] format(char[] format_str, ...)
-{
-  auto args = arguments(_arguments, _argptr);
-  return format_args(format_str, args);
-}
-
-char[] format_args(char[] format_str, char[][] args)
-{
-  char[] result = format_str;
-
-  foreach (i, arg; args)
-    result = std.string.replace(result, std.string.format("{%s}", i+1), arg);
-
-  return result;
-}
-
-char[][] arguments(TypeInfo[] tinfos, void* argptr)
-{
-  char[][] args;
-  foreach (ti; tinfos)
-  {
-    if (ti == typeid(char[]))
-      args ~= va_arg!(char[])(argptr);
-    else if (ti == typeid(int))
-      args ~= std.string.format(va_arg!(int)(argptr));
-    else if (ti == typeid(dchar))
-      args ~= std.string.format(va_arg!(dchar)(argptr));
-    else
-      assert(0, "argument type not supported yet.");
-  }
-  return args;
-}
--- a/trunk/src/Parser.d	Tue Aug 21 16:18:02 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4193 +0,0 @@
-/++
-  Author: Aziz Köksal
-  License: GPL3
-+/
-module Parser;
-import Lexer;
-import SyntaxTree;
-import Token;
-import Messages;
-import Information;
-import Declarations;
-import Statements;
-import Expressions;
-import Types;
-import std.stdio;
-
-private alias TOK T;
-
-class Parser
-{
-  Lexer lx;
-  Token* token; /// Current non-whitespace token.
-  Token* prevToken; /// Previous non-whitespace token.
-
-  Information[] errors;
-
-  this(char[] srcText, string fileName)
-  {
-    lx = new Lexer(srcText, fileName);
-  }
-
-  debug char* prev;
-
-  void start()
-  {
-    debug prev = lx.text.ptr;
-    nT();
-    prevToken = token;
-  }
-
-  void nT()
-  {
-    prevToken = token;
-    do
-    {
-      lx.nextToken();
-      token = lx.token;
-
-debug if (!trying)
-{
-      writef("\33[32m%s\33[0m", token.type);
-      writef("%s", prev[0 .. token.end - prev]);
-      prev = token.end;
-}
-    } while (token.isWhitespace) // Skip whitespace
-  }
-
-  void skipToOnePast(TOK tok)
-  {
-    for (; token.type != tok && token.type != T.EOF; nT())
-    {}
-    nT();
-  }
-
-  int trying;
-  int errorCount;
-
-  ReturnType try_(ReturnType)(lazy ReturnType parseMethod, out bool success)
-  {
-debug writef("\33[31mtry_\33[0m");
-    ++trying;
-//     auto len = errors.length;
-    auto oldToken = token;
-    auto oldPrevToken = prevToken;
-    auto oldCount = errorCount;
-//     auto lexerState = lx.getState();
-    auto result = parseMethod();
-    // If the length of the array changed we know an error occurred.
-    if (errorCount != oldCount)
-    {
-//       lexerState.restore(); // Restore state of the Lexer object.
-//       errors = errors[0..len]; // Remove errors that were added when parseMethod() was called.
-      token = oldToken;
-      prevToken = oldPrevToken;
-      lx.token = oldToken;
-      errorCount = oldCount;
-      success = false;
-    }
-    else
-      success = true;
-    --trying;
-debug writef("\33[34m%s\33[0m", success);
-    return result;
-  }
-
-  Class set(Class)(Class node, Token* begin)
-  {
-    node.setTokens(begin, this.prevToken);
-    return node;
-  }
-
-  TOK peekNext()
-  {
-    Token* next = token;
-    do
-      lx.peek(next);
-    while (next.isWhitespace) // Skip whitespace
-    return next.type;
-  }
-
-  /++++++++++++++++++++++++++++++
-  + Declaration parsing methods +
-  ++++++++++++++++++++++++++++++/
-
-  Declarations parseModule()
-  {
-    auto decls = new Declarations;
-
-    if (token.type == T.Module)
-    {
-      auto begin = token;
-      ModuleName moduleName;
-      do
-      {
-        nT();
-        moduleName ~= requireId();
-      } while (token.type == T.Dot)
-      require(T.Semicolon);
-      decls ~= set(new ModuleDeclaration(moduleName), begin);
-    }
-    decls ~= parseDeclarationDefinitions();
-    return decls;
-  }
-
-  Declarations parseDeclarationDefinitions()
-  {
-    auto decls = new Declarations;
-    while (token.type != T.EOF)
-      decls ~= parseDeclarationDefinition();
-    return decls;
-  }
-
-  /*
-    DeclDefsBlock:
-        { }
-        { DeclDefs }
-  */
-  Declarations parseDeclarationDefinitionsBlock()
-  {
-    auto decls = new Declarations;
-    require(T.LBrace);
-    while (token.type != T.RBrace && token.type != T.EOF)
-      decls ~= parseDeclarationDefinition();
-    require(T.RBrace);
-    return decls;
-  }
-
-  Declaration parseDeclarationDefinition()
-  {
-    auto begin = token;
-    Declaration decl;
-    switch (token.type)
-    {
-    case T.Align,
-         T.Pragma,
-         // Protection attributes
-         T.Export,
-         T.Private,
-         T.Package,
-         T.Protected,
-         T.Public:
-      decl = parseAttributeSpecifier();
-      break;
-    // Storage classes
-    case T.Extern,
-         T.Deprecated,
-         T.Override,
-         T.Abstract,
-         T.Synchronized,
-         //T.Static,
-         T.Final,
-         T.Const,
-         //T.Invariant, // D 2.0
-         T.Auto,
-         T.Scope:
-    case_StaticAttribute:
-    case_InvariantAttribute: // D 2.0
-      decl = parseStorageAttribute();
-      break;
-    case T.Alias:
-      nT();
-      // TODO: parse StorageClasses?
-      decl = new AliasDeclaration(parseDeclaration());
-      break;
-    case T.Typedef:
-      nT();
-      // TODO: parse StorageClasses?
-      decl = new TypedefDeclaration(parseDeclaration());
-      break;
-    case T.Static:
-      switch (peekNext())
-      {
-      case T.Import:
-        goto case T.Import;
-      case T.This:
-        decl = parseStaticConstructorDeclaration();
-        break;
-      case T.Tilde:
-        decl = parseStaticDestructorDeclaration();
-        break;
-      case T.If:
-        decl = parseStaticIfDeclaration();
-        break;
-      case T.Assert:
-        decl = parseStaticAssertDeclaration();
-        break;
-      default:
-        goto case_StaticAttribute;
-      }
-      break;
-    case T.Import:
-      decl = parseImportDeclaration();
-      break;
-    case T.Enum:
-      decl = parseEnumDeclaration();
-      break;
-    case T.Class:
-      decl = parseClassDeclaration();
-      break;
-    case T.Interface:
-      decl = parseInterfaceDeclaration();
-      break;
-    case T.Struct, T.Union:
-      decl = parseAggregateDeclaration();
-      break;
-    case T.This:
-      decl = parseConstructorDeclaration();
-      break;
-    case T.Tilde:
-      decl = parseDestructorDeclaration();
-      break;
-    case T.Invariant:
-    version(D2)
-    {
-      auto next = token;
-      lx.peek(next);
-      if (next.type == T.LParen)
-      {
-        lx.peek(next);
-        if (next.type != T.RParen)
-          goto case_Declaration;
-      }
-      else
-        goto case_InvariantAttribute;
-    }
-      decl = parseInvariantDeclaration();
-      break;
-    case T.Unittest:
-      decl = parseUnittestDeclaration();
-      break;
-    case T.Debug:
-      decl = parseDebugDeclaration();
-      break;
-    case T.Version:
-      decl = parseVersionDeclaration();
-      break;
-    case T.Template:
-      decl = parseTemplateDeclaration();
-      break;
-    case T.New:
-      decl = parseNewDeclaration();
-      break;
-    case T.Delete:
-      decl = parseDeleteDeclaration();
-      break;
-    case T.Mixin:
-      decl = parseMixin!(MixinDeclaration)();
-      break;
-    case T.Semicolon:
-      nT();
-      decl = new EmptyDeclaration();
-      break;
-    // Declaration
-    case T.Identifier, T.Dot, T.Typeof:
-    // BasicType
-    case T.Char,   T.Wchar,   T.Dchar,  T.Bool,
-         T.Byte,   T.Ubyte,   T.Short,  T.Ushort,
-         T.Int,    T.Uint,    T.Long,   T.Ulong,
-         T.Float,  T.Double,  T.Real,
-         T.Ifloat, T.Idouble, T.Ireal,
-         T.Cfloat, T.Cdouble, T.Creal, T.Void:
-    case_Declaration:
-      decl = parseDeclaration();
-      break;
-    /+case T.Module:
-      // TODO: Error: module is optional and can appear only once at the top of the source file.
-      break;+/
-    default:
-      error(MID.ExpectedButFound, "Declaration", token.srcText);
-      decl = new IllegalDeclaration(token);
-      nT();
-    }
-//     writef("§%s§", decl.classinfo.name);
-    set(decl, begin);
-    return decl;
-  }
-
-  /*
-    DeclarationsBlock:
-        : DeclDefs
-        { }
-        { DeclDefs }
-        DeclDef
-  */
-  Declaration parseDeclarationsBlock()
-  {
-    Declaration d;
-    switch (token.type)
-    {
-    case T.LBrace:
-      d = parseDeclarationDefinitionsBlock();
-      break;
-    case T.Colon:
-      nT();
-      auto decls = new Declarations;
-      while (token.type != T.RBrace && token.type != T.EOF)
-        decls ~= parseDeclarationDefinition();
-      d = decls;
-      break;
-    default:
-      d = parseDeclarationDefinition();
-    }
-    return d;
-  }
-
-  Declaration parseDeclaration(StorageClass stc = StorageClass.None)
-  {
-    Type type;
-    Token* ident;
-
-    // Check for AutoDeclaration
-    if (stc != StorageClass.None &&
-        token.type == T.Identifier &&
-        peekNext() == T.Assign)
-    {
-      ident = token;
-      nT();
-    }
-    else
-    {
-      type = parseType();
-      ident = requireId();
-      // Type FunctionName ( ParameterList ) FunctionBody
-      if (token.type == T.LParen)
-      {
-        // It's a function declaration
-        TemplateParameters tparams;
-        if (tokenAfterParenIs(T.LParen))
-        {
-          // ( TemplateParameterList ) ( ParameterList )
-          tparams = parseTemplateParameterList();
-        }
-
-        auto params = parseParameterList();
-        // ReturnType FunctionName ( ParameterList )
-        auto funcBody = parseFunctionBody();
-        return new FunctionDeclaration(type, ident, tparams, params, funcBody);
-      }
-      type = parseDeclaratorSuffix(type);
-    }
-
-    // It's a variable declaration.
-    Token*[] 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();
-    LenterLoop:
-      if (token.type == T.Assign)
-      {
-        nT();
-        values ~= parseInitializer();
-      }
-      else
-        values ~= null;
-    }
-    require(T.Semicolon);
-    return new VariableDeclaration(type, idents, values);
-  }
-
-  Expression parseInitializer()
-  {
-    if (token.type == T.Void)
-    {
-      auto begin = token;
-      auto next = peekNext();
-      if (next == T.Comma || next == T.Semicolon)
-      {
-        nT();
-        return set(new VoidInitializer(), begin);
-      }
-    }
-    return parseNonVoidInitializer();
-  }
-
-  Expression parseNonVoidInitializer()
-  {
-    auto begin = token;
-    Expression init;
-    switch (token.type)
-    {
-    case T.LBracket:
-      // ArrayInitializer:
-      //         [ ]
-      //         [ ArrayMemberInitializations ]
-      Expression[] keys;
-      Expression[] values;
-
-      nT();
-      while (token.type != T.RBracket)
-      {
-        auto e = parseNonVoidInitializer();
-        if (token.type == T.Colon)
-        {
-          nT();
-          keys ~= e;
-          values ~= parseNonVoidInitializer();
-        }
-        else
-        {
-          keys ~= null;
-          values ~= e;
-        }
-
-        if (token.type != T.Comma)
-          break;
-        nT();
-      }
-      require(T.RBracket);
-      init = new ArrayInitializer(keys, values);
-      break;
-    case T.LBrace:
-      // StructInitializer:
-      //         { }
-      //         { StructMemberInitializers }
-      Expression parseStructInitializer()
-      {
-        Token*[] idents;
-        Expression[] values;
-
-        nT();
-        while (token.type != T.RBrace)
-        {
-          if (token.type == T.Identifier)
-          {
-            // Peek for colon to see if this is a member identifier.
-            if (peekNext() == T.Colon)
-            {
-              idents ~= token;
-              nT();
-              nT();
-            }
-          }
-          // NonVoidInitializer
-          values ~= parseNonVoidInitializer();
-
-          if (token.type != T.Comma)
-            break;
-          nT();
-        }
-        require(T.RBrace);
-        return new StructInitializer(idents, values);
-      }
-
-      bool success;
-      auto si = try_(parseStructInitializer(), success);
-      if (success)
-      {
-        init = si;
-        break;
-      }
-      assert(token.type == T.LBrace);
-      //goto default;
-    default:
-      init = parseAssignExpression();
-    }
-    set(init, begin);
-    return init;
-  }
-
-  FunctionBody parseFunctionBody()
-  {
-    auto begin = token;
-    auto func = new FunctionBody;
-    while (1)
-    {
-      switch (token.type)
-      {
-      case T.LBrace:
-        func.funcBody = parseStatements();
-        break;
-      case T.Semicolon:
-        nT();
-        break;
-      case T.In:
-        //if (func.inBody)
-          // TODO: issue error msg.
-        nT();
-        func.inBody = parseStatements();
-        continue;
-      case T.Out:
-        //if (func.outBody)
-          // TODO: issue error msg.
-        nT();
-        if (token.type == T.LParen)
-        {
-          nT();
-          func.outIdent = requireId();
-          require(T.RParen);
-        }
-        func.outBody = parseStatements();
-        continue;
-      case T.Body:
-        nT();
-        goto case T.LBrace;
-      default:
-        error(MID.ExpectedButFound, "FunctionBody", token.srcText);
-      }
-      break; // exit while loop
-    }
-    set(func, begin);
-    func.finishConstruction();
-    return func;
-  }
-
-  Declaration parseStorageAttribute()
-  {
-    StorageClass stc, tmp;
-
-    void addStorageClass()
-    {
-      if (stc & tmp)
-      {
-        error(MID.RedundantStorageClass, token.srcText);
-      }
-      else
-        stc |= tmp;
-    }
-
-    Declaration parse()
-    {
-      Declaration decl;
-      switch (token.type)
-      {
-      case T.Extern:
-        tmp = StorageClass.Extern;
-        addStorageClass();
-        nT();
-        Linkage linkage;
-        if (token.type == T.LParen)
-        {
-          nT();
-          auto ident = requireId();
-          switch (ident ? ident.identifier : null)
-          {
-          case "C":
-            if (token.type == T.PlusPlus)
-            {
-              nT();
-              linkage = Linkage.Cpp;
-              break;
-            }
-            linkage = Linkage.C;
-            break;
-          case "D":
-            linkage = Linkage.D;
-            break;
-          case "Windows":
-            linkage = Linkage.Windows;
-            break;
-          case "Pascal":
-            linkage = Linkage.Pascal;
-            break;
-          case "System":
-            linkage = Linkage.System;
-            break;
-          default:
-            // TODO: issue error msg. Unrecognized LinkageType.
-          }
-          require(T.RParen);
-        }
-        decl = new ExternDeclaration(linkage, parse());
-        break;
-      case T.Override:
-        tmp = StorageClass.Override;
-        goto Lcommon;
-      case T.Deprecated:
-        tmp = StorageClass.Deprecated;
-        goto Lcommon;
-      case T.Abstract:
-        tmp = StorageClass.Abstract;
-        goto Lcommon;
-      case T.Synchronized:
-        tmp = StorageClass.Synchronized;
-        goto Lcommon;
-      case T.Static:
-        tmp = StorageClass.Static;
-        goto Lcommon;
-      case T.Final:
-        tmp = StorageClass.Final;
-        goto Lcommon;
-      case T.Const:
-      version(D2)
-      {
-        if (peekNext() == T.LParen)
-          goto case_Declaration;
-      }
-        tmp = StorageClass.Const;
-        goto Lcommon;
-      version(D2)
-      {
-      case T.Invariant: // D 2.0
-        if (peekNext() == T.LParen)
-          goto case_Declaration;
-        tmp = StorageClass.Invariant;
-        goto Lcommon;
-      }
-      case T.Auto:
-        tmp = StorageClass.Auto;
-        goto Lcommon;
-      case T.Scope:
-        tmp = StorageClass.Scope;
-        goto Lcommon;
-      Lcommon:
-        addStorageClass();
-        auto tok = token.type;
-        nT();
-        decl = new AttributeDeclaration(tok, parse());
-        break;
-      case T.Identifier:
-      case_Declaration:
-        // This could be a normal Declaration or an AutoDeclaration
-        decl = parseDeclaration(stc);
-        break;
-      default:
-        decl = parseDeclarationsBlock();
-      }
-      return decl;
-    }
-    return parse();
-  }
-
-  Token* parseAlignAttribute()
-  {
-    assert(token.type == T.Align);
-    nT(); // Skip align keyword.
-    Token* tok;
-    if (token.type == T.LParen)
-    {
-      nT();
-      if (token.type == T.Int32)
-      {
-        tok = token;
-        nT();
-      }
-      else
-        expected(T.Int32);
-      require(T.RParen);
-    }
-    return tok;
-  }
-
-  Declaration parseAttributeSpecifier()
-  {
-    Declaration decl;
-
-    switch (token.type)
-    {
-    case T.Align:
-      int size = -1;
-      auto intTok = parseAlignAttribute();
-      if (intTok)
-        size = intTok.int_;
-      decl = new AlignDeclaration(size, parseDeclarationsBlock());
-      break;
-    case T.Pragma:
-      // Pragma:
-      //     pragma ( Identifier )
-      //     pragma ( Identifier , ExpressionList )
-      // ExpressionList:
-      //     AssignExpression
-      //     AssignExpression , ExpressionList
-      nT();
-      Token* ident;
-      Expression[] args;
-      Declaration decls;
-
-      require(T.LParen);
-      ident = requireId();
-
-      if (token.type == T.Comma)
-      {
-        // Parse at least one argument.
-        nT();
-        args ~= parseAssignExpression();
-      }
-
-      if (token.type == T.Comma)
-        args ~= parseArguments(T.RParen);
-      else
-        require(T.RParen);
-
-      if (token.type == T.Semicolon)
-      {
-        nT();
-        decls = new EmptyDeclaration();
-      }
-      else
-        decls = parseDeclarationsBlock();
-
-      decl = new PragmaDeclaration(ident, args, decls);
-      break;
-    // Protection attributes
-    case T.Private:
-    case T.Package:
-    case T.Protected:
-    case T.Public:
-    case T.Export:
-      auto tok = token.type;
-      nT();
-      decl = new AttributeDeclaration(tok, parseDeclarationsBlock());
-      break;
-    default:
-      assert(0);
-    }
-    return decl;
-  }
-
-  Declaration parseImportDeclaration()
-  {
-    assert(token.type == T.Import || token.type == T.Static);
-
-    bool isStatic;
-
-    if (token.type == T.Static)
-    {
-      isStatic = true;
-      nT();
-    }
-
-    ModuleName[] moduleNames;
-    Token*[] moduleAliases;
-    Token*[] bindNames;
-    Token*[] bindAliases;
-
-    nT(); // Skip import keyword.
-    while (1)
-    {
-      ModuleName moduleName;
-      Token* moduleAlias;
-
-      moduleAlias = requireId();
-
-      // AliasName = ModuleName
-      if (token.type == T.Assign)
-      {
-        nT();
-        moduleName ~= requireId();
-      }
-      else // import Identifier [^=]
-      {
-        moduleName ~= moduleAlias;
-        moduleAlias = null;
-      }
-
-      // Identifier(.Identifier)*
-      while (token.type == T.Dot)
-      {
-        nT();
-        moduleName ~= requireId();
-      }
-
-      // Push identifiers.
-      moduleNames ~= moduleName;
-      moduleAliases ~= moduleAlias;
-
-      if (token.type == T.Colon)
-        break;
-      if (token.type != T.Comma)
-        break;
-      nT();
-    }
-
-    if (token.type == T.Colon)
-    {
-      // BindAlias = BindName(, BindAlias = BindName)*;
-      // BindName(, BindName)*;
-      Token* bindName, bindAlias;
-      do
-      {
-        nT();
-        bindAlias = requireId();
-
-        if (token.type == T.Assign)
-        {
-          nT();
-          bindName = requireId();
-        }
-        else
-        {
-          bindName = bindAlias;
-          bindAlias = null;
-        }
-
-        // Push identifiers.
-        bindNames ~= bindName;
-        bindAliases ~= bindAlias;
-      } while (token.type == T.Comma)
-    }
-
-    require(T.Semicolon);
-
-    return new ImportDeclaration(moduleNames, moduleAliases, bindNames, bindAliases);
-  }
-
-  Declaration parseEnumDeclaration()
-  {
-    assert(token.type == T.Enum);
-
-    Token* enumName;
-    Type baseType;
-    Token*[] members;
-    Expression[] values;
-    bool hasBody;
-
-    nT(); // Skip enum keyword.
-
-    if (token.type == T.Identifier)
-    {
-      enumName = token;
-      nT();
-    }
-
-    if (token.type == T.Colon)
-    {
-      nT();
-      baseType = parseBasicType();
-    }
-
-    if (token.type == T.Semicolon)
-    {
-      if (enumName is null)
-        expected(T.Identifier);
-      nT();
-    }
-    else if (token.type == T.LBrace)
-    {
-      hasBody = true;
-      nT();
-      do
-      {
-        members ~= requireId();
-
-        if (token.type == T.Assign)
-        {
-          nT();
-          values ~= parseAssignExpression();
-        }
-        else
-          values ~= null;
-
-        if (token.type == T.Comma)
-          nT();
-        else if (token.type != T.RBrace)
-        {
-          expected(T.RBrace);
-          break;
-        }
-      } while (token.type != T.RBrace)
-      nT();
-    }
-    else
-      error(MID.ExpectedButFound, "enum declaration", token.srcText);
-
-    return new EnumDeclaration(enumName, baseType, members, values, hasBody);
-  }
-
-  Declaration parseClassDeclaration()
-  {
-    assert(token.type == T.Class);
-
-    Token* className;
-    TemplateParameters tparams;
-    BaseClass[] bases;
-    Declarations decls;
-    bool hasBody;
-
-    nT(); // Skip class keyword.
-    className = requireId();
-
-    if (token.type == T.LParen)
-    {
-      tparams = parseTemplateParameterList();
-    }
-
-    if (token.type == T.Colon)
-      bases = parseBaseClasses();
-
-    if (token.type == T.Semicolon)
-    {
-      //if (bases.length != 0)
-        // TODO: Error: bases classes are not allowed in forward declarations.
-      nT();
-    }
-    else if (token.type == T.LBrace)
-    {
-      hasBody = true;
-      // TODO: think about setting a member status variable to a flag InClassBody... this way we can check for DeclDefs that are illegal in class bodies in the parsing phase.
-      decls = parseDeclarationDefinitionsBlock();
-    }
-    else
-      expected(T.LBrace); // TODO: better error msg
-
-    return new ClassDeclaration(className, tparams, bases, decls, hasBody);
-  }
-
-  BaseClass[] parseBaseClasses(bool colonLeadsOff = true)
-  {
-    if (colonLeadsOff)
-    {
-      assert(token.type == T.Colon);
-      nT(); // Skip colon
-    }
-
-    BaseClass[] bases;
-
-    while (1)
-    {
-      Protection prot = Protection.Public;
-      switch (token.type)
-      {
-      case T.Identifier, T.Dot, T.Typeof: goto LparseBasicType;
-      case T.Private:   prot = Protection.Private;   break;
-      case T.Protected: prot = Protection.Protected; break;
-      case T.Package:   prot = Protection.Package;   break;
-      case T.Public:  /*prot = Protection.Public;*/  break;
-      default:
-        // TODO: issue error msg
-        return bases;
-      }
-      nT(); // Skip protection attribute.
-    LparseBasicType:
-      auto type = parseBasicType();
-      //if (type.tid != TID.DotList)
-        // TODO: issue error msg. base classes can only be one or more identifiers or template instances separated by dots.
-      bases ~= new BaseClass(prot, type);
-      if (token.type != T.Comma)
-        break;
-    }
-    return bases;
-  }
-
-  Declaration parseInterfaceDeclaration()
-  {
-    assert(token.type == T.Interface);
-
-    Token* name;
-    TemplateParameters tparams;
-    BaseClass[] bases;
-    Declarations decls;
-    bool hasBody;
-
-    nT(); // Skip interface keyword.
-    name = requireId();
-
-    if (token.type == T.LParen)
-    {
-      tparams = parseTemplateParameterList();
-    }
-
-    if (token.type == T.Colon)
-      bases = parseBaseClasses();
-
-    if (token.type == T.Semicolon)
-    {
-      //if (bases.length != 0)
-        // TODO: error: base classes are not allowed in forward declarations.
-      nT();
-    }
-    else if (token.type == T.LBrace)
-    {
-      hasBody = true;
-      decls = parseDeclarationDefinitionsBlock();
-    }
-    else
-      expected(T.LBrace); // TODO: better error msg
-
-    return new InterfaceDeclaration(name, tparams, bases, decls, hasBody);
-  }
-
-  Declaration parseAggregateDeclaration()
-  {
-    assert(token.type == T.Struct || token.type == T.Union);
-
-    TOK tok = token.type;
-
-    Token* name;
-    TemplateParameters tparams;
-    Declarations decls;
-    bool hasBody;
-
-    nT(); // Skip struct or union keyword.
-    // name is optional.
-    if (token.type == T.Identifier)
-    {
-      name = token;
-      nT();
-      if (token.type == T.LParen)
-      {
-        tparams = parseTemplateParameterList();
-      }
-    }
-
-    if (token.type == T.Semicolon)
-    {
-      //if (name.length == 0)
-        // TODO: error: forward declarations must have a name.
-      nT();
-    }
-    else if (token.type == T.LBrace)
-    {
-      hasBody = true;
-      decls = parseDeclarationDefinitionsBlock();
-    }
-    else
-      expected(T.LBrace); // TODO: better error msg
-
-    if (tok == T.Struct)
-      return new StructDeclaration(name, tparams, decls, hasBody);
-    else
-      return new UnionDeclaration(name, tparams, decls, hasBody);
-  }
-
-  Declaration parseConstructorDeclaration()
-  {
-    assert(token.type == T.This);
-    nT(); // Skip 'this' keyword.
-    auto parameters = parseParameterList();
-    auto funcBody = parseFunctionBody();
-    return new ConstructorDeclaration(parameters, funcBody);
-  }
-
-  Declaration parseDestructorDeclaration()
-  {
-    assert(token.type == T.Tilde);
-    nT(); // Skip ~
-    require(T.This);
-    require(T.LParen);
-    require(T.RParen);
-    auto funcBody = parseFunctionBody();
-    return new DestructorDeclaration(funcBody);
-  }
-
-  Declaration parseStaticConstructorDeclaration()
-  {
-    assert(token.type == T.Static);
-    nT(); // Skip static keyword.
-    nT(); // Skip 'this' keyword.
-    require(T.LParen);
-    require(T.RParen);
-    auto funcBody = parseFunctionBody();
-    return new StaticConstructorDeclaration(funcBody);
-  }
-
-  Declaration parseStaticDestructorDeclaration()
-  {
-    assert(token.type == T.Static);
-    nT(); // Skip static keyword.
-    nT(); // Skip ~
-    require(T.This);
-    require(T.LParen);
-    require(T.RParen);
-    auto funcBody = parseFunctionBody();
-    return new StaticDestructorDeclaration(funcBody);
-  }
-
-  Declaration parseInvariantDeclaration()
-  {
-    assert(token.type == T.Invariant);
-    nT(); // Skip invariant keyword.
-    // Optional () for getting ready porting to D 2.0
-    if (token.type == T.LParen)
-      requireNext(T.RParen);
-    auto funcBody = parseFunctionBody();
-    return new InvariantDeclaration(funcBody);
-  }
-
-  Declaration parseUnittestDeclaration()
-  {
-    assert(token.type == T.Unittest);
-
-    nT(); // Skip unittest keyword.
-    auto funcBody = parseFunctionBody();
-    return new UnittestDeclaration(funcBody);
-  }
-
-  Declaration parseDebugDeclaration()
-  {
-    assert(token.type == T.Debug);
-
-    nT(); // Skip debug keyword.
-
-    Token* spec; // debug = Integer ;
-                 // debug = Identifier ;
-    Token* cond; // debug ( Integer )
-                 // debug ( Identifier )
-    Declaration decls, elseDecls;
-
-    void parseIdentOrInt(ref Token* tok)
-    {
-      nT();
-      if (token.type == T.Int32 ||
-          token.type == T.Identifier)
-      {
-        tok = token;
-        nT();
-      }
-      else
-        expected(T.Identifier); // TODO: better error msg
-    }
-
-    if (token.type == T.Assign)
-    {
-      parseIdentOrInt(spec);
-      require(T.Semicolon);
-    }
-    else
-    {
-      // Condition:
-      //     Integer
-      //     Identifier
-      // ( Condition )
-      if (token.type == T.LParen)
-      {
-        parseIdentOrInt(cond);
-        require(T.RParen);
-      }
-
-      // debug DeclarationsBlock
-      // debug ( Condition ) DeclarationsBlock
-      decls = parseDeclarationsBlock();
-
-      // else DeclarationsBlock
-      if (token.type == T.Else)
-      {
-        nT();
-        //if (token.type == T.Colon)
-          // TODO: avoid "else:"?
-        elseDecls = parseDeclarationsBlock();
-      }
-    }
-
-    return new DebugDeclaration(spec, cond, decls, elseDecls);
-  }
-
-  Declaration parseVersionDeclaration()
-  {
-    assert(token.type == T.Version);
-
-    nT(); // Skip version keyword.
-
-    Token* spec; // version = Integer ;
-                 // version = Identifier ;
-    Token* cond; // version ( Integer )
-                 // version ( Identifier )
-    Declaration decls, elseDecls;
-
-    void parseIdentOrInt(ref Token* tok)
-    {
-      if (token.type == T.Int32 ||
-          token.type == T.Identifier)
-      {
-        tok = token;
-        nT();
-      }
-      else
-        expected(T.Identifier); // TODO: better error msg
-    }
-
-    if (token.type == T.Assign)
-    {
-      nT();
-      parseIdentOrInt(spec);
-      require(T.Semicolon);
-    }
-    else
-    {
-      // Condition:
-      //     Integer
-      //     Identifier
-
-      // ( Condition )
-      require(T.LParen);
-      parseIdentOrInt(cond);
-      require(T.RParen);
-
-      // version ( Condition ) DeclarationsBlock
-      decls = parseDeclarationsBlock();
-
-      // else DeclarationsBlock
-      if (token.type == T.Else)
-      {
-        nT();
-        //if (token.type == T.Colon)
-          // TODO: avoid "else:"?
-        elseDecls = parseDeclarationsBlock();
-      }
-    }
-
-    return new VersionDeclaration(spec, cond, decls, elseDecls);
-  }
-
-  Declaration parseStaticIfDeclaration()
-  {
-    assert(token.type == T.Static);
-
-    nT(); // Skip static keyword.
-    nT(); // Skip if keyword.
-
-    Expression condition;
-    Declaration ifDecls, elseDecls;
-
-    require(T.LParen);
-    condition = parseAssignExpression();
-    require(T.RParen);
-
-    if (token.type != T.Colon)
-      ifDecls = parseDeclarationsBlock();
-    else
-      expected(T.LBrace); // TODO: better error msg
-
-    if (token.type == T.Else)
-    {
-      nT();
-      if (token.type != T.Colon)
-        elseDecls = parseDeclarationsBlock();
-      else
-        expected(T.LBrace); // TODO: better error msg
-    }
-
-    return new StaticIfDeclaration(condition, ifDecls, elseDecls);
-  }
-
-  Declaration parseStaticAssertDeclaration()
-  {
-    assert(token.type == T.Static);
-
-    nT(); // Skip static keyword.
-    nT(); // Skip assert keyword.
-
-    Expression condition, message;
-
-    require(T.LParen);
-
-    condition = parseAssignExpression();
-
-    if (token.type == T.Comma)
-    {
-      nT();
-      message = parseAssignExpression();
-    }
-
-    require(T.RParen);
-    require(T.Semicolon);
-
-    return new StaticAssertDeclaration(condition, message);
-  }
-
-  Declaration parseTemplateDeclaration()
-  {
-    assert(token.type == T.Template);
-    nT(); // Skip template keyword.
-    auto templateName = requireId();
-    auto templateParams = parseTemplateParameterList();
-    auto decls = parseDeclarationDefinitionsBlock();
-    return new TemplateDeclaration(templateName, templateParams, decls);
-  }
-
-  Declaration parseNewDeclaration()
-  {
-    assert(token.type == T.New);
-    nT(); // Skip new keyword.
-    auto parameters = parseParameterList();
-    auto funcBody = parseFunctionBody();
-    return new NewDeclaration(parameters, funcBody);
-  }
-
-  Declaration parseDeleteDeclaration()
-  {
-    assert(token.type == T.Delete);
-    nT(); // Skip delete keyword.
-    auto parameters = parseParameterList();
-    // TODO: only one parameter of type void* allowed. Check in parsing or semantic phase?
-    auto funcBody = parseFunctionBody();
-    return new DeleteDeclaration(parameters, funcBody);
-  }
-
-  /+
-    DotListExpression:
-            . DotListItems
-            DotListItems
-            Typeof
-            Typeof . DotListItems
-    DotListItems:
-            DotListItem
-            DotListItem . DotListItems
-    DotListItem:
-            Identifier
-            TemplateInstance
-            NewExpression
-    TemplateInstance:
-            Identifier !( TemplateArguments )
-  +/
-  DotListExpression parseDotListExpression()
-  {
-    assert(token.type == T.Identifier || token.type == T.Dot || token.type == T.Typeof);
-    Expression[] identList;
-    if (token.type == T.Dot)
-    {
-      identList ~= new IdentifierExpression(token);
-      nT();
-    }
-    else if (token.type == T.Typeof)
-    {
-      requireNext(T.LParen);
-      auto type = new TypeofType(parseExpression());
-      require(T.RParen);
-      identList ~= new TypeofExpression(type);
-      if (token.type != T.Dot)
-        goto Lreturn;
-      nT();
-    }
-
-    while (1)
-    {
-      auto begin2 = token;
-      auto ident = requireId();
-      Expression e;
-      if (token.type == T.Not && peekNext() == T.LParen) // Identifier !( TemplateArguments )
-      {
-        nT(); // Skip !.
-        e = set(new TemplateInstanceExpression(ident, parseTemplateArguments()), begin2);
-      }
-      else // Identifier
-        e = set(new IdentifierExpression(ident), begin2);
-
-      identList ~= e;
-
-    LnewExpressionLoop:
-      if (token.type != T.Dot)
-        break;
-      nT(); // Skip dot.
-
-      if (token.type == T.New)
-      {
-        identList ~= parseNewExpression();
-        goto LnewExpressionLoop;
-      }
-    }
-
-  Lreturn:
-    return new DotListExpression(identList);
-  }
-
-  /+
-    DotListType:
-            . TypeItems
-            TypeItems
-            Typeof
-            Typeof . TypeItems
-    TypeItems:
-            TypeItem
-            TypeItem . TypeItems
-    TypeItem:
-            Identifier
-            TemplateInstance
-    TemplateInstance:
-            Identifier !( TemplateArguments )
-  +/
-  DotListType parseDotListType()
-  {
-    Type[] identList;
-    if (token.type == T.Dot)
-    {
-      identList ~= new IdentifierType(token);
-      nT();
-    }
-    else if (token.type == T.Typeof)
-    {
-      requireNext(T.LParen);
-      identList ~= new TypeofType(parseExpression());
-      require(T.RParen);
-      if (token.type != T.Dot)
-        goto Lreturn;
-      nT();
-    }
-
-    while (1)
-    {
-      auto begin2 = token;
-      auto ident = requireId();
-      // 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()), begin2);
-      }
-      else // Identifier
-        identList ~= set(new IdentifierType(ident), begin2);
-
-      if (token.type != T.Dot)
-        break;
-      nT();
-    }
-  Lreturn:
-    return new DotListType(identList);
-  }
-
-  /*
-    TemplateMixin:
-            mixin ( AssignExpression ) ;
-            mixin TemplateIdentifier ;
-            mixin TemplateIdentifier MixinIdentifier ;
-            mixin TemplateIdentifier !( TemplateArguments ) ;
-            mixin TemplateIdentifier !( TemplateArguments ) MixinIdentifier ;
-  */
-  Class parseMixin(Class)()
-  {
-    assert(token.type == T.Mixin);
-    auto begin = token;
-    nT(); // Skip mixin keyword.
-
-  static if (is(Class == MixinDeclaration))
-  {
-    if (token.type == T.LParen)
-    {
-      // TODO: What about mixin(...).ident;?
-      nT();
-      auto e = parseAssignExpression();
-      require(T.RParen);
-      require(T.Semicolon);
-      return new MixinDeclaration(e);
-    }
-  }
-
-    Expression[] templateIdent;
-    Token* mixinIdent;
-
-    // This code is similar to parseDotListType().
-    if (token.type == T.Dot)
-    {
-      templateIdent ~= new IdentifierExpression(token);
-      nT();
-    }
-
-    while (1)
-    {
-      auto ident = requireId();
-      Expression e;
-      if (token.type == T.Not) // Identifier !( TemplateArguments )
-      {
-        // No need to peek for T.LParen. This must be a template instance.
-        nT();
-        e = new TemplateInstanceExpression(ident, parseTemplateArguments());
-      }
-      else // Identifier
-        e = new IdentifierExpression(ident);
-
-      templateIdent ~= e;
-
-      if (token.type != T.Dot)
-        break;
-      nT();
-    }
-
-    if (token.type == T.Identifier)
-    {
-      mixinIdent = token;
-      nT();
-    }
-
-    require(T.Semicolon);
-
-    return new Class(templateIdent, mixinIdent);
-  }
-
-  /+++++++++++++++++++++++++++++
-  + Statement parsing methods  +
-  +++++++++++++++++++++++++++++/
-
-  Statements parseStatements()
-  {
-    auto begin = token;
-    require(T.LBrace);
-    auto statements = new Statements();
-    while (token.type != T.RBrace && token.type != T.EOF)
-      statements ~= parseStatement();
-    require(T.RBrace);
-    return set(statements, begin);
-  }
-
-  Statement parseStatement()
-  {
-// writefln("°parseStatement:(%d)token='%s'°", lx.loc, token.srcText);
-    auto begin = token;
-    Statement s;
-    Declaration d;
-    switch (token.type)
-    {
-    case T.Align:
-      int size = -1;
-      auto intTok = parseAlignAttribute();
-      if (intTok)
-        size = intTok.int_;
-      // Restrict align attribute to structs in parsing phase.
-      Declaration structDecl;
-      if (token.type == T.Struct)
-        structDecl = parseAggregateDeclaration();
-      else
-        expected(T.Struct);
-      d = new AlignDeclaration(size, structDecl ? structDecl : new Declarations);
-      goto case_DeclarationStatement;
-/+ Not applicable for statements.
-//          T.Private,
-//          T.Package,
-//          T.Protected,
-//          T.Public,
-//          T.Export,
-//          T.Deprecated,
-//          T.Override,
-//          T.Abstract,
-+/
-    case T.Extern,
-         T.Final,
-         T.Const,
-         T.Auto:
-         //T.Scope
-         //T.Static
-    case_parseAttribute:
-      s = parseAttributeStatement();
-      return s;
-    case T.Identifier:
-      if (peekNext() == T.Colon)
-      {
-        auto ident = token;
-        nT(); // Skip Identifier
-        nT(); // Skip :
-        s = new LabeledStatement(ident, parseNoScopeOrEmptyStatement());
-        break;
-      }
-      goto case T.Dot;
-    case T.Dot, T.Typeof:
-      bool success;
-      d = try_(parseDeclaration(), success);
-      if (success)
-        goto case_DeclarationStatement; // Declaration
-      else
-        goto default; // Expression
-    // BasicType
-    case T.Char,   T.Wchar,   T.Dchar,  T.Bool,
-         T.Byte,   T.Ubyte,   T.Short,  T.Ushort,
-         T.Int,    T.Uint,    T.Long,   T.Ulong,
-         T.Float,  T.Double,  T.Real,
-         T.Ifloat, T.Idouble, T.Ireal,
-         T.Cfloat, T.Cdouble, T.Creal, T.Void:
-    case_parseDeclaration:
-      d = parseDeclaration();
-      goto case_DeclarationStatement;
-    case T.If:
-      s = parseIfStatement();
-      break;
-    case T.While:
-      s = parseWhileStatement();
-      break;
-    case T.Do:
-      s = parseDoWhileStatement();
-      break;
-    case T.For:
-      s = parseForStatement();
-      break;
-    case T.Foreach, T.Foreach_reverse:
-      s = parseForeachStatement();
-      break;
-    case T.Switch:
-      s = parseSwitchStatement();
-      break;
-    case T.Case:
-      s = parseCaseStatement();
-      break;
-    case T.Default:
-      s = parseDefaultStatement();
-      break;
-    case T.Continue:
-      s = parseContinueStatement();
-      break;
-    case T.Break:
-      s = parseBreakStatement();
-      break;
-    case T.Return:
-      s = parseReturnStatement();
-      break;
-    case T.Goto:
-      s = parseGotoStatement();
-      break;
-    case T.With:
-      s = parseWithStatement();
-      break;
-    case T.Synchronized:
-      s = parseSynchronizedStatement();
-      break;
-    case T.Try:
-      s = parseTryStatement();
-      break;
-    case T.Throw:
-      s = parseThrowStatement();
-      break;
-    case T.Scope:
-      if (peekNext() != T.LParen)
-        goto case_parseAttribute;
-      s = parseScopeGuardStatement();
-      break;
-    case T.Volatile:
-      s = parseVolatileStatement();
-      break;
-    case T.Asm:
-      s = parseAsmStatement();
-      break;
-    case T.Pragma:
-      s = parsePragmaStatement();
-      break;
-    case T.Mixin:
-      if (peekNext() == T.LParen)
-        goto default; // Parse as expression.
-      s = parseMixin!(MixinStatement)();
-      break;
-    case T.Static:
-      switch (peekNext())
-      {
-      case T.If:
-        s = parseStaticIfStatement();
-        break;
-      case T.Assert:
-        s = parseStaticAssertStatement();
-        break;
-      default:
-        goto case_parseAttribute;
-      }
-      break;
-    case T.Debug:
-      s = parseDebugStatement();
-      break;
-    case T.Version:
-      s = parseVersionStatement();
-      break;
-    // DeclDef
-    case T.Alias, T.Typedef:
-      d = parseDeclarationDefinition();
-      goto case_DeclarationStatement;
-    case T.Enum:
-      d = parseEnumDeclaration();
-      goto case_DeclarationStatement;
-    case T.Class:
-      d = parseClassDeclaration();
-      goto case_DeclarationStatement;
-    case T.Interface:
-      d = parseInterfaceDeclaration();
-      goto case_DeclarationStatement;
-    case T.Struct, T.Union:
-      d = parseAggregateDeclaration();
-      goto case_DeclarationStatement;
-    case_DeclarationStatement:
-      set(d, begin);
-      s = new DeclarationStatement(d);
-      break;
-    case T.LBrace:
-      s = parseScopeStatement();
-      break;
-    case T.Semicolon:
-      nT();
-      s = new EmptyStatement();
-      break;
-    default:
-      bool success;
-      auto expression = try_(parseExpression(), success);
-// writefln("parseExpression()=", failed?"failed":"success");
-      if (success)
-      {
-        require(T.Semicolon);
-        s = new ExpressionStatement(expression);
-      }
-      else
-      {
-        error(MID.ExpectedButFound, "Statement", token.srcText);
-        s = new IllegalStatement(token);
-        nT();
-      }
-    }
-    assert(s !is null);
-//     writef("§%s§", s.classinfo.name);
-    set(s, begin);
-    return s;
-  }
-
-  /+
-    ScopeStatement:
-        NoScopeStatement
-  +/
-  Statement parseScopeStatement()
-  {
-    return new ScopeStatement(parseNoScopeStatement());
-  }
-
-  /+
-    NoScopeStatement:
-        NonEmptyStatement
-        BlockStatement
-    BlockStatement:
-        { }
-        { StatementList }
-  +/
-  Statement parseNoScopeStatement()
-  {
-    Statement s;
-    if (token.type == T.LBrace)
-    {
-      nT();
-      auto ss = new Statements();
-      while (token.type != T.RBrace && token.type != T.EOF)
-        ss ~= parseStatement();
-      require(T.RBrace);
-      s = ss;
-    }
-    else if (token.type == T.Semicolon)
-    {
-      error(MID.ExpectedButFound, "non-empty statement", ";");
-      s = new EmptyStatement();
-      nT();
-    }
-    else
-      s = parseStatement();
-    return s;
-  }
-
-  /+
-    NoScopeOrEmptyStatement:
-        ;
-        NoScopeStatement
-  +/
-  Statement parseNoScopeOrEmptyStatement()
-  {
-    if (token.type == T.Semicolon)
-    {
-      nT();
-      return new EmptyStatement();
-    }
-    else
-      return parseNoScopeStatement();
-  }
-
-  Statement parseAttributeStatement()
-  {
-    StorageClass stc, tmp;
-
-    void addStorageClass()
-    {
-      if (stc & tmp)
-      {
-        error(MID.RedundantStorageClass, token.srcText);
-      }
-      else
-        stc |= tmp;
-    }
-
-    Statement parse()
-    {
-      auto begin = token;
-      Statement s;
-      switch (token.type)
-      {
-      case T.Extern:
-        tmp = StorageClass.Extern;
-        addStorageClass();
-        nT();
-        Linkage linkage;
-        if (token.type == T.LParen)
-        {
-          nT();
-          auto ident = requireId();
-          switch (ident ? ident.identifier : null)
-          {
-          case "C":
-            if (token.type == T.PlusPlus)
-            {
-              nT();
-              linkage = Linkage.Cpp;
-              break;
-            }
-            linkage = Linkage.C;
-            break;
-          case "D":
-            linkage = Linkage.D;
-            break;
-          case "Windows":
-            linkage = Linkage.Windows;
-            break;
-          case "Pascal":
-            linkage = Linkage.Pascal;
-            break;
-          case "System":
-            linkage = Linkage.System;
-            break;
-          default:
-            // TODO: issue error msg. Unrecognized LinkageType.
-          }
-          require(T.RParen);
-        }
-        s = new ExternStatement(linkage, parse());
-        break;
-      case T.Static:
-        tmp = StorageClass.Static;
-        goto Lcommon;
-      case T.Final:
-        tmp = StorageClass.Final;
-        goto Lcommon;
-      case T.Const:
-      version(D2)
-      {
-        if (peekNext() == T.LParen)
-          goto case_Declaration;
-      }
-        tmp = StorageClass.Const;
-        goto Lcommon;
-      version(D2)
-      {
-      case T.Invariant: // D 2.0
-        if (peekNext() == T.LParen)
-          goto case_Declaration;
-        tmp = StorageClass.Invariant;
-        goto Lcommon;
-      }
-      case T.Auto:
-        tmp = StorageClass.Auto;
-        goto Lcommon;
-      case T.Scope:
-        tmp = StorageClass.Scope;
-        goto Lcommon;
-      Lcommon:
-        addStorageClass();
-        auto tok = token.type;
-        nT();
-        s = new AttributeStatement(tok, parse());
-        break;
-      // TODO: allow "scope class", "abstract scope class" in function bodies?
-      //case T.Class:
-      default:
-      case_Declaration:
-        s = new DeclarationStatement(parseDeclaration(stc));
-      }
-      set(s, begin);
-      return s;
-    }
-    return parse();
-  }
-
-  Statement parseIfStatement()
-  {
-    assert(token.type == T.If);
-    nT();
-
-    Statement variable;
-    Expression condition;
-    Statement ifBody, elseBody;
-
-    require(T.LParen);
-
-    Token* ident;
-    // auto Identifier = Expression
-    if (token.type == T.Auto)
-    {
-      auto a = new AttributeStatement(token.type, null);
-      nT();
-      ident = requireId();
-      require(T.Assign);
-      auto init = parseExpression();
-      a.statement = new DeclarationStatement(new VariableDeclaration(null, [ident], [init]));
-      variable = a;
-    }
-    else
-    {
-      // Declarator = Expression
-      Type parseDeclaratorAssign()
-      {
-        auto type = parseDeclarator(ident);
-        require(T.Assign);
-        return type;
-      }
-      bool success;
-      auto type = try_(parseDeclaratorAssign(), success);
-      if (success)
-      {
-        auto init = parseExpression();
-        variable = new DeclarationStatement(new VariableDeclaration(type, [ident], [init]));
-      }
-      else
-        condition = parseExpression();
-    }
-    require(T.RParen);
-    ifBody = parseScopeStatement();
-    if (token.type == T.Else)
-    {
-      nT();
-      elseBody = parseScopeStatement();
-    }
-    return new IfStatement(variable, condition, ifBody, elseBody);
-  }
-
-  Statement parseWhileStatement()
-  {
-    assert(token.type == T.While);
-    nT();
-    require(T.LParen);
-    auto condition = parseExpression();
-    require(T.RParen);
-    return new WhileStatement(condition, parseScopeStatement());
-  }
-
-  Statement parseDoWhileStatement()
-  {
-    assert(token.type == T.Do);
-    nT();
-    auto doBody = parseScopeStatement();
-    require(T.While);
-    require(T.LParen);
-    auto condition = parseExpression();
-    require(T.RParen);
-    return new DoWhileStatement(condition, doBody);
-  }
-
-  Statement parseForStatement()
-  {
-    assert(token.type == T.For);
-    nT();
-    require(T.LParen);
-
-    Statement init, forBody;
-    Expression condition, increment;
-
-    if (token.type != T.Semicolon)
-      init = parseNoScopeStatement();
-    else
-      nT(); // Skip ;
-    if (token.type != T.Semicolon)
-      condition = parseExpression();
-    require(T.Semicolon);
-    if (token.type != T.RParen)
-      increment = parseExpression();
-    require(T.RParen);
-    forBody = parseScopeStatement();
-    return new ForStatement(init, condition, increment, forBody);
-  }
-
-  Statement parseForeachStatement()
-  {
-    assert(token.type == T.Foreach || token.type == T.Foreach_reverse);
-    TOK tok = token.type;
-    nT();
-
-    auto params = new Parameters;
-    Expression e; // Aggregate or LwrExpression
-
-    require(T.LParen);
-    while (1)
-    {
-      auto paramBegin = token;
-      Token* stcTok;
-      Type type;
-      Token* ident;
-
-      switch (token.type)
-      {
-      case T.Ref, T.Inout:
-        stcTok = token;
-        nT();
-        // fall through
-      case T.Identifier:
-        auto next = peekNext();
-        if (next == T.Comma || next == T.Semicolon || next == T.RParen)
-        {
-          ident = token;
-          nT();
-          break;
-        }
-        // fall through
-      default:
-        type = parseDeclarator(ident);
-      }
-
-      params ~= set(new Parameter(stcTok, type, ident, null), paramBegin);
-
-      if (token.type != T.Comma)
-        break;
-      nT();
-    }
-    require(T.Semicolon);
-    e = parseExpression();
-  version(D2)
-  { //Foreach (ForeachType; LwrExpression .. UprExpression ) ScopeStatement
-    if (token.type == T.Slice)
-    {
-      // if (params.length != 1)
-        // error(MID.XYZ); // TODO: issue error msg
-      nT();
-      auto upper = parseExpression();
-      require(T.RParen);
-      auto forBody = parseScopeStatement();
-      return new ForeachRangeStatement(tok, params, e, upper, forBody);
-    }
-  }
-    // Foreach (ForeachTypeList; Aggregate) ScopeStatement
-    require(T.RParen);
-    auto forBody = parseScopeStatement();
-    return new ForeachStatement(tok, params, e, forBody);
-  }
-
-  Statement parseSwitchStatement()
-  {
-    assert(token.type == T.Switch);
-    nT();
-
-    require(T.LParen);
-    auto condition = parseExpression();
-    require(T.RParen);
-    auto switchBody = parseScopeStatement();
-    return new SwitchStatement(condition, switchBody);
-  }
-
-  Statement parseCaseDefaultBody()
-  {
-    // This function is similar to parseNoScopeStatement()
-    auto s = new Statements();
-    while (token.type != T.Case &&
-            token.type != T.Default &&
-            token.type != T.RBrace &&
-            token.type != T.EOF)
-      s ~= parseStatement();
-    return new ScopeStatement(s);
-  }
-
-  Statement parseCaseStatement()
-  {
-    assert(token.type == T.Case);
-    // T.Case skipped in do-while.
-    Expression[] values;
-    do
-    {
-      nT();
-      values ~= parseAssignExpression();
-    } while (token.type == T.Comma)
-    require(T.Colon);
-
-    auto caseBody = parseCaseDefaultBody();
-    return new CaseStatement(values, caseBody);
-  }
-
-  Statement parseDefaultStatement()
-  {
-    assert(token.type == T.Default);
-    nT();
-    require(T.Colon);
-    return new DefaultStatement(parseCaseDefaultBody());
-  }
-
-  Statement parseContinueStatement()
-  {
-    assert(token.type == T.Continue);
-    nT();
-    Token* ident;
-    if (token.type == T.Identifier)
-    {
-      ident = token;
-      nT();
-    }
-    require(T.Semicolon);
-    return new ContinueStatement(ident);
-  }
-
-  Statement parseBreakStatement()
-  {
-    assert(token.type == T.Break);
-    nT();
-    Token* ident;
-    if (token.type == T.Identifier)
-    {
-      ident = token;
-      nT();
-    }
-    require(T.Semicolon);
-    return new BreakStatement(ident);
-  }
-
-  Statement parseReturnStatement()
-  {
-    assert(token.type == T.Return);
-    nT();
-    Expression expr;
-    if (token.type != T.Semicolon)
-      expr = parseExpression();
-    require(T.Semicolon);
-    return new ReturnStatement(expr);
-  }
-
-  Statement parseGotoStatement()
-  {
-    assert(token.type == T.Goto);
-    nT();
-    Token* ident;
-    Expression caseExpr;
-    switch (token.type)
-    {
-    case T.Case:
-      nT();
-      if (token.type == T.Semicolon)
-        break;
-      caseExpr = parseExpression();
-      break;
-    case T.Default:
-      nT();
-      break;
-    default:
-      ident = requireId();
-    }
-    require(T.Semicolon);
-    return new GotoStatement(ident, caseExpr);
-  }
-
-  Statement parseWithStatement()
-  {
-    assert(token.type == T.With);
-    nT();
-    require(T.LParen);
-    auto expr = parseExpression();
-    require(T.RParen);
-    return new WithStatement(expr, parseScopeStatement());
-  }
-
-  Statement parseSynchronizedStatement()
-  {
-    assert(token.type == T.Synchronized);
-    nT();
-    Expression expr;
-
-    if (token.type == T.LParen)
-    {
-      nT();
-      expr = parseExpression();
-      require(T.RParen);
-    }
-    return new SynchronizedStatement(expr, parseScopeStatement());
-  }
-
-  Statement parseTryStatement()
-  {
-    assert(token.type == T.Try);
-    nT();
-
-    auto tryBody = parseScopeStatement();
-    CatchBody[] catchBodies;
-    FinallyBody finBody;
-
-    while (token.type == T.Catch)
-    {
-      nT();
-      Parameter param;
-      if (token.type == T.LParen)
-      {
-        nT();
-        Token* ident;
-        auto type = parseDeclarator(ident);
-        param = new Parameter(null, type, ident, null);
-        require(T.RParen);
-      }
-      catchBodies ~= new CatchBody(param, parseNoScopeStatement());
-      if (param is null)
-        break; // This is a LastCatch
-    }
-
-    if (token.type == T.Finally)
-    {
-      nT();
-      finBody = new FinallyBody(parseNoScopeStatement());
-    }
-
-    if (catchBodies.length == 0 || finBody is null)
-    {
-      // TODO: issue error msg.
-    }
-
-    return new TryStatement(tryBody, catchBodies, finBody);
-  }
-
-  Statement parseThrowStatement()
-  {
-    assert(token.type == T.Throw);
-    nT();
-    auto expr = parseExpression();
-    require(T.Semicolon);
-    return new ThrowStatement(expr);
-  }
-
-  Statement parseScopeGuardStatement()
-  {
-    assert(token.type == T.Scope);
-    nT();
-    assert(token.type == T.LParen);
-    nT();
-
-    Token* condition = requireId();
-    if (condition)
-      switch (condition.identifier)
-      {
-      case "exit":
-      case "success":
-      case "failure":
-        break;
-      default:
-        // TODO: issue error msg.
-      }
-    require(T.RParen);
-    Statement scopeBody;
-    if (token.type == T.LBrace)
-      scopeBody = parseScopeStatement();
-    else
-      scopeBody = parseNoScopeStatement();
-    return new ScopeGuardStatement(condition, scopeBody);
-  }
-
-  Statement parseVolatileStatement()
-  {
-    assert(token.type == T.Volatile);
-    nT();
-    Statement volatileBody;
-    if (token.type == T.Semicolon)
-      nT();
-    else if (token.type == T.LBrace)
-      volatileBody = parseScopeStatement();
-    else
-      volatileBody = parseStatement();
-    return new VolatileStatement(volatileBody);
-  }
-
-  Statement parsePragmaStatement()
-  {
-    assert(token.type == T.Pragma);
-    nT();
-
-    Token* ident;
-    Expression[] args;
-    Statement pragmaBody;
-
-    require(T.LParen);
-    ident = requireId();
-
-    if (token.type == T.Comma)
-    {
-      // Parse at least one argument.
-      nT();
-      args ~= parseAssignExpression();
-    }
-
-    if (token.type == T.Comma)
-      args ~= parseArguments(T.RParen);
-    else
-      require(T.RParen);
-
-    pragmaBody = parseNoScopeOrEmptyStatement();
-
-    return new PragmaStatement(ident, args, pragmaBody);
-  }
-
-  Statement parseStaticIfStatement()
-  {
-    assert(token.type == T.Static);
-    nT();
-    assert(token.type == T.If);
-    nT();
-    Expression condition;
-    Statement ifBody, elseBody;
-
-    require(T.LParen);
-    condition = parseExpression();
-    require(T.RParen);
-    ifBody = parseNoScopeStatement();
-    if (token.type == T.Else)
-    {
-      nT();
-      elseBody = parseNoScopeStatement();
-    }
-    return new StaticIfStatement(condition, ifBody, elseBody);
-  }
-
-  Statement parseStaticAssertStatement()
-  {
-    assert(token.type == T.Static);
-    nT();
-    assert(token.type == T.Assert);
-    nT();
-    Expression condition, message;
-    require(T.LParen);
-    condition = parseAssignExpression();
-    if (token.type == T.Comma)
-    {
-      nT();
-      message = parseAssignExpression();
-    }
-    require(T.RParen);
-    require(T.Semicolon);
-    return new StaticAssertStatement(condition, message);
-  }
-
-  Statement parseDebugStatement()
-  {
-    assert(token.type == T.Debug);
-    nT(); // Skip debug keyword.
-
-    Token* cond; // debug ( Integer )
-                 // debug ( Identifier )
-    Statement debugBody, elseBody;
-
-    void parseIdentOrInt(ref Token* tok)
-    {
-      nT();
-      if (token.type == T.Int32 ||
-          token.type == T.Identifier)
-      {
-        tok = token;
-        nT();
-      }
-      else
-        expected(T.Identifier); // TODO: better error msg
-    }
-
-//     if (token.type == T.Assign)
-//     {
-//       parseIdentOrInt(identSpec, levelSpec);
-//       require(T.Semicolon);
-//     }
-//     else
-    {
-      // Condition:
-      //     Integer
-      //     Identifier
-
-      // ( Condition )
-      if (token.type == T.LParen)
-      {
-        parseIdentOrInt(cond);
-        require(T.RParen);
-      }
-
-      // debug Statement
-      // debug ( Condition ) Statement
-      debugBody = parseNoScopeStatement();
-
-      // else Statement
-      if (token.type == T.Else)
-      {
-        // debug without condition and else body makes no sense
-        //if (levelCond == -1 && identCond.length == 0)
-          // TODO: issue error msg
-        nT();
-        elseBody = parseNoScopeStatement();
-      }
-    }
-
-    return new DebugStatement(cond, debugBody, elseBody);
-  }
-
-  Statement parseVersionStatement()
-  {
-    assert(token.type == T.Version);
-
-    nT(); // Skip version keyword.
-
-    Token* cond; // version ( Integer )
-                 // version ( Identifier )
-    Statement versionBody, elseBody;
-
-    void parseIdentOrInt(ref Token* tok)
-    {
-      if (token.type == T.Int32 ||
-          token.type == T.Identifier)
-      {
-        tok = token;
-        nT();
-      }
-      else
-        expected(T.Identifier); // TODO: better error msg
-    }
-
-//     if (token.type == T.Assign)
-//     {
-//       parseIdentOrInt(identSpec, levelSpec);
-//       require(T.Semicolon);
-//     }
-//     else
-    {
-      // Condition:
-      //     Integer
-      //     Identifier
-
-      // ( Condition )
-      require(T.LParen);
-      parseIdentOrInt(cond);
-      require(T.RParen);
-
-      // version ( Condition ) Statement
-      versionBody = parseNoScopeStatement();
-
-      // else Statement
-      if (token.type == T.Else)
-      {
-        nT();
-        elseBody = parseNoScopeStatement();
-      }
-    }
-
-    return new VersionStatement(cond, versionBody, elseBody);
-  }
-
-  /+++++++++++++++++++++++++++++
-  + Assembler parsing methods  +
-  +++++++++++++++++++++++++++++/
-
-  Statement parseAsmStatement()
-  {
-    assert(token.type == T.Asm);
-    nT(); // Skip asm keyword.
-    require(T.LBrace);
-    auto ss = new Statements;
-    while (token.type != T.RBrace && token.type != T.EOF)
-      ss ~= parseAsmInstruction();
-    require(T.RBrace);
-    return new AsmStatement(ss);
-  }
-
-  Statement parseAsmInstruction()
-  {
-    auto begin = token;
-    Statement s;
-    switch (token.type)
-    {
-    case T.Identifier:
-      auto ident = token;
-      auto next = peekNext();
-      if (next == T.Colon)
-      {
-        // Identifier : AsmInstruction
-        nT(); // Skip Identifier
-        nT(); // Skip :
-        s = new LabeledStatement(ident, parseAsmInstruction());
-        break;
-      }
-
-      // Opcode ;
-      // Opcode Operands ;
-      // Opcode
-      //     Identifier
-      Expression[] es;
-      if (next != T.Semicolon)
-      {
-        while (1)
-        {
-          es ~= parseAsmExpression();
-          if (token.type != T.Comma)
-            break;
-          nT();
-        }
-      }
-      require(T.Semicolon);
-      s = new AsmInstruction(ident, es);
-      break;
-    case T.Semicolon:
-      s = new EmptyStatement();
-      nT();
-      break;
-    default:
-      error(MID.ExpectedButFound, "AsmStatement", token.srcText);
-      s = new IllegalAsmInstruction(token);
-      nT();
-    }
-    set(s, begin);
-    return s;
-  }
-
-  Expression parseAsmExpression()
-  {
-    auto begin = token;
-    auto e = parseOrOrExpression();
-    if (token.type == T.Question)
-    {
-      auto tok = token;
-      nT();
-      auto iftrue = parseAsmExpression();
-      require(T.Colon);
-      auto iffalse = parseAsmExpression();
-      e = new CondExpression(e, iftrue, iffalse, tok);
-      set(e, begin);
-    }
-    // TODO: create AsmExpression that contains e?
-    return e;
-  }
-
-  Expression parseAsmOrOrExpression()
-  {
-    auto begin = token;
-    alias parseAsmAndAndExpression parseNext;
-    auto e = parseNext();
-    while (token.type == T.OrLogical)
-    {
-      auto tok = token;
-      nT();
-      e = new OrOrExpression(e, parseNext(), tok);
-      set(e, begin);
-    }
-    return e;
-  }
-
-  Expression parseAsmAndAndExpression()
-  {
-    auto begin = token;
-    alias parseAsmOrExpression parseNext;
-    auto e = parseNext();
-    while (token.type == T.AndLogical)
-    {
-      auto tok = token;
-      nT();
-      e = new AndAndExpression(e, parseNext(), tok);
-      set(e, begin);
-    }
-    return e;
-  }
-
-  Expression parseAsmOrExpression()
-  {
-    auto begin = token;
-    alias parseAsmXorExpression parseNext;
-    auto e = parseNext();
-    while (token.type == T.OrBinary)
-    {
-      auto tok = token;
-      nT();
-      e = new OrExpression(e, parseNext(), tok);
-      set(e, begin);
-    }
-    return e;
-  }
-
-  Expression parseAsmXorExpression()
-  {
-    alias parseAsmAndExpression parseNext;
-    auto begin = token;
-    auto e = parseNext();
-    while (token.type == T.Xor)
-    {
-      auto tok = token;
-      nT();
-      e = new XorExpression(e, parseNext(), tok);
-      set(e, begin);
-    }
-    return e;
-  }
-
-  Expression parseAsmAndExpression()
-  {
-    alias parseAsmCmpExpression parseNext;
-    auto begin = token;
-    auto e = parseNext();
-    while (token.type == T.AndBinary)
-    {
-      auto tok = token;
-      nT();
-      e = new AndExpression(e, parseNext(), tok);
-      set(e, begin);
-    }
-    return e;
-  }
-
-  Expression parseAsmCmpExpression()
-  {
-    alias parseAsmShiftExpression parseNext;
-    auto begin = token;
-    auto e = parseNext();
-
-    auto operator = token;
-    switch (operator.type)
-    {
-    case T.Equal, T.NotEqual:
-      nT();
-      e = new EqualExpression(e, parseNext(), operator);
-      break;
-    case T.LessEqual, T.Less, T.GreaterEqual, T.Greater:
-      nT();
-      e = new RelExpression(e, parseNext(), operator);
-      break;
-    default:
-      return e;
-    }
-    set(e, begin);
-    return e;
-  }
-
-  Expression parseAsmShiftExpression()
-  {
-    alias parseAsmAddExpression parseNext;
-    auto begin = token;
-    auto e = parseNext();
-    while (1)
-    {
-      auto operator = token;
-      switch (operator.type)
-      {
-      case T.LShift:  nT(); e = new LShiftExpression(e, parseNext(), operator); break;
-      case T.RShift:  nT(); e = new RShiftExpression(e, parseNext(), operator); break;
-      case T.URShift: nT(); e = new URShiftExpression(e, parseNext(), operator); break;
-      default:
-        return e;
-      }
-      set(e, begin);
-    }
-    assert(0);
-  }
-
-  Expression parseAsmAddExpression()
-  {
-    alias parseAsmMulExpression parseNext;
-    auto begin = token;
-    auto e = parseNext();
-    while (1)
-    {
-      auto operator = token;
-      switch (operator.type)
-      {
-      case T.Plus:  nT(); e = new PlusExpression(e, parseNext(), operator); break;
-      case T.Minus: nT(); e = new MinusExpression(e, parseNext(), operator); break;
-      // Not allowed in asm
-      //case T.Tilde: nT(); e = new CatExpression(e, parseNext(), operator); break;
-      default:
-        return e;
-      }
-      set(e, begin);
-    }
-    assert(0);
-  }
-
-  Expression parseAsmMulExpression()
-  {
-    alias parseAsmPostExpression parseNext;
-    auto begin = token;
-    auto e = parseNext();
-    while (1)
-    {
-      auto operator = token;
-      switch (operator.type)
-      {
-      case T.Mul: nT(); e = new MulExpression(e, parseNext(), operator); break;
-      case T.Div: nT(); e = new DivExpression(e, parseNext(), operator); break;
-      case T.Mod: nT(); e = new ModExpression(e, parseNext(), operator); break;
-      default:
-        return e;
-      }
-      set(e, begin);
-    }
-    assert(0);
-  }
-
-  Expression parseAsmPostExpression()
-  {
-    auto begin = token;
-    auto e = parseAsmUnaryExpression();
-    while (token.type == T.RBracket)
-    {
-      nT();
-      e = parseAsmExpression();
-      e = new AsmPostBracketExpression(e);
-      require(T.RBracket);
-      set(e, begin);
-    }
-    return e;
-  }
-
-  Expression parseAsmUnaryExpression()
-  {
-    auto begin = token;
-    Expression e;
-    switch (token.type)
-    {
-    case T.Identifier:
-      switch (token.identifier)
-      {
-      case "near", "far",   "byte",  "short",  "int",
-           "word", "dword", "float", "double", "real":
-        nT();
-        if (token.type == T.Identifier && token.identifier == "ptr")
-          nT();
-        else
-          error(MID.ExpectedButFound, "ptr", token.srcText);
-        e = new AsmTypeExpression(parseAsmUnaryExpression());
-        break;
-      case "offset":
-        nT();
-        e = new AsmOffsetExpression(parseAsmUnaryExpression());
-        break;
-      case "seg":
-        nT();
-        e = new AsmSegExpression(parseAsmUnaryExpression());
-        break;
-      default:
-      }
-      goto default;
-    case T.Minus:
-    case T.Plus:
-      nT();
-      e = new SignExpression(parseAsmUnaryExpression());
-      break;
-    case T.Not:
-      nT();
-      e = new NotExpression(parseAsmUnaryExpression());
-      break;
-    case T.Tilde:
-      nT();
-      e = new CompExpression(parseAsmUnaryExpression());
-    default:
-      e = parseAsmPrimaryExpression();
-      return e;
-    }
-    set(e, begin);
-    return e;
-  }
-
-  Expression parseAsmPrimaryExpression()
-  {
-    auto begin = token;
-    Expression e;
-    switch (token.type)
-    {
-    case T.Int32, T.Int64, T.Uint32, T.Uint64:
-      e = new IntNumberExpression(token.type, token.ulong_);
-      nT();
-      break;
-    case T.Float32, T.Float64, T.Float80,
-         T.Imaginary32, T.Imaginary64, T.Imaginary80:
-      e = new RealNumberExpression(token.type, token.real_);
-      nT();
-      break;
-    case T.Dollar:
-      e = new DollarExpression();
-      nT();
-      break;
-    case T.LBracket:
-      // [ AsmExpression ]
-      nT();
-      e = parseAsmExpression();
-      require(T.RBracket);
-      e = new AsmBracketExpression(e);
-      break;
-    case T.Identifier:
-      switch (token.identifier)
-      {
-      // __LOCAL_SIZE
-      case "__LOCAL_SIZE":
-        e = new AsmLocalSizeExpression();
-        nT();
-        break;
-      // Register
-      case "ST":
-        auto register = token;
-        nT();
-        // (1) - (7)
-        Token* number;
-        if (token.type == T.LParen)
-        {
-          nT();
-          if (token.type == T.Int32)
-          {
-            number = token;
-            nT();
-          }
-          else
-            expected(T.Int32);
-          require(T.RParen);
-        }
-        e = new AsmRegisterExpression(register, number);
-        break;
-      case "AL", "AH", "AX", "EAX",
-           "BL", "BH", "BX", "EBX",
-           "CL", "CH", "CX", "ECX",
-           "DL", "DH", "DX", "EDX",
-           "BP", "EBP",
-           "SP", "ESP",
-           "DI", "EDI",
-           "SI", "ESI",
-           "ES", "CS", "SS", "DS", "GS", "FS",
-           "CR0", "CR2", "CR3", "CR4",
-           "DR0", "DR1", "DR2", "DR3", "DR6", "DR7",
-           "TR3", "TR4", "TR5", "TR6", "TR7",
-           "MM0", "MM1", "MM2", "MM3", "MM4", "MM5", "MM6", "MM7",
-           "XMM0", "XMM1", "XMM2", "XMM3", "XMM4", "XMM5", "XMM6", "XMM7":
-          e = new AsmRegisterExpression(token);
-          nT();
-        break;
-      default:
-        // DotIdentifier
-        auto begin2 = token;
-        Expression[] identList;
-        goto LenterLoop;
-        while (token.type == T.Dot)
-        {
-          nT();
-          begin2 = token;
-          auto ident = requireId();
-        LenterLoop:
-          e = new IdentifierExpression(token);
-          nT();
-          set(e, begin2);
-          identList ~= e;
-        }
-        e = new DotListExpression(identList);
-      }
-      break;
-    default:
-      error(MID.ExpectedButFound, "Expression", token.srcText);
-      e = new EmptyExpression();
-      break;
-    }
-    set(e, begin);
-    return e;
-  }
-
-  /+++++++++++++++++++++++++++++
-  + Expression parsing methods +
-  +++++++++++++++++++++++++++++/
-
-  Expression parseExpression()
-  {
-    auto begin = token;
-    auto e = parseAssignExpression();
-    while (token.type == T.Comma)
-    {
-      auto comma = token;
-      nT();
-      e = new CommaExpression(e, parseAssignExpression(), comma);
-      set(e, begin);
-    }
-// if (!trying)
-// writef("§%s§", e.classinfo.name);
-    return e;
-  }
-
-  Expression parseAssignExpression()
-  {
-    auto begin = token;
-    auto e = parseCondExpression();
-    while (1)
-    {
-      switch (token.type)
-      {
-      case T.Assign:
-        nT(); e = new AssignExpression(e, parseAssignExpression());
-        break;
-      case T.LShiftAssign:
-        nT(); e = new LShiftAssignExpression(e, parseAssignExpression());
-        break;
-      case T.RShiftAssign:
-        nT(); e = new RShiftAssignExpression(e, parseAssignExpression());
-        break;
-      case T.URShiftAssign:
-        nT(); e = new URShiftAssignExpression(e, parseAssignExpression());
-        break;
-      case T.OrAssign:
-        nT(); e = new OrAssignExpression(e, parseAssignExpression());
-        break;
-      case T.AndAssign:
-        nT(); e = new AndAssignExpression(e, parseAssignExpression());
-        break;
-      case T.PlusAssign:
-        nT(); e = new PlusAssignExpression(e, parseAssignExpression());
-        break;
-      case T.MinusAssign:
-        nT(); e = new MinusAssignExpression(e, parseAssignExpression());
-        break;
-      case T.DivAssign:
-        nT(); e = new DivAssignExpression(e, parseAssignExpression());
-        break;
-      case T.MulAssign:
-        nT(); e = new MulAssignExpression(e, parseAssignExpression());
-        break;
-      case T.ModAssign:
-        nT(); e = new ModAssignExpression(e, parseAssignExpression());
-        break;
-      case T.XorAssign:
-        nT(); e = new XorAssignExpression(e, parseAssignExpression());
-        break;
-      case T.CatAssign:
-        nT(); e = new CatAssignExpression(e, parseAssignExpression());
-        break;
-      default:
-        return e;
-      }
-      set(e, begin);
-    }
-    return e;
-  }
-
-  Expression parseCondExpression()
-  {
-    auto begin = token;
-    auto e = parseOrOrExpression();
-    if (token.type == T.Question)
-    {
-      auto tok = token;
-      nT();
-      auto iftrue = parseExpression();
-      require(T.Colon);
-      auto iffalse = parseCondExpression();
-      e = new CondExpression(e, iftrue, iffalse, tok);
-      set(e, begin);
-    }
-    return e;
-  }
-
-  Expression parseOrOrExpression()
-  {
-    auto begin = token;
-    alias parseAndAndExpression parseNext;
-    auto e = parseNext();
-    while (token.type == T.OrLogical)
-    {
-      auto tok = token;
-      nT();
-      e = new OrOrExpression(e, parseNext(), tok);
-      set(e, begin);
-    }
-    return e;
-  }
-
-  Expression parseAndAndExpression()
-  {
-    auto begin = token;
-    alias parseOrExpression parseNext;
-    auto e = parseNext();
-    while (token.type == T.AndLogical)
-    {
-      auto tok = token;
-      nT();
-      e = new AndAndExpression(e, parseNext(), tok);
-      set(e, begin);
-    }
-    return e;
-  }
-
-  Expression parseOrExpression()
-  {
-    auto begin = token;
-    alias parseXorExpression parseNext;
-    auto e = parseNext();
-    while (token.type == T.OrBinary)
-    {
-      auto tok = token;
-      nT();
-      e = new OrExpression(e, parseNext(), tok);
-      set(e, begin);
-    }
-    return e;
-  }
-
-  Expression parseXorExpression()
-  {
-    auto begin = token;
-    alias parseAndExpression parseNext;
-    auto e = parseNext();
-    while (token.type == T.Xor)
-    {
-      auto tok = token;
-      nT();
-      e = new XorExpression(e, parseNext(), tok);
-      set(e, begin);
-    }
-    return e;
-  }
-
-  Expression parseAndExpression()
-  {
-    auto begin = token;
-    alias parseCmpExpression parseNext;
-    auto e = parseNext();
-    while (token.type == T.AndBinary)
-    {
-      auto tok = token;
-      nT();
-      e = new AndExpression(e, parseNext(), tok);
-      set(e, begin);
-    }
-    return e;
-  }
-
-  Expression parseCmpExpression()
-  {
-    auto begin = token;
-    auto e = parseShiftExpression();
-
-    auto operator = token;
-    switch (operator.type)
-    {
-    case T.Equal, T.NotEqual:
-      nT();
-      e = new EqualExpression(e, parseShiftExpression(), operator);
-      break;
-    case T.Not:
-      if (peekNext() != T.Is)
-        break;
-      nT();
-      // fall through
-    case T.Is:
-      nT();
-      e = new IdentityExpression(e, parseShiftExpression(), operator);
-      break;
-    case T.LessEqual, T.Less, T.GreaterEqual, T.Greater,
-         T.Unordered, T.UorE, T.UorG, T.UorGorE,
-         T.UorL, T.UorLorE, T.LorEorG, T.LorG:
-      nT();
-      e = new RelExpression(e, parseShiftExpression(), operator);
-      break;
-    case T.In:
-      nT();
-      e = new InExpression(e, parseShiftExpression(), operator);
-      break;
-    default:
-      return e;
-    }
-    set(e, begin);
-    return e;
-  }
-
-  Expression parseShiftExpression()
-  {
-    auto begin = token;
-    auto e = parseAddExpression();
-    while (1)
-    {
-      auto operator = token;
-      switch (operator.type)
-      {
-      case T.LShift:  nT(); e = new LShiftExpression(e, parseAddExpression(), operator); break;
-      case T.RShift:  nT(); e = new RShiftExpression(e, parseAddExpression(), operator); break;
-      case T.URShift: nT(); e = new URShiftExpression(e, parseAddExpression(), operator); break;
-      default:
-        return e;
-      }
-      set(e, begin);
-    }
-    assert(0);
-  }
-
-  Expression parseAddExpression()
-  {
-    auto begin = token;
-    auto e = parseMulExpression();
-    while (1)
-    {
-      auto operator = token;
-      switch (operator.type)
-      {
-      case T.Plus:  nT(); e = new PlusExpression(e, parseMulExpression(), operator); break;
-      case T.Minus: nT(); e = new MinusExpression(e, parseMulExpression(), operator); break;
-      case T.Tilde: nT(); e = new CatExpression(e, parseMulExpression(), operator); break;
-      default:
-        return e;
-      }
-      set(e, begin);
-    }
-    assert(0);
-  }
-
-  Expression parseMulExpression()
-  {
-    auto begin = token;
-    auto e = parseUnaryExpression();
-    while (1)
-    {
-      auto operator = token;
-      switch (operator.type)
-      {
-      case T.Mul: nT(); e = new MulExpression(e, parseUnaryExpression(), operator); break;
-      case T.Div: nT(); e = new DivExpression(e, parseUnaryExpression(), operator); break;
-      case T.Mod: nT(); e = new ModExpression(e, parseUnaryExpression(), operator); break;
-      default:
-        return e;
-      }
-      set(e, begin);
-    }
-    assert(0);
-  }
-
-  Expression parseUnaryExpression()
-  {
-    auto begin = token;
-    Expression e;
-    switch (token.type)
-    {
-    case T.AndBinary:
-      nT();
-      e = new AddressExpression(parseUnaryExpression());
-      break;
-    case T.PlusPlus:
-      nT();
-      e = new PreIncrExpression(parseUnaryExpression());
-      break;
-    case T.MinusMinus:
-      nT();
-      e = new PreDecrExpression(parseUnaryExpression());
-      break;
-    case T.Mul:
-      nT();
-      e = new DerefExpression(parseUnaryExpression());
-      break;
-    case T.Minus:
-    case T.Plus:
-      nT();
-      e = new SignExpression(parseUnaryExpression());
-      break;
-    case T.Not:
-      nT();
-      e = new NotExpression(parseUnaryExpression());
-      break;
-    case T.Tilde:
-      nT();
-      e = new CompExpression(parseUnaryExpression());
-      break;
-    case T.New:
-      e = parseNewExpression();
-      return e;
-    case T.Delete:
-      nT();
-      e = new DeleteExpression(parseUnaryExpression());
-      break;
-    case T.Cast:
-      requireNext(T.LParen);
-      Type type;
-      switch (token.type)
-      {
-      version(D2)
-      {
-      auto begin2 = token;
-      case T.Const:
-        type = new ConstType(null);
-        goto case_break;
-      case T.Invariant:
-        type = new InvariantType(null);
-      case_break:
-        nT();
-        set(type, begin2);
-        break;
-      }
-      default:
-       type = parseType();
-      }
-      require(T.RParen);
-      e = new CastExpression(parseUnaryExpression(), type);
-      break;
-    case T.LParen:
-      // ( Type ) . Identifier
-      Type parseType_()
-      {
-        nT();
-        auto type = parseType();
-        require(T.RParen);
-        require(T.Dot);
-        return type;
-      }
-      bool success;
-      auto type = try_(parseType_(), success);
-      if (success)
-      {
-        auto ident = requireId();
-        e = new TypeDotIdExpression(type, ident);
-        break;
-      }
-      goto default;
-    default:
-      e = parsePostExpression(parsePrimaryExpression());
-      return e;
-    }
-    assert(e !is null);
-    set(e, begin);
-    return e;
-  }
-
-  Expression parsePostExpression(Expression e)
-  {
-    typeof(token) begin;
-    while (1)
-    {
-      begin = token;
-      switch (token.type)
-      {
-/*
-// Commented out because parseDotListExpression() handles this.
-      case T.Dot:
-        nT();
-        if (token.type == T.Identifier)
-        {
-          string ident = token.identifier;
-          nT();
-          if (token.type == T.Not && peekNext() == T.LParen) // Identifier !( TemplateArguments )
-          {
-            nT(); // Skip !.
-            e = new DotTemplateInstanceExpression(e, ident, parseTemplateArguments());
-          }
-          else
-          {
-            e = new DotIdExpression(e, ident);
-            nT();
-          }
-        }
-        else if (token.type == T.New)
-          e = parseNewExpression(e);
-        else
-          expected(T.Identifier);
-        continue;
-*/
-      case T.Dot:
-        e = new PostDotListExpression(e, parseDotListExpression());
-        goto Lset;
-      case T.PlusPlus:
-        e = new PostIncrExpression(e);
-        break;
-      case T.MinusMinus:
-        e = new PostDecrExpression(e);
-        break;
-      case T.LParen:
-        e = new CallExpression(e, parseArguments(T.RParen));
-        goto Lset;
-      case T.LBracket:
-        // parse Slice- and IndexExpression
-        nT();
-        if (token.type == T.RBracket)
-        {
-          e = new SliceExpression(e, null, null);
-          break;
-        }
-
-        Expression[] es = [parseAssignExpression()];
-
-        if (token.type == T.Slice)
-        {
-          nT();
-          e = new SliceExpression(e, es[0], parseAssignExpression());
-          require(T.RBracket);
-          goto Lset;
-        }
-        else if (token.type == T.Comma)
-        {
-           es ~= parseArguments(T.RBracket);
-        }
-        else
-          require(T.RBracket);
-
-        e = new IndexExpression(e, es);
-        goto Lset;
-      default:
-        return e;
-      }
-      nT();
-    Lset:
-      set(e, begin);
-    }
-    assert(0);
-  }
-
-  Expression parsePrimaryExpression()
-  {
-    auto begin = token;
-    Expression e;
-    switch (token.type)
-    {
-/*
-// Commented out because parseDotListExpression() handles this.
-    case T.Identifier:
-      string ident = token.identifier;
-      nT();
-      if (token.type == T.Not && peekNext() == T.LParen) // Identifier !( TemplateArguments )
-      {
-        nT(); // Skip !.
-        e = new TemplateInstanceExpression(ident, parseTemplateArguments());
-      }
-      else
-        e = new IdentifierExpression(ident);
-      break;
-    case T.Dot:
-      nT();
-      e = new IdentifierExpression(".");
-      break;
-*/
-    case T.Identifier, T.Dot, T.Typeof:
-      e = parseDotListExpression();
-      break;
-    case T.This:
-      nT();
-      e = new ThisExpression();
-      break;
-    case T.Super:
-      nT();
-      e = new SuperExpression();
-      break;
-    case T.Null:
-      nT();
-      e = new NullExpression();
-      break;
-    case T.True, T.False:
-      nT();
-      e = new BoolExpression();
-      break;
-    case T.Dollar:
-      nT();
-      e = new DollarExpression();
-      break;
-    case T.Int32, T.Int64, T.Uint32, T.Uint64:
-      e = new IntNumberExpression(token.type, token.ulong_);
-      nT();
-      break;
-    case T.Float32, T.Float64, T.Float80,
-         T.Imaginary32, T.Imaginary64, T.Imaginary80:
-      e = new RealNumberExpression(token.type, token.real_);
-      nT();
-      break;
-    case T.CharLiteral, T.WCharLiteral, T.DCharLiteral:
-      nT();
-      e = new CharLiteralExpression();
-      break;
-    case T.String:
-      Token*[] stringLiterals;
-      do
-      {
-        stringLiterals ~= token;
-        nT();
-      } while (token.type == T.String)
-      e = new StringLiteralsExpression(stringLiterals);
-      break;
-    case T.LBracket:
-      Expression[] values;
-
-      nT();
-      if (token.type != T.RBracket)
-      {
-        e = parseAssignExpression();
-        if (token.type == T.Colon)
-          goto LparseAssocArray;
-        else if (token.type == T.Comma)
-          values = [e] ~ parseArguments(T.RBracket);
-        else
-          require(T.RBracket);
-      }
-      else
-        nT();
-
-      e = new ArrayLiteralExpression(values);
-      break;
-
-    LparseAssocArray:
-      Expression[] keys;
-
-      keys ~= e;
-      nT(); // Skip colon.
-      goto LenterLoop;
-
-      while (1)
-      {
-        keys ~= parseAssignExpression();
-        require(T.Colon);
-      LenterLoop:
-        values ~= parseAssignExpression();
-        if (token.type != T.Comma)
-          break;
-        nT();
-      }
-      require(T.RBracket);
-      e = new AssocArrayLiteralExpression(keys, values);
-      break;
-    case T.LBrace:
-      // DelegateLiteral := { Statements }
-      auto funcBody = parseFunctionBody();
-      e = new FunctionLiteralExpression(funcBody);
-      break;
-    case T.Function, T.Delegate:
-      // FunctionLiteral := (function|delegate) Type? '(' ArgumentList ')' '{' Statements '}'
-      nT(); // Skip function|delegate token.
-      Type returnType;
-      Parameters parameters;
-      if (token.type != T.LBrace)
-      {
-        if (token.type != T.LParen) // Optional return type
-          returnType = parseType();
-        parameters = parseParameterList();
-      }
-      auto funcBody = parseFunctionBody();
-      e = new FunctionLiteralExpression(returnType, parameters, funcBody);
-      break;
-    case T.Assert:
-      Expression msg;
-      requireNext(T.LParen);
-      e = parseAssignExpression();
-      if (token.type == T.Comma)
-      {
-        nT();
-        msg = parseAssignExpression();
-      }
-      require(T.RParen);
-      e = new AssertExpression(e, msg);
-      break;
-    case T.Mixin:
-      requireNext(T.LParen);
-      e = parseAssignExpression();
-      require(T.RParen);
-      e = new MixinExpression(e);
-      break;
-    case T.Import:
-      requireNext(T.LParen);
-      e = parseAssignExpression();
-      require(T.RParen);
-      e = new ImportExpression(e);
-      break;
-    case T.Typeid:
-      requireNext(T.LParen);
-      auto type = parseType();
-      require(T.RParen);
-      e = new TypeidExpression(type);
-      break;
-/*
-// Commented out because parseDotListExpression() handles this.
-    case T.Typeof:
-      requireNext(T.LParen);
-      auto type = new TypeofType(parseExpression());
-      require(T.RParen);
-      if (token.type == T.Dot)
-      { // typeof ( Expression ) . Identifier
-        nT();
-        string ident = requireIdentifier;
-        e = new TypeDotIdExpression(type, ident);
-      }
-      else // typeof ( Expression )
-        e = new TypeofExpression(type);
-      break;
-*/
-    case T.Is:
-      requireNext(T.LParen);
-
-      Type type, specType;
-      Token* ident; // optional Identifier
-      Token* opTok, specTok;
-
-      type = parseDeclarator(ident, true);
-
-      switch (token.type)
-      {
-      case T.Colon, T.Equal:
-        opTok = token;
-        nT();
-        switch (token.type)
-        {
-        case T.Typedef,
-             T.Struct,
-             T.Union,
-             T.Class,
-             T.Interface,
-             T.Enum,
-             T.Function,
-             T.Delegate,
-             T.Super,
-             T.Return:
-          specTok = token;
-          nT();
-          break;
-        default:
-          specType = parseType();
-        }
-      default:
-      }
-      require(T.RParen);
-      e = new IsExpression(type, ident, opTok, specTok, specType);
-      break;
-    case T.LParen:
-      if (tokenAfterParenIs(T.LBrace))
-      {
-        auto parameters = parseParameterList();
-        // ( ParameterList ) FunctionBody
-        auto funcBody = parseFunctionBody();
-        e = new FunctionLiteralExpression(null, parameters, funcBody);
-      }
-      else
-      {
-        // ( Expression )
-        nT();
-        e = parseExpression();
-        require(T.RParen);
-        // TODO: create ParenExpression?
-      }
-      break;
-    // BasicType . Identifier
-    case T.Char,   T.Wchar,   T.Dchar,  T.Bool,
-         T.Byte,   T.Ubyte,   T.Short,  T.Ushort,
-         T.Int,    T.Uint,    T.Long,   T.Ulong,
-         T.Float,  T.Double,  T.Real,
-         T.Ifloat, T.Idouble, T.Ireal,
-         T.Cfloat, T.Cdouble, T.Creal, T.Void:
-      auto type = new IntegralType(token.type);
-      nT();
-      set(type, begin);
-      require(T.Dot);
-      auto ident = requireId();
-
-      e = new TypeDotIdExpression(type, ident);
-      break;
-    version(D2)
-    {
-    case T.Traits:
-      nT();
-      require(T.LParen);
-      auto id = requireId();
-      TemplateArguments args;
-      if (token.type == T.Comma)
-      {
-        args = parseTemplateArguments2();
-      }
-      else
-        require(T.RParen);
-      e = new TraitsExpression(id, args);
-      break;
-    }
-    case T.Special:
-      e = new SpecialTokenExpression(token);
-      nT();
-      break;
-    default:
-      // TODO: issue error msg.
-      error(MID.ExpectedButFound, "Expression", token.srcText);
-      e = new EmptyExpression();
-    }
-    set(e, begin);
-    return e;
-  }
-
-  Expression parseNewExpression(/*Expression e*/)
-  {
-    auto begin = token;
-    assert(token.type == T.New);
-    nT(); // Skip new keyword.
-
-    Expression[] newArguments;
-    Expression[] ctorArguments;
-
-    if (token.type == T.LParen)
-      newArguments = parseArguments(T.RParen);
-
-    // NewAnonClassExpression:
-    //         new (ArgumentList)opt class (ArgumentList)opt SuperClassopt InterfaceClassesopt ClassBody
-    if (token.type == T.Class)
-    {
-      nT();
-      if (token.type == T.LParen)
-        ctorArguments = parseArguments(T.RParen);
-
-      BaseClass[] bases = token.type != T.LBrace ? parseBaseClasses(false) : null ;
-
-      auto decls = parseDeclarationDefinitionsBlock();
-      return set(new NewAnonClassExpression(/*e, */newArguments, bases, ctorArguments, decls), begin);
-    }
-
-    // NewExpression:
-    //         NewArguments Type [ AssignExpression ]
-    //         NewArguments Type ( ArgumentList )
-    //         NewArguments Type
-    auto type = parseType();
-
-    if (token.type == T.LParen)
-      ctorArguments = parseArguments(T.RParen);
-
-    return set(new NewExpression(/*e, */newArguments, type, ctorArguments), begin);
-  }
-
-  Type parseType()
-  {
-    return parseBasicType2(parseBasicType());
-  }
-
-  Type parseBasicType()
-  {
-    auto begin = token;
-    Type t;
-//     IdentifierType tident;
-
-    switch (token.type)
-    {
-    case T.Char,   T.Wchar,   T.Dchar,  T.Bool,
-         T.Byte,   T.Ubyte,   T.Short,  T.Ushort,
-         T.Int,    T.Uint,    T.Long,   T.Ulong,
-         T.Float,  T.Double,  T.Real,
-         T.Ifloat, T.Idouble, T.Ireal,
-         T.Cfloat, T.Cdouble, T.Creal, T.Void:
-      t = new IntegralType(token.type);
-      nT();
-      set(t, begin);
-      break;
-    case T.Identifier, T.Typeof, T.Dot:
-      t = parseDotListType();
-      break;
-    version(D2)
-    {
-    case T.Const:
-      // const ( Type )
-      nT();
-      require(T.LParen);
-      t = parseType();
-      require(T.RParen);
-      t = new ConstType(t);
-      set(t, begin);
-      break;
-    case T.Invariant:
-      // invariant ( Type )
-      nT();
-      require(T.LParen);
-      t = parseType();
-      require(T.RParen);
-      t = new InvariantType(t);
-      set(t, begin);
-      break;
-    }
-    default:
-      // TODO: issue error msg.
-      error(MID.ExpectedButFound, "BasicType", token.srcText);
-      t = new UndefinedType();
-      nT();
-      set(t, begin);
-    }
-    return t;
-  }
-
-  Type parseBasicType2(Type t)
-  {
-    typeof(token) begin;
-    while (1)
-    {
-      begin = token;
-      switch (token.type)
-      {
-      case T.Mul:
-        t = new PointerType(t);
-        nT();
-        break;
-      case T.LBracket:
-        t = parseArrayType(t);
-        continue;
-      case T.Function, T.Delegate:
-        TOK tok = token.type;
-        nT();
-        auto parameters = parseParameterList();
-        if (tok == T.Function)
-          t = new FunctionType(t, parameters);
-        else
-          t = new DelegateType(t, parameters);
-        break;
-      default:
-        return t;
-      }
-      set(t, begin);
-    }
-    assert(0);
-  }
-
-  bool tokenAfterParenIs(TOK tok)
-  {
-    // We count nested parentheses tokens because template types may appear inside parameter lists; e.g. (int x, Foo!(int) y).
-    assert(token.type == T.LParen);
-    Token* next = token;
-    uint level = 1;
-    while (1)
-    {
-      lx.peek(next);
-      switch (next.type)
-      {
-      case T.RParen:
-        if (--level == 0)
-        { // Closing parentheses found.
-          lx.peek(next);
-          break;
-        }
-        continue;
-      case T.LParen:
-        ++level;
-        continue;
-      case T.EOF:
-        break;
-      default:
-        continue;
-      }
-      break;
-    }
-
-    return next.type == tok;
-  }
-
-  Type parseDeclaratorSuffix(Type t)
-  {
-    switch (token.type)
-    {
-    case T.LBracket:
-      // Type Identifier ArrayType
-      // ArrayType := [] or [Type] or [Expression..Expression]
-      do
-        t = parseArrayType(t);
-      while (token.type == T.LBracket)
-      break;
-/+ // parsed in parseDeclaration()
-    case T.LParen:
-      TemplateParameters tparams;
-      if (tokenAfterParenIs(T.LParen))
-      {
-        // ( TemplateParameterList ) ( ParameterList )
-        tparams = parseTemplateParameterList();
-      }
-
-      auto params = parseParameterList();
-      // ReturnType FunctionName ( ParameterList )
-      t = new FunctionType(t, params, tparams);
-      break;
-+/
-    default:
-      break;
-    }
-    return t;
-  }
-
-  Type parseArrayType(Type t)
-  {
-    assert(token.type == T.LBracket);
-    auto begin = token;
-    nT();
-    if (token.type == T.RBracket)
-    {
-      t = new ArrayType(t);
-      nT();
-    }
-    else
-    {
-      bool success;
-      auto assocType = try_(parseType(), success);
-      if (success)
-        t = new ArrayType(t, assocType);
-      else
-      {
-        Expression e = parseExpression(), e2;
-        if (token.type == T.Slice)
-        {
-          nT();
-          e2 = parseExpression();
-        }
-        t = new ArrayType(t, e, e2);
-      }
-      require(T.RBracket);
-    }
-    set(t, begin);
-    return t;
-  }
-
-  Type parseDeclarator(ref Token* ident, bool identOptional = false)
-  {
-    auto t = parseType();
-
-    if (token.type == T.Identifier)
-    {
-      ident = token;
-      nT();
-      t = parseDeclaratorSuffix(t);
-    }
-    else if (!identOptional)
-      expected(T.Identifier);
-
-    return t;
-  }
-
-  Expression[] parseArguments(TOK terminator)
-  {
-    assert(token.type == T.LParen || token.type == T.LBracket || token.type == T.Comma);
-    assert(terminator == T.RParen || terminator == T.RBracket);
-    Expression[] args;
-
-    nT();
-    if (token.type == terminator)
-    {
-      nT();
-      return null;
-    }
-
-    goto LenterLoop;
-    do
-    {
-      nT();
-    LenterLoop:
-      args ~= parseAssignExpression();
-    } while (token.type == T.Comma)
-
-    require(terminator);
-    return args;
-  }
-
-  Parameters parseParameterList()
-  out(params)
-  {
-    if (params.length > 1)
-      foreach (param; params.items[0..$-1])
-      {
-        if (param.isVariadic())
-          assert(0, "variadic arguments can only appear at the end of the parameter list.");
-      }
-  }
-  body
-  {
-    auto begin = token;
-    require(T.LParen);
-
-    auto params = new Parameters();
-
-    if (token.type == T.RParen)
-    {
-      nT();
-      return set(params, begin);
-    }
-
-    while (1)
-    {
-      auto paramBegin = token;
-      Token* stcTok;
-      StorageClass stc, tmp;
-
-      if (token.type == T.Ellipses)
-      {
-        nT();
-        params ~= set(new Parameter(null, null, null, null), paramBegin);
-        break; // Exit loop.
-      }
-
-    Lstc_loop:
-      switch (token.type)
-      {
-      version(D2)
-      {
-      case T.Invariant: // D2.0
-        if (peekNext() == T.LParen)
-          goto default;
-        tmp = StorageClass.Invariant;
-        goto Lcommon;
-      case T.Const: // D2.0
-        if (peekNext() == T.LParen)
-          goto default;
-        tmp = StorageClass.Const;
-        goto Lcommon;
-      case T.Final: // D2.0
-        tmp = StorageClass.Final;
-        goto Lcommon;
-      case T.Scope: // D2.0
-        tmp = StorageClass.Scope;
-        goto Lcommon;
-      case T.Static: // D2.0
-        tmp = StorageClass.Static;
-        goto Lcommon;
-      case T.In:
-        tmp = StorageClass.In;
-        goto Lcommon;
-      case T.Out:
-        tmp = StorageClass.Out;
-        goto Lcommon;
-      case T.Inout, T.Ref:
-        tmp = StorageClass.Ref;
-        goto Lcommon;
-      case T.Lazy:
-        tmp = StorageClass.Lazy;
-        goto Lcommon;
-      Lcommon:
-        if (stc & tmp)
-          error(MID.RedundantStorageClass, token.srcText);
-        else
-          stc |= tmp;
-        nT();
-        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;
-      }
-      default:
-      version(D2)
-      {
-        if (stc != StorageClass.None)
-          stcTok = begin;
-      }
-        Token* ident;
-        auto type = parseDeclarator(ident, true);
-
-        Expression assignExpr;
-        if (token.type == T.Assign)
-        {
-          nT();
-          assignExpr = 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.
-        }
-
-        params ~= set(new Parameter(stcTok, type, ident, assignExpr), paramBegin);
-
-        if (token.type != T.Comma)
-          break; // Exit loop.
-        nT();
-        continue;
-      }
-      break; // Exit loop.
-    }
-    require(T.RParen);
-    return set(params, begin);
-  }
-
-  TemplateArguments parseTemplateArguments()
-  {
-    auto begin = token;
-    auto args = new TemplateArguments;
-
-    require(T.LParen);
-    if (token.type != T.RParen)
-    {
-      while (1)
-      {
-        bool success;
-        auto typeArgument = try_(parseType(), success);
-        if (success)
-        {
-          // TemplateArgument:
-          //         Type
-          //         Symbol
-          args ~= typeArgument;
-        }
-        else
-        {
-          // TemplateArgument:
-          //         AssignExpression
-          args ~= parseAssignExpression();
-        }
-        if (token.type != T.Comma)
-          break; // Exit loop.
-        nT();
-      }
-    }
-    require(T.RParen);
-    set(args, begin);
-    return args;
-  }
-version(D2)
-{
-  TemplateArguments parseTemplateArguments2()
-  {
-    assert(token.type == T.Comma);
-    nT();
-    auto begin = token;
-    auto args = new TemplateArguments;
-
-    if (token.type != T.RParen)
-    {
-      while (1)
-      {
-        bool success;
-        auto typeArgument = try_(parseType(), success);
-        if (success)
-        {
-          // TemplateArgument:
-          //         Type
-          //         Symbol
-          args ~= typeArgument;
-        }
-        else
-        {
-          // TemplateArgument:
-          //         AssignExpression
-          args ~= parseAssignExpression();
-        }
-        if (token.type != T.Comma)
-          break; // Exit loop.
-        nT();
-      }
-    }
-    else
-      error(MID.ExpectedButFound, "Type/Expression", ")");
-    require(T.RParen);
-    set(args, begin);
-    return args;
-  }
-} // version(D2)
-  TemplateParameters parseTemplateParameterList()
-  {
-    auto begin = token;
-    auto tparams = new TemplateParameters;
-
-    require(T.LParen);
-    if (token.type == T.RParen)
-      return tparams;
-
-    while (1)
-    {
-      auto paramBegin = token;
-      TP tp;
-      Token* ident;
-      Type valueType;
-      Type specType, defType;
-      Expression specValue, defValue;
-
-      switch (token.type)
-      {
-      case T.Alias:
-        // TemplateAliasParameter:
-        //         alias Identifier
-        tp = TP.Alias;
-        nT(); // Skip alias keyword.
-        ident = requireId();
-        // : SpecializationType
-        if (token.type == T.Colon)
-        {
-          nT();
-          specType = parseType();
-        }
-        // = DefaultType
-        if (token.type == T.Assign)
-        {
-          nT();
-          defType = parseType();
-        }
-        break;
-      case T.Identifier:
-        ident = token;
-        switch (peekNext())
-        {
-        case T.Ellipses:
-          // TemplateTupleParameter:
-          //         Identifier ...
-          tp = TP.Tuple;
-          nT(); // Skip Identifier.
-          nT(); // Skip Ellipses.
-          // if (token.type == T.Comma)
-          //  error(); // TODO: issue error msg for variadic param not being last.
-          break;
-        case T.Comma, T.RParen, T.Colon, T.Assign:
-          // TemplateTypeParameter:
-          //         Identifier
-          tp = TP.Type;
-          nT(); // Skip Identifier.
-          // : SpecializationType
-          if (token.type == T.Colon)
-          {
-            nT();
-            specType = parseType();
-          }
-          // = DefaultType
-          if (token.type == T.Assign)
-          {
-            nT();
-            defType = parseType();
-          }
-          break;
-        default:
-          // TemplateValueParameter:
-          //         Declarator
-          ident = null;
-          goto LTemplateValueParameter;
-        }
-        break;
-      default:
-      LTemplateValueParameter:
-        // TemplateValueParameter:
-        //         Declarator
-        tp = TP.Value;
-        valueType = parseDeclarator(ident);
-        // : SpecializationValue
-        if (token.type == T.Colon)
-        {
-          nT();
-          specValue = parseCondExpression();
-        }
-        // = DefaultValue
-        if (token.type == T.Assign)
-        {
-          nT();
-          defValue = parseCondExpression();
-        }
-      }
-
-      tparams ~= set(new TemplateParameter(tp, valueType, ident, specType, defType, specValue, defValue), paramBegin);
-
-      if (token.type != T.Comma)
-        break;
-      nT();
-    }
-    require(T.RParen);
-    set(tparams, begin);
-    return tparams;
-  }
-
-  void expected(TOK tok)
-  {
-    if (token.type != tok)
-      error(MID.ExpectedButFound, Token.Token.toString(tok), token.srcText);
-  }
-
-  void require(TOK tok)
-  {
-    if (token.type == tok)
-      nT();
-    else
-      error(MID.ExpectedButFound, Token.Token.toString(tok), token.srcText);
-  }
-
-  void requireNext(TOK tok)
-  {
-    nT();
-    require(tok);
-  }
-
-  string requireIdentifier()
-  {
-    string identifier;
-    if (token.type == T.Identifier)
-    {
-      identifier = token.identifier;
-      nT();
-    }
-    else
-      error(MID.ExpectedButFound, "Identifier", token.srcText);
-    return identifier;
-  }
-
-  Token* requireId()
-  {
-    if (token.type == T.Identifier)
-    {
-      auto id = token;
-      nT();
-      return id;
-    }
-    else
-      error(MID.ExpectedButFound, "Identifier", token.srcText);
-    return null;
-  }
-
-  void error(MID id, ...)
-  {
-    if (trying)
-    {
-      ++errorCount;
-      return;
-    }
-
-//     if (errors.length == 10)
-//       return;
-    errors ~= new Information(InfoType.Parser, id, lx.loc, arguments(_arguments, _argptr));
-//     writefln("(%d)P: ", lx.loc, errors[$-1].getMsg);
-  }
-}
--- a/trunk/src/Settings.d	Tue Aug 21 16:18:02 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/++
-  Author: Aziz Köksal
-  License: GPL3
-+/
-module Settings;
-import Messages;
-import Parser, SyntaxTree, Declarations, Expressions;
-import std.metastrings;
-
-version(D2)
-{
-  const VERSION_MAJOR = 2;
-  const VERSION_MINOR = 0;
-}
-else
-{
-  const VERSION_MAJOR = 1;
-  const VERSION_MINOR = 0;
-}
-const string VERSION = Format!("%s.%s", VERSION_MAJOR, VERSION_MINOR);
-
-const COMPILED_WITH = __VENDOR__;
-const COMPILED_VERSION = Format!("%s.%s", __VERSION__/1000, __VERSION__%1000);
-const COMPILED_DATE = __TIMESTAMP__;
-
-const usageHighlight = "highlight (hl) file.d";
-
-struct GlobalSettings
-{
-static:
-  string language; /// Language of messages catalogue to load.
-  string[] messages; /// Table of localized compiler messages.
-  void load()
-  {
-    auto fileName = "config.d"[];
-    auto sourceText = cast(char[]) std.file.read(fileName);
-    auto parser = new Parser(sourceText, fileName);
-    parser.start();
-    auto root = parser.parseModule();
-
-    if (parser.errors.length || parser.lx.errors.length)
-    {
-      throw new Exception("There are errors in " ~ fileName ~ ".");
-    }
-
-    foreach (decl; root.children)
-    {
-      auto v = Cast!(VariableDeclaration)(decl);
-      if (v && v.idents[0].srcText == "language")
-      {
-        auto e = v.values[0];
-        if (!e)
-          throw new Exception("language variable has no value set.");
-        auto val = Cast!(StringLiteralsExpression)(e);
-        if (val)
-        {
-          GlobalSettings.language = val.getString();
-          break;
-        }
-      }
-    }
-
-    // Load messages
-    if (GlobalSettings.language.length)
-    {
-      fileName = "lang_" ~ GlobalSettings.language ~ ".d";
-      sourceText = cast(char[]) std.file.read(fileName);
-      parser = new Parser(sourceText, fileName);
-      parser.start();
-      root = parser.parseModule();
-
-      if (parser.errors.length || parser.lx.errors.length)
-      {
-        throw new Exception("There are errors in "~fileName~".");
-      }
-
-      char[][] messages;
-      foreach (decl; root.children)
-      {
-        auto v = Cast!(VariableDeclaration)(decl);
-        if (v && v.idents[0].srcText == "messages")
-        {
-          auto e = v.values[0];
-          if (!e)
-            throw new Exception("messages variable in "~fileName~" has no value set.");
-          if (auto array = Cast!(ArrayInitializer)(e))
-          {
-            foreach (value; array.values)
-            {
-              if (auto str = Cast!(StringLiteralsExpression)(value))
-                messages ~= str.getString();
-            }
-          }
-          else
-            throw new Exception("messages variable is set to "~e.classinfo.name~" instead of an ArrayInitializer.");
-        }
-      }
-      if (messages.length != MID.max+1)
-        throw new Exception(std.string.format("messages table in %s must exactly have %d entries, but %s were found.", fileName, MID.max, messages.length));
-      GlobalSettings.messages = messages;
-    }
-  }
-
-}
--- a/trunk/src/Statements.d	Tue Aug 21 16:18:02 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,567 +0,0 @@
-/++
-  Author: Aziz Köksal
-  License: GPL3
-+/
-module Statements;
-import SyntaxTree;
-import Expressions;
-import Declarations;
-import Types;
-import Token;
-
-abstract class Statement : Node
-{
-  this()
-  {
-    super(NodeCategory.Statement);
-  }
-}
-
-class Statements : Statement
-{
-  this()
-  {
-    mixin(set_kind);
-  }
-
-  void opCatAssign(Statement s)
-  {
-    this.children ~= s;
-  }
-}
-
-class IllegalStatement : Statement
-{
-  Token* tok;
-  this(Token* tok)
-  {
-    mixin(set_kind);
-    this.tok = tok;
-  }
-}
-
-class EmptyStatement : Statement
-{
-  this()
-  {
-    mixin(set_kind);
-  }
-}
-
-class FunctionBody : Node
-{
-  Statement funcBody, inBody, outBody;
-  Token* outIdent;
-  this()
-  {
-    super(NodeCategory.Other);
-    mixin(set_kind);
-  }
-
-  void finishConstruction()
-  {
-    if (funcBody)
-      this.children ~= funcBody;
-    if (inBody)
-      this.children ~= inBody;
-    if (outBody)
-      this.children ~= outBody;
-  }
-}
-
-class ScopeStatement : Statement
-{
-  Statement s;
-  this(Statement s)
-  {
-    mixin(set_kind);
-    this.children = [s];
-    this.s = s;
-  }
-}
-
-class LabeledStatement : Statement
-{
-  Token* label;
-  Statement s;
-  this(Token* label, Statement s)
-  {
-    mixin(set_kind);
-    this.children = [s];
-    this.label = label;
-    this.s = s;
-  }
-}
-
-class ExpressionStatement : Statement
-{
-  Expression expression;
-  this(Expression expression)
-  {
-    mixin(set_kind);
-    this.children = [expression];
-    this.expression = expression;
-  }
-}
-
-class DeclarationStatement : Statement
-{
-  Declaration declaration;
-  this(Declaration declaration)
-  {
-    mixin(set_kind);
-    this.children = [declaration];
-    this.declaration = declaration;
-  }
-}
-
-class IfStatement : Statement
-{
-  Statement variable; // AutoDeclaration or VariableDeclaration
-  Expression condition;
-  Statement ifBody;
-  Statement elseBody;
-  this(Statement variable, Expression condition, Statement ifBody, Statement elseBody)
-  {
-    mixin(set_kind);
-    if (variable)
-      this.children ~= variable;
-    else
-      this.children ~= condition;
-    this.children ~= ifBody;
-    if (elseBody)
-      this.children ~= elseBody;
-    this.variable = variable;
-    this.condition = condition;
-    this.ifBody = ifBody;
-    this.elseBody = elseBody;
-  }
-}
-
-class WhileStatement : Statement
-{
-  Expression condition;
-  Statement whileBody;
-  this(Expression condition, Statement whileBody)
-  {
-    mixin(set_kind);
-    this.children = [cast(Node)condition, whileBody];
-    this.condition = condition;
-    this.whileBody = whileBody;
-  }
-}
-
-class DoWhileStatement : Statement
-{
-  Expression condition;
-  Statement doBody;
-  this(Expression condition, Statement doBody)
-  {
-    mixin(set_kind);
-    this.children = [cast(Node)condition, doBody];
-    this.condition = condition;
-    this.doBody = doBody;
-  }
-}
-
-class ForStatement : Statement
-{
-  Statement init;
-  Expression condition, increment;
-  Statement forBody;
-
-  this(Statement init, Expression condition, Expression increment, Statement forBody)
-  {
-    mixin(set_kind);
-    if (init)
-      this.children ~= init;
-    if (condition)
-      this.children ~= condition;
-    if (increment)
-      this.children ~= increment;
-    this.children ~= forBody;
-    this.init = init;
-    this.condition = condition;
-    this.increment = increment;
-    this.forBody = forBody;
-  }
-}
-
-class ForeachStatement : Statement
-{
-  TOK tok;
-  Parameters params;
-  Expression aggregate;
-  Statement forBody;
-
-  this(TOK tok, Parameters params, Expression aggregate, Statement forBody)
-  {
-    mixin(set_kind);
-    this.children = [cast(Node)params, aggregate, forBody];
-    this.tok = tok;
-    this.params = params;
-    this.aggregate = aggregate;
-    this.forBody = forBody;
-  }
-}
-
-version(D2)
-{
-class ForeachRangeStatement : Statement
-{
-  TOK tok;
-  Parameters params;
-  Expression lower, upper;
-  Statement forBody;
-
-  this(TOK tok, Parameters params, Expression lower, Expression upper, Statement forBody)
-  {
-    mixin(set_kind);
-    this.children = [cast(Node)params, lower, upper, forBody];
-    this.tok = tok;
-    this.params = params;
-    this.lower = lower;
-    this.upper = upper;
-    this.forBody = forBody;
-  }
-}
-}
-
-class SwitchStatement : Statement
-{
-  Expression condition;
-  Statement switchBody;
-
-  this(Expression condition, Statement switchBody)
-  {
-    mixin(set_kind);
-    this.children = [cast(Node)condition, switchBody];
-    this.condition = condition;
-    this.switchBody = switchBody;
-  }
-}
-
-class CaseStatement : Statement
-{
-  Expression[] values;
-  Statement caseBody;
-
-  this(Expression[] values, Statement caseBody)
-  {
-    mixin(set_kind);
-    this.children = cast(Node[])values ~ [caseBody];
-    this.values = values;
-    this.caseBody = caseBody;
-  }
-}
-
-class DefaultStatement : Statement
-{
-  Statement defaultBody;
-  this(Statement defaultBody)
-  {
-    mixin(set_kind);
-    this.children = [defaultBody];
-    this.defaultBody = defaultBody;
-  }
-}
-
-class ContinueStatement : Statement
-{
-  Token* ident;
-  this(Token* ident)
-  {
-    mixin(set_kind);
-    this.ident = ident;
-  }
-}
-
-class BreakStatement : Statement
-{
-  Token* ident;
-  this(Token* ident)
-  {
-    mixin(set_kind);
-    this.ident = ident;
-  }
-}
-
-class ReturnStatement : Statement
-{
-  Expression expr;
-  this(Expression expr)
-  {
-    mixin(set_kind);
-    if (expr)
-      this.children = [expr];
-    this.expr = expr;
-  }
-}
-
-class GotoStatement : Statement
-{
-  Token* ident;
-  Expression caseExpr;
-  this(Token* ident, Expression caseExpr)
-  {
-    mixin(set_kind);
-    if (caseExpr)
-      this.children = [caseExpr];
-    this.ident = ident;
-    this.caseExpr = caseExpr;
-  }
-}
-
-class WithStatement : Statement
-{
-  Expression expr;
-  Statement withBody;
-  this(Expression expr, Statement withBody)
-  {
-    mixin(set_kind);
-    this.children = [cast(Node)expr, withBody];
-    this.expr = expr;
-    this.withBody = withBody;
-  }
-}
-
-class SynchronizedStatement : Statement
-{
-  Expression expr;
-  Statement syncBody;
-  this(Expression expr, Statement withBody)
-  {
-    mixin(set_kind);
-    this.children = [cast(Node)expr, syncBody];
-    this.expr = expr;
-    this.syncBody = syncBody;
-  }
-}
-
-class TryStatement : Statement
-{
-  Statement tryBody;
-  CatchBody[] catchBodies;
-  FinallyBody finallyBody;
-  this(Statement tryBody, CatchBody[] catchBodies, FinallyBody finallyBody)
-  {
-    mixin(set_kind);
-    this.children = [tryBody];
-    if (catchBodies.length)
-      this.children ~= catchBodies;
-    if (finallyBody)
-      this.children ~= finallyBody;
-    this.tryBody = tryBody;
-    this.catchBodies = catchBodies;
-    this.finallyBody = finallyBody;
-  }
-}
-
-class CatchBody : Statement
-{
-  Parameter param;
-  Statement catchBody;
-  this(Parameter param, Statement catchBody)
-  {
-    mixin(set_kind);
-    this.children = [cast(Node)param, catchBody];
-    this.param = param;
-    this.catchBody = catchBody;
-  }
-}
-
-class FinallyBody : Statement
-{
-  Statement finallyBody;
-  this(Statement finallyBody)
-  {
-    mixin(set_kind);
-    this.children = [finallyBody];
-    this.finallyBody = finallyBody;
-  }
-}
-
-class ScopeGuardStatement : Statement
-{
-  Token* condition;
-  Statement scopeBody;
-  this(Token* condition, Statement scopeBody)
-  {
-    mixin(set_kind);
-    this.children = [scopeBody];
-    this.condition = condition;
-    this.scopeBody = scopeBody;
-  }
-}
-
-class ThrowStatement : Statement
-{
-  Expression expr;
-  this(Expression expr)
-  {
-    mixin(set_kind);
-    this.children = [expr];
-    this.expr = expr;
-  }
-}
-
-class VolatileStatement : Statement
-{
-  Statement volatileBody;
-  this(Statement volatileBody)
-  {
-    mixin(set_kind);
-    if (volatileBody)
-      this.children = [volatileBody];
-    this.volatileBody = volatileBody;
-  }
-}
-
-class AsmStatement : Statement
-{
-  Statements statements;
-  this(Statements statements)
-  {
-    mixin(set_kind);
-    this.children = [statements];
-    this.statements = statements;
-  }
-}
-
-class AsmInstruction : Statement
-{
-  Token* ident;
-  Expression[] operands;
-  this(Token* ident, Expression[] operands)
-  {
-    mixin(set_kind);
-    this.children = operands;
-    this.ident = ident;
-    this.operands = operands;
-  }
-}
-
-class IllegalAsmInstruction : IllegalStatement
-{
-  this(Token* token)
-  {
-    super(token);
-    mixin(set_kind);
-  }
-}
-
-class PragmaStatement : Statement
-{
-  Token* ident;
-  Expression[] args;
-  Statement pragmaBody;
-  this(Token* ident, Expression[] args, Statement pragmaBody)
-  {
-    mixin(set_kind);
-    if (args.length)
-      this.children = args;
-    this.children ~= pragmaBody;
-    this.ident = ident;
-    this.args = args;
-    this.pragmaBody = pragmaBody;
-  }
-}
-
-class MixinStatement : Statement
-{
-  Expression[] templateIdents;
-  Token* mixinIdent;
-  this(Expression[] templateIdents, Token* mixinIdent)
-  {
-    mixin(set_kind);
-    this.children = templateIdents;
-    this.templateIdents = templateIdents;
-    this.mixinIdent = mixinIdent;
-  }
-}
-
-class StaticIfStatement : Statement
-{
-  Expression condition;
-  Statement ifBody, elseBody;
-  this(Expression condition, Statement ifBody, Statement elseBody)
-  {
-    mixin(set_kind);
-    this.children = [cast(Node)condition, ifBody];
-    if (elseBody)
-      this.children ~= elseBody;
-    this.condition = condition;
-    this.ifBody = ifBody;
-    this.elseBody = elseBody;
-  }
-}
-
-class StaticAssertStatement : Statement
-{
-  Expression condition, message;
-  this(Expression condition, Expression message)
-  {
-    mixin(set_kind);
-    this.children = [condition];
-    if (message)
-      this.children ~= message;
-    this.condition = condition;
-    this.message = message;
-  }
-}
-
-class DebugStatement : Statement
-{
-  Token* cond;
-  Statement debugBody, elseBody;
-  this(Token* cond, Statement debugBody, Statement elseBody)
-  {
-    mixin(set_kind);
-    this.children = [debugBody];
-    if (elseBody)
-      this.children ~= elseBody;
-    this.cond = cond;
-    this.debugBody = debugBody;
-    this.elseBody = elseBody;
-  }
-}
-
-class VersionStatement : Statement
-{
-  Token* cond;
-  Statement versionBody, elseBody;
-  this(Token* cond, Statement versionBody, Statement elseBody)
-  {
-    mixin(set_kind);
-    this.children = [versionBody];
-    if (elseBody)
-      this.children ~= [elseBody];
-    this.cond = cond;
-    this.versionBody = versionBody;
-    this.elseBody = elseBody;
-  }
-}
-
-class AttributeStatement : Statement
-{
-  TOK tok;
-  Statement statement;
-  this(TOK tok, Statement statement)
-  {
-    mixin(set_kind);
-    this.children = [statement];
-    this.tok = tok;
-    this.statement = statement;
-  }
-}
-
-class ExternStatement : AttributeStatement
-{
-  Linkage linkage;
-  this(Linkage linkage, Statement statement)
-  {
-    super(TOK.Extern, statement);
-    mixin(set_kind);
-    this.linkage = linkage;
-  }
-}
--- a/trunk/src/SyntaxTree.d	Tue Aug 21 16:18:02 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/++
-  Author: Aziz Köksal
-  License: GPL3
-+/
-module SyntaxTree;
-import Token;
-
-enum NodeCategory
-{
-  Declaration,
-  Statement,
-  Expression,
-  Type,
-  Other
-}
-
-enum NodeKind
-{
-  // Declarations:
-  Declarations,
-  EmptyDeclaration,
-  IllegalDeclaration,
-  ModuleDeclaration,
-  ImportDeclaration,
-  AliasDeclaration,
-  TypedefDeclaration,
-  EnumDeclaration,
-  ClassDeclaration,
-  InterfaceDeclaration,
-  StructDeclaration,
-  UnionDeclaration,
-  ConstructorDeclaration,
-  StaticConstructorDeclaration,
-  DestructorDeclaration,
-  StaticDestructorDeclaration,
-  FunctionDeclaration,
-  VariableDeclaration,
-  InvariantDeclaration,
-  UnittestDeclaration,
-  DebugDeclaration,
-  VersionDeclaration,
-  StaticIfDeclaration,
-  StaticAssertDeclaration,
-  TemplateDeclaration,
-  NewDeclaration,
-  DeleteDeclaration,
-  AttributeDeclaration,
-  ExternDeclaration,
-  AlignDeclaration,
-  PragmaDeclaration,
-  MixinDeclaration,
-
-  // Statements:
-  Statements,
-  IllegalStatement,
-  EmptyStatement,
-  ScopeStatement,
-  LabeledStatement,
-  ExpressionStatement,
-  DeclarationStatement,
-  IfStatement,
-  ConditionalStatement,
-  WhileStatement,
-  DoWhileStatement,
-  ForStatement,
-  ForeachStatement,
-  ForeachRangeStatement, // D2.0
-  SwitchStatement,
-  CaseStatement,
-  DefaultStatement,
-  ContinueStatement,
-  BreakStatement,
-  ReturnStatement,
-  GotoStatement,
-  WithStatement,
-  SynchronizedStatement,
-  TryStatement,
-  CatchBody,
-  FinallyBody,
-  ScopeGuardStatement,
-  ThrowStatement,
-  VolatileStatement,
-  AsmStatement,
-  AsmInstruction,
-  IllegalAsmInstruction,
-  PragmaStatement,
-  MixinStatement,
-  StaticIfStatement,
-  StaticAssertStatement,
-  DebugStatement,
-  VersionStatement,
-  AttributeStatement,
-  ExternStatement,
-
-  // Expressions:
-  EmptyExpression,
-  BinaryExpression,
-  CondExpression,
-  CommaExpression,
-  OrOrExpression,
-  AndAndExpression,
-  OrExpression,
-  XorExpression,
-  AndExpression,
-  CmpExpression,
-  EqualExpression,
-  IdentityExpression,
-  RelExpression,
-  InExpression,
-  LShiftExpression,
-  RShiftExpression,
-  URShiftExpression,
-  PlusExpression,
-  MinusExpression,
-  CatExpression,
-  MulExpression,
-  DivExpression,
-  ModExpression,
-  AssignExpression,
-  LShiftAssignExpression,
-  RShiftAssignExpression,
-  URShiftAssignExpression,
-  OrAssignExpression,
-  AndAssignExpression,
-  PlusAssignExpression,
-  MinusAssignExpression,
-  DivAssignExpression,
-  MulAssignExpression,
-  ModAssignExpression,
-  XorAssignExpression,
-  CatAssignExpression,
-  UnaryExpression,
-  AddressExpression,
-  PreIncrExpression,
-  PreDecrExpression,
-  PostIncrExpression,
-  PostDecrExpression,
-  DerefExpression,
-  SignExpression,
-  NotExpression,
-  CompExpression,
-  PostDotListExpression,
-  CallExpression,
-  NewExpression,
-  NewAnonClassExpression,
-  DeleteExpression,
-  CastExpression,
-  IndexExpression,
-  SliceExpression,
-  PrimaryExpressio,
-  IdentifierExpression,
-  SpecialTokenExpression,
-  DotListExpression,
-  TemplateInstanceExpression,
-  ThisExpression,
-  SuperExpression,
-  NullExpression,
-  DollarExpression,
-  BoolExpression,
-  IntNumberExpression,
-  RealNumberExpression,
-  CharLiteralExpression,
-  StringLiteralsExpression,
-  ArrayLiteralExpression,
-  AssocArrayLiteralExpression,
-  AssertExpression,
-  MixinExpression,
-  ImportExpression,
-  TypeofExpression,
-  TypeDotIdExpression,
-  TypeidExpression,
-  IsExpression,
-  FunctionLiteralExpression,
-  TraitsExpression, // D2.0
-  VoidInitializer,
-  ArrayInitializer,
-  StructInitializer,
-  AsmTypeExpression,
-  AsmOffsetExpression,
-  AsmSegExpression,
-  AsmPostBracketExpression,
-  AsmBracketExpression,
-  AsmLocalSizeExpression,
-  AsmRegisterExpression,
-
-  // Types:
-  IntegralType,
-  UndefinedType,
-  DotListType,
-  IdentifierType,
-  TypeofType,
-  TemplateInstanceType,
-  PointerType,
-  ArrayType,
-  FunctionType,
-  DelegateType,
-  ConstType, // D2.0
-  InvariantType, // D2.0
-
-  // Other:
-  FunctionBody,
-  Parameter,
-  Parameters,
-  BaseClass,
-  TemplateParameter,
-  TemplateParameters,
-  TemplateArguments,
-}
-
-/// This string is mixed into the constructor of a class that inherits from Node.
-const string set_kind = `this.kind = mixin("NodeKind." ~ typeof(this).stringof);`;
-
-Class Cast(Class)(Node n)
-{
-  assert(n !is null);
-  if (n.kind == mixin("NodeKind." ~ typeof(Class).stringof))
-    return cast(Class)cast(void*)n;
-  return null;
-}
-
-class Node
-{
-  NodeCategory category;
-  NodeKind kind;
-  Node[] children;
-  Token* begin, end;
-
-  this(NodeCategory category)
-  {
-    this.category = category;
-  }
-
-  void setTokens(Token* begin, Token* end)
-  {
-    this.begin = begin;
-    this.end = end;
-  }
-}
--- a/trunk/src/Token.d	Tue Aug 21 16:18:02 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-/++
-  Author: Aziz Köksal
-  License: GPL3
-+/
-module Token;
-import std.c.stdlib : malloc, free;
-import std.outofmemory;
-
-struct Position
-{
-  size_t loc;
-  size_t col;
-}
-
-enum TOK : ushort
-{
-  Invalid,
-
-  /// Flag for whitespace tokens that must be ignored in the parsing phase.
-  Whitespace = 0x8000,
-  Comment = 1 | Whitespace,
-  Shebang = 2 | Whitespace,
-  HashLine = 3 | Whitespace,
-  Filespec = 4 | Whitespace,
-
-  Identifier = 5,
-  String,
-  Special,
-  CharLiteral, WCharLiteral, DCharLiteral,
-
-  // Numbers
-  Int32, Int64, Uint32, Uint64,
-  // Floating point number scanner relies on this order. (FloatXY + 3 == ImaginaryXY)
-  Float32, Float64, Float80,
-  Imaginary32, Imaginary64, Imaginary80,
-
-
-  // Brackets
-  LParen,
-  RParen,
-  LBracket,
-  RBracket,
-  LBrace,
-  RBrace,
-
-  Dot, Slice, Ellipses,
-
-  // Floating point number operators
-  Unordered,
-  UorE,
-  UorG,
-  UorGorE,
-  UorL,
-  UorLorE,
-  LorEorG,
-  LorG,
-
-  // Normal operators
-  Assign, Equal, NotEqual, Not,
-  LessEqual, Less,
-  GreaterEqual, Greater,
-  LShiftAssign, LShift,
-  RShiftAssign,RShift,
-  URShiftAssign, URShift,
-  OrAssign, OrLogical, OrBinary,
-  AndAssign, AndLogical, AndBinary,
-  PlusAssign, PlusPlus, Plus,
-  MinusAssign, MinusMinus, Minus,
-  DivAssign, Div,
-  MulAssign, Mul,
-  ModAssign, Mod,
-  XorAssign, Xor,
-  CatAssign, Catenate,
-  Tilde,
-  Identity, NotIdentity,
-
-  Colon,
-  Semicolon,
-  Question,
-  Comma,
-  Dollar,
-
-  /* Keywords:
-     NB.: Token.isKeyword() depends on this list being contiguous.
-  */
-  Abstract,Alias,Align,Asm,Assert,Auto,Body,
-  Bool,Break,Byte,Case,Cast,Catch,Cdouble,
-  Cent,Cfloat,Char,Class,Const,Continue,Creal,
-  Dchar,Debug,Default,Delegate,Delete,Deprecated,Do,
-  Double,Else,Enum,Export,Extern,False,Final,
-  Finally,Float,For,Foreach,Foreach_reverse,Function,Goto,
-  Idouble,If,Ifloat,Import,In,Inout,Int,
-  Interface,Invariant,Ireal,Is,Lazy,Long,Macro/+D2.0+/,
-  Mixin,Module,New,Null,Out,Override,Package,
-  Pragma,Private,Protected,Public,Real,Ref/+D2.0+/,Return,
-  Scope,Short,Static,Struct,Super,Switch,Synchronized,
-  Template,This,Throw,Traits/+D2.0+/,True,Try,Typedef,Typeid,
-  Typeof,Ubyte,Ucent,Uint,Ulong,Union,Unittest,
-  Ushort,Version,Void,Volatile,Wchar,While,With,
-
-  HEAD, // start of linked list
-  EOF
-}
-
-alias TOK.Abstract KeywordsBegin;
-alias TOK.With KeywordsEnd;
-
-struct Token
-{
-  TOK type;
-//   Position pos;
-
-  Token* next, prev;
-
-  char* start;
-  char* end;
-
-  union
-  {
-    struct
-    {
-      Token* line_num; // #line number
-      Token* line_filespec; // #line number filespec
-    }
-    struct
-    {
-      string str;
-      char pf;
-    }
-    dchar  dchar_;
-    long   long_;
-    ulong  ulong_;
-    int    int_;
-    uint   uint_;
-    float  float_;
-    double double_;
-    real   real_;
-  }
-
-  alias srcText identifier;
-
-  string srcText()
-  {
-    assert(start && end);
-    return start[0 .. end - start];
-  }
-
-  static string toString(TOK tok)
-  {
-    return tokToString[tok];
-  }
-
-  bool isKeyword()
-  {
-    return KeywordsBegin <= type && type <= KeywordsEnd;
-  }
-
-  bool isWhitespace()
-  {
-    return !!(type & TOK.Whitespace);
-  }
-
-  int opEquals(TOK type2)
-  {
-    return type == type2;
-  }
-
-  new(size_t size)
-  {
-    void* p = malloc(size);
-    if (p is null)
-      throw new OutOfMemoryException();
-    *cast(Token*)p = Token.init;
-    return p;
-  }
-
-  delete(void* p)
-  {
-    free(p);
-  }
-}
-
-string[] tokToString = [
-  "Invalid",
-
-  "Comment",
-  "#! /shebang/",
-  "#line",
-
-  "Identifier",
-  "String",
-  "Special",
-  "CharLiteral", "WCharLiteral", "DCharLiteral",
-
-  "Int32", "Int64", "Uint32", "Uint64",
-  "Float32", "Float64", "Float80",
-  "Imaginary32", "Imaginary64", "Imaginary80",
-
-  "(",
-  ")",
-  "[",
-  "]",
-  "{",
-  "}",
-
-  ".", "..", "...",
-
-  "Unordered",
-  "UorE",
-  "UorG",
-  "UorGorE",
-  "UorL",
-  "UorLorE",
-  "LorEorG",
-  "LorG",
-
-  "=", "==", "!=", "!",
-  "<=", "<",
-  ">=", ">",
-  "<<=", "<<",
-  ">>=",">>",
-  ">>>=", ">>>",
-  "|=", "||", "|",
-  "&=", "&&", "&",
-  "+=", "++", "+",
-  "-=", "--", "-",
-  "/=", "/",
-  "*=", "*",
-  "%=", "%",
-  "^=", "^",
-  "~=", "~",
-  "~",
-  "is", "!is",
-
-  ":",
-  ";",
-  "?",
-  ",",
-  "$",
-
-  "abstract","alias","align","asm","assert","auto","body",
-  "bool","break","byte","case","cast","catch","cdouble",
-  "cent","cfloat","char","class","const","continue","creal",
-  "dchar","debug","default","delegate","delete","deprecated","do",
-  "double","else","enum","export","extern","false","final",
-  "finally","float","for","foreach","foreach_reverse","function","goto",
-  "idouble","if","ifloat","import","in","inout","int",
-  "interface","invariant","ireal","is","lazy","long","macro",
-  "mixin","module","new","null","out","override","package",
-  "pragma","private","protected","public","real","ref","return",
-  "scope","short","static","struct","super","switch","synchronized",
-  "template","this","throw","true","try","typedef","typeid",
-  "typeof","ubyte","ucent","uint","ulong","union","unittest",
-  "ushort","version","void","volatile","wchar","while","with",
-
-  "EOF"
-];
--- a/trunk/src/Types.d	Tue Aug 21 16:18:02 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,426 +0,0 @@
-/++
-  Author: Aziz Köksal
-  License: GPL3
-+/
-module Types;
-import SyntaxTree;
-import Token;
-import Expressions;
-
-enum Linkage
-{
-  Invalid,
-  C,
-  Cpp,
-  D,
-  Windows,
-  Pascal,
-  System
-}
-
-enum StorageClass
-{
-  None         = 0,
-  Abstract     = 1,
-  Auto         = 1<<2,
-  Const        = 1<<3,
-  Deprecated   = 1<<4,
-  Extern       = 1<<5,
-  Final        = 1<<6,
-  Invariant    = 1<<7,
-  Override     = 1<<8,
-  Scope        = 1<<9,
-  Static       = 1<<10,
-  Synchronized = 1<<11,
-  In           = 1<<12,
-  Out          = 1<<13,
-  Ref          = 1<<14,
-  Lazy         = 1<<15,
-  Variadic     = 1<<16,
-}
-
-class Parameter : Node
-{
-  StorageClass stc;
-  Token* stcTok;
-  Type type;
-  Token* ident;
-  Expression assignExpr;
-
-  this(Token* stcTok, Type type, Token* ident, Expression assignExpr)
-  {
-    super(NodeCategory.Other);
-    mixin(set_kind);
-    if (type) // type can be null when param in foreach statement
-      this.children = [type];
-    if (assignExpr)
-      this.children ~= 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;
-  }
-
-  bool isVariadic()
-  {
-    return !!(stc & StorageClass.Variadic);
-  }
-
-  bool isOnlyVariadic()
-  {
-    return stc == StorageClass.Variadic;
-  }
-}
-
-class Parameters : Node
-{
-  this()
-  {
-    super(NodeCategory.Other);
-    mixin(set_kind);
-  }
-
-  bool hasVariadic()
-  {
-    if (children.length != 0)
-      return items[$-1].isVariadic();
-    return false;
-  }
-
-  void opCatAssign(Parameter param)
-  { children ~= param; }
-
-  Parameter[] items()
-  { return cast(Parameter[])children; }
-
-  size_t length()
-  { return children.length; }
-}
-
-
-enum Protection
-{
-  None,
-  Private   = 1,
-  Protected = 1<<1,
-  Package   = 1<<2,
-  Public    = 1<<3,
-  Export    = 1<<4
-}
-
-class BaseClass : Node
-{
-  Protection prot;
-  Type type;
-  this(Protection prot, Type type)
-  {
-    super(NodeCategory.Other);
-    mixin(set_kind);
-    this.children = [type];
-    this.prot = prot;
-    this.type = type;
-  }
-}
-
-enum TP
-{
-  Type,
-  Value,
-  Alias,
-  Tuple
-}
-
-class TemplateParameter : Node
-{
-  TP tp;
-  Type valueType;
-  Token* ident;
-  Type specType, defType;
-  Expression specValue, defValue;
-  this(TP tp, Type valueType, Token* ident, Type specType, Type defType, Expression specValue, Expression defValue)
-  {
-    super(NodeCategory.Other);
-    mixin(set_kind);
-    if (valueType)
-      this.children ~= valueType;
-    if (specType)
-      this.children ~= specType;
-    if (defType)
-      this.children ~= defType;
-    if (specValue)
-      this.children ~= specValue;
-    if (defValue)
-      this.children ~= defValue;
-    this.tp = tp;
-    this.valueType = valueType;
-    this.ident = ident;
-    this.specType = specType;
-    this.defType = defType;
-    this.specValue = specValue;
-    this.defValue = defValue;
-  }
-}
-
-class TemplateParameters : Node
-{
-  this()
-  {
-    super(NodeCategory.Other);
-    mixin(set_kind);
-  }
-
-  void opCatAssign(TemplateParameter parameter)
-  {
-    this.children ~= parameter;
-  }
-
-  TemplateParameter[] items()
-  {
-    return cast(TemplateParameter[])children;
-  }
-}
-
-class TemplateArguments : Node
-{
-  this()
-  {
-    super(NodeCategory.Other);
-    mixin(set_kind);
-  }
-
-  void opCatAssign(Node argument)
-  {
-    this.children ~= argument;
-  }
-}
-
-enum TID
-{
-  Void    = TOK.Void,
-  Char    = TOK.Char,
-  Wchar   = TOK.Wchar,
-  Dchar   = TOK.Dchar,
-  Bool    = TOK.Bool,
-  Byte    = TOK.Byte,
-  Ubyte   = TOK.Ubyte,
-  Short   = TOK.Short,
-  Ushort  = TOK.Ushort,
-  Int     = TOK.Int,
-  Uint    = TOK.Uint,
-  Long    = TOK.Long,
-  Ulong   = TOK.Ulong,
-  Float   = TOK.Float,
-  Double  = TOK.Double,
-  Real    = TOK.Real,
-  Ifloat  = TOK.Ifloat,
-  Idouble = TOK.Idouble,
-  Ireal   = TOK.Ireal,
-  Cfloat  = TOK.Cfloat,
-  Cdouble = TOK.Cdouble,
-  Creal   = TOK.Creal,
-
-  Undefined,
-  Function,
-  Delegate,
-  Pointer,
-  Array,
-  DotList,
-  Identifier,
-  Typeof,
-  TemplateInstance,
-  Const, // D2
-  Invariant, // D2
-}
-
-abstract class Type : Node
-{
-  TID tid;
-  Type next;
-
-  this(TID tid)
-  {
-    this(tid, null);
-  }
-
-  this(TID tid, Type next)
-  {
-    super(NodeCategory.Type);
-    if (next)
-      this.children ~= next;
-    this.tid = tid;
-    this.next = next;
-  }
-}
-
-class IntegralType : Type
-{
-  this(TOK tok)
-  {
-    super(cast(TID)tok);
-    mixin(set_kind);
-  }
-}
-
-class UndefinedType : Type
-{
-  this()
-  {
-    super(TID.Undefined);
-    mixin(set_kind);
-  }
-}
-
-class DotListType : Type
-{
-  Type[] dotList;
-  this(Type[] dotList)
-  {
-    super(TID.DotList);
-    mixin(set_kind);
-    this.children ~= dotList;
-    this.dotList = dotList;
-  }
-}
-
-class IdentifierType : Type
-{
-  Token* ident;
-  this(Token* ident)
-  {
-    super(TID.Identifier);
-    mixin(set_kind);
-    this.ident = ident;
-  }
-}
-
-class TypeofType : Type
-{
-  Expression e;
-  this(Expression e)
-  {
-    super(TID.Typeof);
-    mixin(set_kind);
-    this.children ~= e;
-    this.e = e;
-  }
-}
-
-class TemplateInstanceType : Type
-{
-  Token* ident;
-  TemplateArguments targs;
-  this(Token* ident, TemplateArguments targs)
-  {
-    super(TID.TemplateInstance);
-    mixin(set_kind);
-    this.children ~= targs;
-    this.ident = ident;
-    this.targs = targs;
-  }
-}
-
-class PointerType : Type
-{
-  this(Type t)
-  {
-    super(TID.Pointer, t);
-    mixin(set_kind);
-  }
-}
-
-class ArrayType : Type
-{
-  Expression e, e2;
-  Type assocType;
-  this(Type t)
-  {
-    super(TID.Array, t);
-    mixin(set_kind);
-  }
-  this(Type t, Expression e, Expression e2)
-  {
-    this.children = [e];
-    if (e2)
-      this.children ~= e2;
-    this.e = e;
-    this.e2 = e2;
-    this(t);
-  }
-  this(Type t, Type assocType)
-  {
-    this.children = [assocType];
-    this.assocType = assocType;
-    this(t);
-  }
-}
-
-class FunctionType : Type
-{
-  Type returnType;
-  Parameters parameters;
-  this(Type returnType, Parameters parameters)
-  {
-    super(TID.Function);
-    mixin(set_kind);
-    this.children = [cast(Node)returnType, parameters];
-    this.returnType = returnType;
-    this.parameters = parameters;
-  }
-}
-
-class DelegateType : Type
-{
-  Type returnType;
-  Parameters parameters;
-  this(Type returnType, Parameters parameters)
-  {
-    super(TID.Delegate);
-    mixin(set_kind);
-    this.children = [cast(Node)returnType, parameters];
-    this.returnType = returnType;
-    this.parameters = parameters;
-  }
-}
-
-version(D2)
-{
-class ConstType : Type
-{
-  this(Type t)
-  {
-    // If t is null: cast(const)
-    super(TID.Const, t);
-    mixin(set_kind);
-  }
-}
-
-class InvariantType : Type
-{
-  this(Type t)
-  {
-    // If t is null: cast(invariant)
-    super(TID.Invariant, t);
-    mixin(set_kind);
-  }
-}
-} // version(D2)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/Declarations.d	Tue Aug 21 16:28:05 2007 +0000
@@ -0,0 +1,526 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module Declarations;
+import SyntaxTree;
+import Expressions;
+import Types;
+import Statements;
+import Token;
+
+abstract class Declaration : Node
+{
+  bool hasBody;
+  this(bool hasBody)
+  {
+    super(NodeCategory.Declaration);
+    this.hasBody = hasBody;
+  }
+}
+
+class Declarations : Declaration
+{
+  this()
+  {
+    super(true);
+    mixin(set_kind);
+  }
+
+  void opCatAssign(Declaration d)
+  {
+    this.children ~= d;
+  }
+
+  void opCatAssign(Declarations ds)
+  {
+    this.children ~= ds.children;
+  }
+}
+
+class EmptyDeclaration : Declaration
+{
+  this()
+  {
+    super(false);
+    mixin(set_kind);
+  }
+}
+
+class IllegalDeclaration : Declaration
+{
+  Token* token;
+  this(Token* token)
+  {
+    super(false);
+    mixin(set_kind);
+    this.token = token;
+  }
+}
+
+alias Token*[] ModuleName; // Identifier(.Identifier)*
+
+class ModuleDeclaration : Declaration
+{
+  ModuleName moduleName; // module name sits at end of array
+  this(ModuleName moduleName)
+  {
+    super(false);
+    mixin(set_kind);
+    this.moduleName = moduleName;
+  }
+}
+
+class ImportDeclaration : Declaration
+{
+  ModuleName[] moduleNames;
+  Token*[] moduleAliases;
+  Token*[] bindNames;
+  Token*[] bindAliases;
+  this(ModuleName[] moduleNames, Token*[] moduleAliases, Token*[] bindNames, Token*[] bindAliases)
+  {
+    super(false);
+    mixin(set_kind);
+    this.moduleNames = moduleNames;
+    this.moduleAliases = moduleAliases;
+    this.bindNames = bindNames;
+    this.bindAliases = bindAliases;
+  }
+}
+
+class AliasDeclaration : Declaration
+{
+  Declaration decl;
+  this(Declaration decl)
+  {
+    super(false);
+    mixin(set_kind);
+    this.children = [decl];
+    this.decl = decl;
+  }
+}
+
+class TypedefDeclaration : Declaration
+{
+  Declaration decl;
+  this(Declaration decl)
+  {
+    super(false);
+    mixin(set_kind);
+    this.children = [decl];
+    this.decl = decl;
+  }
+}
+
+class EnumDeclaration : Declaration
+{
+  Token* name;
+  Type baseType;
+  Token*[] members;
+  Expression[] values;
+  this(Token* name, Type baseType, Token*[] members, Expression[] values, bool hasBody)
+  {
+    super(hasBody);
+    mixin(set_kind);
+    if (baseType)
+      this.children = [baseType];
+    foreach(value; values)
+      if (value)
+        this.children ~= value;
+    this.name = name;
+    this.baseType = baseType;
+    this.members = members;
+    this.values = values;
+  }
+}
+
+class ClassDeclaration : Declaration
+{
+  Token* name;
+  TemplateParameters tparams;
+  BaseClass[] bases;
+  Declarations decls;
+  this(Token* name, TemplateParameters tparams, BaseClass[] bases, Declarations decls, bool hasBody)
+  {
+    super(hasBody);
+    mixin(set_kind);
+    if (tparams)
+      this.children = [tparams];
+    if (bases.length)
+      this.children ~= bases;
+    this.children ~= decls;
+
+    this.name = name;
+    this.tparams = tparams;
+    this.bases = bases;
+    this.decls = decls;
+  }
+}
+
+class InterfaceDeclaration : Declaration
+{
+  Token* name;
+  TemplateParameters tparams;
+  BaseClass[] bases;
+  Declarations decls;
+  this(Token* name, TemplateParameters tparams, BaseClass[] bases, Declarations decls, bool hasBody)
+  {
+    super(hasBody);
+    mixin(set_kind);
+    if (tparams)
+      this.children = [tparams];
+    if (bases.length)
+      this.children ~= bases;
+    this.children ~= decls;
+
+    this.name = name;
+    this.tparams = tparams;
+    this.bases = bases;
+    this.decls = decls;
+  }
+}
+
+class StructDeclaration : Declaration
+{
+  Token* name;
+  TemplateParameters tparams;
+  Declarations decls;
+  this(Token* name, TemplateParameters tparams, Declarations decls, bool hasBody)
+  {
+    super(hasBody);
+    mixin(set_kind);
+    if (tparams)
+      this.children = [tparams];
+    this.children ~= decls;
+
+    this.name = name;
+    this.tparams = tparams;
+    this.decls = decls;
+  }
+}
+
+class UnionDeclaration : Declaration
+{
+  Token* name;
+  TemplateParameters tparams;
+  Declarations decls;
+  this(Token* name, TemplateParameters tparams, Declarations decls, bool hasBody)
+  {
+    super(hasBody);
+    mixin(set_kind);
+    if (tparams)
+      this.children = [tparams];
+    this.children ~= decls;
+
+    this.name = name;
+    this.tparams = tparams;
+    this.decls = decls;
+  }
+}
+
+class ConstructorDeclaration : Declaration
+{
+  Parameters parameters;
+  FunctionBody funcBody;
+  this(Parameters parameters, FunctionBody funcBody)
+  {
+    super(true);
+    mixin(set_kind);
+    this.children = [cast(Node)parameters, funcBody];
+    this.parameters = parameters;
+    this.funcBody = funcBody;
+  }
+}
+
+class StaticConstructorDeclaration : Declaration
+{
+  FunctionBody funcBody;
+  this(FunctionBody funcBody)
+  {
+    super(true);
+    mixin(set_kind);
+    this.children = [funcBody];
+    this.funcBody = funcBody;
+  }
+}
+
+class DestructorDeclaration : Declaration
+{
+  FunctionBody funcBody;
+  this(FunctionBody funcBody)
+  {
+    super(true);
+    mixin(set_kind);
+    this.children = [funcBody];
+    this.funcBody = funcBody;
+  }
+}
+
+class StaticDestructorDeclaration : Declaration
+{
+  FunctionBody funcBody;
+  this(FunctionBody funcBody)
+  {
+    super(true);
+    mixin(set_kind);
+    this.children = [funcBody];
+    this.funcBody = funcBody;
+  }
+}
+
+class FunctionDeclaration : Declaration
+{
+  Type returnType;
+  Token* funcName;
+  TemplateParameters tparams;
+  Parameters params;
+  FunctionBody funcBody;
+  this(Type returnType, Token* funcName, TemplateParameters tparams, Parameters params, FunctionBody funcBody)
+  {
+    assert(returnType !is null);
+    super(funcBody.funcBody !is null);
+    mixin(set_kind);
+    this.children = [returnType];
+    if (tparams)
+      this.children ~= tparams;
+    this.children ~= [cast(Node)params, funcBody];
+    this.returnType = returnType;
+    this.funcName = funcName;
+    this.tparams = tparams;
+    this.params = params;
+    this.funcBody = funcBody;
+  }
+}
+
+class VariableDeclaration : Declaration
+{
+  Type type;
+  Token*[] idents;
+  Expression[] values;
+  this(Type type, Token*[] idents, Expression[] values)
+  {
+    super(false);
+    mixin(set_kind);
+    if (type)
+      this.children = [type];
+    foreach(value; values)
+      if (value)
+        this.children ~= value;
+    this.type = type;
+    this.idents = idents;
+    this.values = values;
+  }
+}
+
+class InvariantDeclaration : Declaration
+{
+  FunctionBody funcBody;
+  this(FunctionBody funcBody)
+  {
+    super(true);
+    mixin(set_kind);
+    this.children = [funcBody];
+    this.funcBody = funcBody;
+  }
+}
+
+class UnittestDeclaration : Declaration
+{
+  FunctionBody funcBody;
+  this(FunctionBody funcBody)
+  {
+    super(true);
+    mixin(set_kind);
+    this.children = [funcBody];
+    this.funcBody = funcBody;
+  }
+}
+
+class DebugDeclaration : Declaration
+{
+  Token* spec;
+  Token* cond;
+  Declaration decls, elseDecls;
+
+  this(Token* spec, Token* cond, Declaration decls, Declaration elseDecls)
+  {
+    super(true /+decls.length != 0+/);
+    mixin(set_kind);
+    if (decls)
+      this.children = [decls];
+    if (elseDecls)
+      this.children ~= elseDecls;
+    this.spec = spec;
+    this.cond = cond;
+    this.decls = decls;
+    this.elseDecls = elseDecls;
+  }
+}
+
+class VersionDeclaration : Declaration
+{
+  Token* spec;
+  Token* cond;
+  Declaration decls, elseDecls;
+
+  this(Token* spec, Token* cond, Declaration decls, Declaration elseDecls)
+  {
+    super(true /+decls.length != 0+/);
+    mixin(set_kind);
+    if (decls)
+      this.children = [decls];
+    if (elseDecls)
+      this.children ~= elseDecls;
+    this.spec = spec;
+    this.cond = cond;
+    this.decls = decls;
+    this.elseDecls = elseDecls;
+  }
+}
+
+class StaticIfDeclaration : Declaration
+{
+  Expression condition;
+  Declaration ifDecls, elseDecls;
+  this(Expression condition, Declaration ifDecls, Declaration elseDecls)
+  {
+    super(true);
+    mixin(set_kind);
+    this.children = [cast(Node)condition, ifDecls, elseDecls];
+    this.condition = condition;
+    this.ifDecls = ifDecls;
+    this.elseDecls = elseDecls;
+  }
+}
+
+class StaticAssertDeclaration : Declaration
+{
+  Expression condition, message;
+  this(Expression condition, Expression message)
+  {
+    super(true);
+    mixin(set_kind);
+    this.children = [condition];
+    if (message)
+      this.children ~= message;
+    this.condition = condition;
+    this.message = message;
+  }
+}
+
+class TemplateDeclaration : Declaration
+{
+  Token* name;
+  TemplateParameters tparams;
+  Declarations decls;
+  this(Token* name, TemplateParameters tparams, Declarations decls)
+  {
+    super(true);
+    mixin(set_kind);
+    this.children = [cast(Node)tparams, decls];
+    this.name = name;
+    this.tparams = tparams;
+    this.decls = decls;
+  }
+}
+
+class NewDeclaration : Declaration
+{
+  Parameters parameters;
+  FunctionBody funcBody;
+  this(Parameters parameters, FunctionBody funcBody)
+  {
+    super(true);
+    mixin(set_kind);
+    this.children = [cast(Node)parameters, funcBody];
+    this.parameters = parameters;
+    this.funcBody = funcBody;
+  }
+}
+
+class DeleteDeclaration : Declaration
+{
+  Parameters parameters;
+  FunctionBody funcBody;
+  this(Parameters parameters, FunctionBody funcBody)
+  {
+    super(true);
+    mixin(set_kind);
+    this.children = [cast(Node)parameters, funcBody];
+    this.parameters = parameters;
+    this.funcBody = funcBody;
+  }
+}
+
+class AttributeDeclaration : Declaration
+{
+  TOK attribute;
+  Declaration decls;
+  this(TOK attribute, Declaration decls)
+  {
+    super(true);
+    mixin(set_kind);
+    this.children = [decls];
+    this.attribute = attribute;
+    this.decls = decls;
+  }
+}
+
+class ExternDeclaration : AttributeDeclaration
+{
+  Linkage linkage;
+  this(Linkage linkage, Declaration decls)
+  {
+    super(TOK.Extern, decls);
+    mixin(set_kind);
+    this.linkage = linkage;
+  }
+}
+
+class AlignDeclaration : AttributeDeclaration
+{
+  int size;
+  this(int size, Declaration decls)
+  {
+    super(TOK.Align, decls);
+    mixin(set_kind);
+    this.size = size;
+  }
+}
+
+class PragmaDeclaration : AttributeDeclaration
+{
+  Token* ident;
+  Expression[] args;
+  this(Token* ident, Expression[] args, Declaration decls)
+  {
+    super(TOK.Pragma, decls);
+    mixin(set_kind);
+    if (args.length)
+      this.children ~= args;
+    this.ident = ident;
+    this.args = args;
+  }
+}
+
+class MixinDeclaration : Declaration
+{
+  Expression[] templateIdents;
+  Token* mixinIdent;
+  Expression argument; // mixin ( AssignExpression )
+  this(Expression[] templateIdents, Token* mixinIdent)
+  {
+    super(false);
+    mixin(set_kind);
+    this.children = templateIdents;
+    this.templateIdents = templateIdents;
+    this.mixinIdent = mixinIdent;
+  }
+  this(Expression argument)
+  {
+    super(false);
+    mixin(set_kind);
+    this.children = [argument];
+    this.argument = argument;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/Expressions.d	Tue Aug 21 16:28:05 2007 +0000
@@ -0,0 +1,988 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module Expressions;
+import SyntaxTree;
+import Token;
+import Types;
+import Declarations;
+import Statements;
+
+abstract class Expression : Node
+{
+  this()
+  {
+    super(NodeCategory.Expression);
+  }
+}
+
+class EmptyExpression : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+}
+
+abstract class BinaryExpression : Expression
+{
+  Expression left, right;
+  Token* tok;
+  this(Expression left, Expression right, Token* tok)
+  {
+    this.children = [left, right];
+    this.left = left;
+    this.right = right;
+    this.tok = tok;
+  }
+}
+
+class CondExpression : BinaryExpression
+{
+  Expression condition;
+  this(Expression condition, Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+    this.children ~= [condition];
+    this.condition = condition;
+  }
+}
+
+class CommaExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class OrOrExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class AndAndExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class OrExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class XorExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class AndExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+abstract class CmpExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+  }
+}
+
+class EqualExpression : CmpExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class IdentityExpression : CmpExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class RelExpression : CmpExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class InExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class LShiftExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class RShiftExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class URShiftExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class PlusExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class MinusExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class CatExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class MulExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class DivExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class ModExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class AssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class LShiftAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class RShiftAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class URShiftAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class OrAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class AndAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class PlusAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class MinusAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class DivAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class MulAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class ModAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class XorAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class CatAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+
+abstract class UnaryExpression : Expression
+{
+  Expression e;
+  this(Expression e)
+  {
+    this.children ~= e;
+    this.e = e;
+  }
+}
+
+class AddressExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class PreIncrExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class PreDecrExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class PostIncrExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class PostDecrExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class DerefExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class SignExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class NotExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class CompExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+/+
+class DotIdExpression : UnaryExpression
+{
+  string ident;
+  this(Expression e, string ident)
+  {
+    super(e);
+    this.ident = ident;
+  }
+}
++/
+/+
+class DotTemplateInstanceExpression : UnaryExpression
+{
+  string ident;
+  TemplateArguments targs;
+  this(Expression e, string ident, TemplateArguments targs)
+  {
+    super(e);
+    this.ident = ident;
+    this.targs = targs;
+  }
+}
++/
+class PostDotListExpression : UnaryExpression
+{
+  DotListExpression dotList;
+  this(Expression e, DotListExpression dotList)
+  {
+    super(e);
+    mixin(set_kind);
+    this.children ~= [dotList];
+    this.dotList = dotList;
+  }
+}
+
+class CallExpression : UnaryExpression
+{
+  Expression[] args;
+  this(Expression e, Expression[] args)
+  {
+    super(e);
+    mixin(set_kind);
+    this.children ~= args;
+    this.args = args;
+  }
+}
+
+class NewExpression : /*Unary*/Expression
+{
+  Expression[] newArgs;
+  Type type;
+  Expression[] ctorArgs;
+  this(/*Expression e, */Expression[] newArgs, Type type, Expression[] ctorArgs)
+  {
+    /*super(e);*/
+    mixin(set_kind);
+    if (newArgs.length)
+      this.children ~= newArgs;
+    this.children ~= type;
+    if (ctorArgs.length)
+      this.children ~= ctorArgs;
+    this.newArgs = newArgs;
+    this.type = type;
+    this.ctorArgs = ctorArgs;
+  }
+}
+
+class NewAnonClassExpression : /*Unary*/Expression
+{
+  Expression[] newArgs;
+  BaseClass[] bases;
+  Expression[] ctorArgs;
+  Declarations decls;
+  this(/*Expression e, */Expression[] newArgs, BaseClass[] bases, Expression[] ctorArgs, Declarations decls)
+  {
+    /*super(e);*/
+    mixin(set_kind);
+    if (newArgs.length)
+      this.children ~= newArgs;
+    if (bases.length)
+      this.children ~= bases;
+    if (ctorArgs.length)
+      this.children ~= ctorArgs;
+    this.children ~= decls;
+
+    this.newArgs = newArgs;
+    this.bases = bases;
+    this.ctorArgs = ctorArgs;
+    this.decls = decls;
+  }
+}
+
+class DeleteExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class CastExpression : UnaryExpression
+{
+  Type type;
+  this(Expression e, Type type)
+  {
+    this.children = [type];
+    super(e);
+    mixin(set_kind);
+    this.type = type;
+  }
+}
+
+class IndexExpression : UnaryExpression
+{
+  Expression[] args;
+  this(Expression e, Expression[] args)
+  {
+    super(e);
+    mixin(set_kind);
+    this.children ~= args;
+    this.args = args;
+  }
+}
+
+class SliceExpression : UnaryExpression
+{
+  Expression left, right;
+  this(Expression e, Expression left, Expression right)
+  {
+    super(e);
+    mixin(set_kind);
+    this.children ~= [left, right];
+    this.left = left;
+    this.right = right;
+  }
+}
+
+/*
+class PrimaryExpression
+{
+
+}
+*/
+
+class IdentifierExpression : Expression
+{
+  Token* identifier;
+  this(Token* identifier)
+  {
+    mixin(set_kind);
+    this.identifier = identifier;
+  }
+}
+
+class SpecialTokenExpression : Expression
+{
+  Token* special;
+  this(Token* special)
+  {
+    mixin(set_kind);
+    this.special = special;
+  }
+}
+
+/*
+class IdentifierListExpression : Expression
+{
+  Expression[] identList;
+  this(Expression[] identList)
+  {
+    this.identList = identList;
+  }
+}
+*/
+class DotListExpression : Expression
+{
+  Expression[] items;
+  this(Expression[] items)
+  {
+    mixin(set_kind);
+    this.children = items;
+    this.items = items;
+  }
+}
+
+class TemplateInstanceExpression : Expression
+{
+  Token* ident;
+  TemplateArguments targs;
+  this(Token* ident, TemplateArguments targs)
+  {
+    mixin(set_kind);
+    this.children = [targs];
+    this.ident = ident;
+    this.targs = targs;
+  }
+}
+
+class ThisExpression : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+}
+
+class SuperExpression : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+}
+
+class NullExpression : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+}
+
+class DollarExpression : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+}
+
+class BoolExpression : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+}
+
+class IntNumberExpression : Expression
+{
+  TOK type;
+  ulong number;
+  this(TOK type, ulong number)
+  {
+    mixin(set_kind);
+    this.number = number;
+    this.type = type;
+  }
+}
+
+class RealNumberExpression : Expression
+{
+  TOK type;
+  real number;
+  this(TOK type, real number)
+  {
+    mixin(set_kind);
+    this.number = number;
+    this.type = type;
+  }
+}
+
+class CharLiteralExpression : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+}
+
+class StringLiteralsExpression : Expression
+{
+  Token*[] strings;
+  this(Token*[] strings)
+  {
+    mixin(set_kind);
+    this.strings = strings;
+  }
+
+  string getString()
+  {
+    char[] buffer;
+    foreach (strTok; strings)
+    {
+      buffer ~= strTok.str[0..$-1];
+    }
+    return buffer;
+  }
+}
+
+class ArrayLiteralExpression : Expression
+{
+  Expression[] values;
+  this(Expression[] values)
+  {
+    mixin(set_kind);
+    this.children = values;
+    this.values = values;
+  }
+}
+
+class AssocArrayLiteralExpression : Expression
+{
+  Expression[] keys, values;
+  this(Expression[] keys, Expression[] values)
+  {
+    assert(keys.length == values.length);
+    mixin(set_kind);
+    foreach (i, key; keys)
+      this.children ~= [key, values[i]];
+    this.keys = keys;
+    this.values = values;
+  }
+}
+
+class AssertExpression : Expression
+{
+  Expression expr, msg;
+  this(Expression expr, Expression msg)
+  {
+    mixin(set_kind);
+    this.children = [expr];
+    if (msg)
+      this.children ~= msg;
+    this.expr = expr;
+    this.msg = msg;
+  }
+}
+
+class MixinExpression : Expression
+{
+  Expression expr;
+  this(Expression expr)
+  {
+    mixin(set_kind);
+    this.children = [expr];
+    this.expr = expr;
+  }
+}
+
+class ImportExpression : Expression
+{
+  Expression expr;
+  this(Expression expr)
+  {
+    mixin(set_kind);
+    this.children = [expr];
+    this.expr = expr;
+  }
+}
+
+class TypeofExpression : Expression
+{
+  Type type;
+  this(Type type)
+  {
+    mixin(set_kind);
+    this.children = [type];
+    this.type = type;
+  }
+}
+
+class TypeDotIdExpression : Expression
+{
+  Type type;
+  Token* ident;
+  this(Type type, Token* ident)
+  {
+    mixin(set_kind);
+    this.children = [type];
+    this.type = type;
+    this.ident = ident;
+  }
+}
+
+class TypeidExpression : Expression
+{
+  Type type;
+  this(Type type)
+  {
+    mixin(set_kind);
+    this.children = [type];
+    this.type = type;
+  }
+}
+
+class IsExpression : Expression
+{
+  Type type;
+  Token* ident;
+  Token* opTok, specTok;
+  Type specType;
+  this(Type type, Token* ident, Token* opTok, Token* specTok, Type specType)
+  {
+    mixin(set_kind);
+    this.children = [type];
+    if (specType)
+      this.children ~= specType;
+    this.type = type;
+    this.ident = ident;
+    this.opTok = opTok;
+    this.specTok = specTok;
+    this.specType = specType;
+  }
+}
+
+class FunctionLiteralExpression : Expression
+{
+  Type returnType;
+  Parameters parameters;
+  FunctionBody funcBody;
+
+  this()
+  {
+    mixin(set_kind);
+    if (returnType)
+      this.children ~= returnType;
+    if (parameters)
+      this.children ~= parameters;
+    this.children ~= funcBody;
+  }
+
+  this(Type returnType, Parameters parameters, FunctionBody funcBody)
+  {
+    this.returnType = returnType;
+    this.parameters = parameters;
+    this.funcBody = funcBody;
+    this();
+  }
+
+  this(FunctionBody funcBody)
+  {
+    this.funcBody = funcBody;
+    this();
+  }
+}
+
+version(D2)
+{
+class TraitsExpression : Expression
+{
+  Token* ident;
+  TemplateArguments targs;
+  this(typeof(ident) ident, typeof(targs) targs)
+  {
+    mixin(set_kind);
+    this.children = [targs];
+    this.ident = ident;
+    this.targs = targs;
+  }
+}
+}
+
+class VoidInitializer : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+}
+
+class ArrayInitializer : Expression
+{
+  Expression[] keys;
+  Expression[] values;
+  this(Expression[] keys, Expression[] values)
+  {
+    assert(keys.length == values.length);
+    mixin(set_kind);
+    foreach (i, key; keys)
+    {
+      if (key)
+        this.children ~= key;
+      if (values[i])
+        this.children ~= values[i];
+    }
+    this.keys = keys;
+    this.values = values;
+  }
+}
+
+class StructInitializer : Expression
+{
+  Token*[] idents;
+  Expression[] values;
+  this(Token*[] idents, Expression[] values)
+  {
+    mixin(set_kind);
+    this.children = values;
+    this.idents = idents;
+    this.values = values;
+  }
+}
+
+class AsmTypeExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class AsmOffsetExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class AsmSegExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class AsmPostBracketExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class AsmBracketExpression : Expression
+{
+  Expression e;
+  this(Expression e)
+  {
+    mixin(set_kind);
+    this.children = [e];
+    this.e = e;
+  }
+}
+
+class AsmLocalSizeExpression : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+}
+
+class AsmRegisterExpression : Expression
+{
+  Token* register;
+  Token* number; // ST(0) - ST(7)
+  this(Token* register, Token* number = null)
+  {
+    mixin(set_kind);
+    this.register = register;
+    this.number = number;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/HtmlEntities.d	Tue Aug 21 16:28:05 2007 +0000
@@ -0,0 +1,277 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module HtmlEntities;
+
+private const dchar[char[]] entities_table;
+
+static this()
+{
+  entities_table = [
+    "Aacute"[] : '\u00C1',
+    "aacute" : '\u00E1',
+    "Acirc" : '\u00C2',
+    "acirc" : '\u00E2',
+    "acute" : '\u00B4',
+    "AElig" : '\u00C6',
+    "aelig" : '\u00E6',
+    "Agrave" : '\u00C0',
+    "agrave" : '\u00E0',
+    "alefsym" : '\u2135',
+    "Alpha" : '\u0391',
+    "alpha" : '\u03B1',
+    "amp" : '\u0026',
+    "and" : '\u2227',
+    "ang" : '\u2220',
+    "Aring" : '\u00C5',
+    "aring" : '\u00E5',
+    "asymp" : '\u2248',
+    "Atilde" : '\u00C3',
+    "atilde" : '\u00E3',
+    "Auml" : '\u00C4',
+    "auml" : '\u00E4',
+    "bdquo" : '\u201E',
+    "Beta" : '\u0392',
+    "beta" : '\u03B2',
+    "brvbar" : '\u00A6',
+    "bull" : '\u2022',
+    "cap" : '\u2229',
+    "Ccedil" : '\u00C7',
+    "ccedil" : '\u00E7',
+    "cedil" : '\u00B8',
+    "cent" : '\u00A2',
+    "Chi" : '\u03A7',
+    "chi" : '\u03C7',
+    "circ" : '\u02C6',
+    "clubs" : '\u2663',
+    "cong" : '\u2245',
+    "copy" : '\u00A9',
+    "crarr" : '\u21B5',
+    "cup" : '\u222A',
+    "curren" : '\u00A4',
+    "Dagger" : '\u2021',
+    "dagger" : '\u2020',
+    "dArr" : '\u21D3',
+    "darr" : '\u2193',
+    "deg" : '\u00B0',
+    "Delta" : '\u0394',
+    "delta" : '\u03B4',
+    "diams" : '\u2666',
+    "divide" : '\u00F7',
+    "Eacute" : '\u00C9',
+    "eacute" : '\u00E9',
+    "Ecirc" : '\u00CA',
+    "ecirc" : '\u00EA',
+    "Egrave" : '\u00C8',
+    "egrave" : '\u00E8',
+    "empty" : '\u2205',
+    "emsp" : '\u2003',
+    "ensp" : '\u2002',
+    "Epsilon" : '\u0395',
+    "epsilon" : '\u03B5',
+    "equiv" : '\u2261',
+    "Eta" : '\u0397',
+    "eta" : '\u03B7',
+    "ETH" : '\u00D0',
+    "eth" : '\u00F0',
+    "Euml" : '\u00CB',
+    "euml" : '\u00EB',
+    "euro" : '\u20AC',
+    "exist" : '\u2203',
+    "fnof" : '\u0192',
+    "forall" : '\u2200',
+    "frac12" : '\u00BD',
+    "frac14" : '\u00BC',
+    "frac34" : '\u00BE',
+    "frasl" : '\u2044',
+    "Gamma" : '\u0393',
+    "gamma" : '\u03B3',
+    "ge" : '\u2265',
+    "gt" : '\u003E',
+    "hArr" : '\u21D4',
+    "harr" : '\u2194',
+    "hearts" : '\u2665',
+    "hellip" : '\u2026',
+    "Iacute" : '\u00CD',
+    "iacute" : '\u00ED',
+    "Icirc" : '\u00CE',
+    "icirc" : '\u00EE',
+    "iexcl" : '\u00A1',
+    "Igrave" : '\u00CC',
+    "igrave" : '\u00EC',
+    "image" : '\u2111',
+    "infin" : '\u221E',
+    "int" : '\u222B',
+    "Iota" : '\u0399',
+    "iota" : '\u03B9',
+    "iquest" : '\u00BF',
+    "isin" : '\u2208',
+    "Iuml" : '\u00CF',
+    "iuml" : '\u00EF',
+    "Kappa" : '\u039A',
+    "kappa" : '\u03BA',
+    "Lambda" : '\u039B',
+    "lambda" : '\u03BB',
+    "lang" : '\u2329',
+    "laquo" : '\u00AB',
+    "lArr" : '\u21D0',
+    "larr" : '\u2190',
+    "lceil" : '\u2308',
+    "ldquo" : '\u201C',
+    "le" : '\u2264',
+    "lfloor" : '\u230A',
+    "lowast" : '\u2217',
+    "loz" : '\u25CA',
+    "lrm" : '\u200E',
+    "lsaquo" : '\u2039',
+    "lsquo" : '\u2018',
+    "lt" : '\u003C',
+    "macr" : '\u00AF',
+    "mdash" : '\u2014',
+    "micro" : '\u00B5',
+    "middot" : '\u00B7',
+    "minus" : '\u2212',
+    "Mu" : '\u039C',
+    "mu" : '\u03BC',
+    "nabla" : '\u2207',
+    "nbsp" : '\u00A0',
+    "ndash" : '\u2013',
+    "ne" : '\u2260',
+    "ni" : '\u220B',
+    "not" : '\u00AC',
+    "notin" : '\u2209',
+    "nsub" : '\u2284',
+    "Ntilde" : '\u00D1',
+    "ntilde" : '\u00F1',
+    "Nu" : '\u039D',
+    "nu" : '\u03BD',
+    "Oacute" : '\u00D3',
+    "oacute" : '\u00F3',
+    "Ocirc" : '\u00D4',
+    "ocirc" : '\u00F4',
+    "OElig" : '\u0152',
+    "oelig" : '\u0153',
+    "Ograve" : '\u00D2',
+    "ograve" : '\u00F2',
+    "oline" : '\u203E',
+    "Omega" : '\u03A9',
+    "omega" : '\u03C9',
+    "Omicron" : '\u039F',
+    "omicron" : '\u03BF',
+    "oplus" : '\u2295',
+    "or" : '\u2228',
+    "ordf" : '\u00AA',
+    "ordm" : '\u00BA',
+    "Oslash" : '\u00D8',
+    "oslash" : '\u00F8',
+    "Otilde" : '\u00D5',
+    "otilde" : '\u00F5',
+    "otimes" : '\u2297',
+    "Ouml" : '\u00D6',
+    "ouml" : '\u00F6',
+    "para" : '\u00B6',
+    "part" : '\u2202',
+    "permil" : '\u2030',
+    "perp" : '\u22A5',
+    "Phi" : '\u03A6',
+    "phi" : '\u03C6',
+    "Pi" : '\u03A0',
+    "pi" : '\u03C0',
+    "piv" : '\u03D6',
+    "plusmn" : '\u00B1',
+    "pound" : '\u00A3',
+    "Prime" : '\u2033',
+    "prime" : '\u2032',
+    "prod" : '\u220F',
+    "prop" : '\u221D',
+    "Psi" : '\u03A8',
+    "psi" : '\u03C8',
+    "quot" : '\u0022',
+    "radic" : '\u221A',
+    "rang" : '\u232A',
+    "raquo" : '\u00BB',
+    "rArr" : '\u21D2',
+    "rarr" : '\u2192',
+    "rceil" : '\u2309',
+    "rdquo" : '\u201D',
+    "real" : '\u211C',
+    "reg" : '\u00AE',
+    "rfloor" : '\u230B',
+    "Rho" : '\u03A1',
+    "rho" : '\u03C1',
+    "rlm" : '\u200F',
+    "rsaquo" : '\u203A',
+    "rsquo" : '\u2019',
+    "sbquo" : '\u201A',
+    "Scaron" : '\u0160',
+    "scaron" : '\u0161',
+    "sdot" : '\u22C5',
+    "sect" : '\u00A7',
+    "shy" : '\u00AD',
+    "Sigma" : '\u03A3',
+    "sigma" : '\u03C3',
+    "sigmaf" : '\u03C2',
+    "sim" : '\u223C',
+    "spades" : '\u2660',
+    "sub" : '\u2282',
+    "sube" : '\u2286',
+    "sum" : '\u2211',
+    "sup" : '\u2283',
+    "sup1" : '\u00B9',
+    "sup2" : '\u00B2',
+    "sup3" : '\u00B3',
+    "supe" : '\u2287',
+    "szlig" : '\u00DF',
+    "Tau" : '\u03A4',
+    "tau" : '\u03C4',
+    "there4" : '\u2234',
+    "Theta" : '\u0398',
+    "theta" : '\u03B8',
+    "thetasym" : '\u03D1',
+    "thinsp" : '\u2009',
+    "THORN" : '\u00DE',
+    "thorn" : '\u00FE',
+    "tilde" : '\u02DC',
+    "times" : '\u00D7',
+    "trade" : '\u2122',
+    "Uacute" : '\u00DA',
+    "uacute" : '\u00FA',
+    "uArr" : '\u21D1',
+    "uarr" : '\u2191',
+    "Ucirc" : '\u00DB',
+    "ucirc" : '\u00FB',
+    "Ugrave" : '\u00D9',
+    "ugrave" : '\u00F9',
+    "uml" : '\u00A8',
+    "upsih" : '\u03D2',
+    "Upsilon" : '\u03A5',
+    "upsilon" : '\u03C5',
+    "Uuml" : '\u00DC',
+    "uuml" : '\u00FC',
+    "weierp" : '\u2118',
+    "Xi" : '\u039E',
+    "xi" : '\u03BE',
+    "Yacute" : '\u00DD',
+    "yacute" : '\u00FD',
+    "yen" : '\u00A5',
+    "Yuml" : '\u0178',
+    "yuml" : '\u00FF',
+    "Zeta" : '\u0396',
+    "zeta" : '\u03B6',
+    "zwj" : '\u200D',
+    "zwnj" : '\u200C'
+  ];
+}
+
+/++
+  Converts a named HTML entity into its equivalent Unicode codepoint.
+  Returns 0xFFFF if entity doesn't exist.
++/
+dchar entity2Unicode(char[] entity)
+{
+  auto d = entity in entities_table;
+  if (d)
+    return *d;
+  return 0xFFFF;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/Identifier.d	Tue Aug 21 16:28:05 2007 +0000
@@ -0,0 +1,30 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module Identifier;
+import Token;
+
+struct Identifier
+{
+  TOK type;
+  string str;
+
+  static Identifier opCall(TOK type, string str)
+  {
+    Identifier i;
+    i.type = type;
+    i.str = str;
+    return i;
+  }
+
+  uint toHash()
+  {
+    uint hash;
+    foreach(c; str) {
+      hash *= 9;
+      hash += c;
+    }
+    return hash;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/Information.d	Tue Aug 21 16:28:05 2007 +0000
@@ -0,0 +1,35 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module Information;
+import Messages;
+import std.stdarg;
+
+enum InfoType
+{
+  Lexer,
+  Parser,
+  Semantic
+}
+
+class Information
+{
+  MID id;
+  InfoType type;
+  uint loc;
+  string[] arguments;
+
+  this(InfoType type, MID id, uint loc, string[] arguments)
+  {
+    this.id = id;
+    this.type = type;
+    this.loc = loc;
+    this.arguments = arguments;
+  }
+
+  string getMsg()
+  {
+    return format_args(GetMsg(id), arguments);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/Keywords.d	Tue Aug 21 16:28:05 2007 +0000
@@ -0,0 +1,117 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module Keywords;
+import Token;
+import Identifier;
+
+static const Identifier[] keywords = [
+  {TOK.Abstract, "abstract"},
+  {TOK.Alias, "alias"},
+  {TOK.Align, "align"},
+  {TOK.Asm, "asm"},
+  {TOK.Assert, "assert"},
+  {TOK.Auto, "auto"},
+  {TOK.Body, "body"},
+  {TOK.Bool, "bool"},
+  {TOK.Break, "break"},
+  {TOK.Byte, "byte"},
+  {TOK.Case, "case"},
+  {TOK.Cast, "cast"},
+  {TOK.Catch, "catch"},
+  {TOK.Cdouble, "cdouble"},
+  {TOK.Cent, "cent"},
+  {TOK.Cfloat, "cfloat"},
+  {TOK.Char, "char"},
+  {TOK.Class, "class"},
+  {TOK.Const, "const"},
+  {TOK.Continue, "continue"},
+  {TOK.Creal, "creal"},
+  {TOK.Dchar, "dchar"},
+  {TOK.Debug, "debug"},
+  {TOK.Default, "default"},
+  {TOK.Delegate, "delegate"},
+  {TOK.Delete, "delete"},
+  {TOK.Deprecated, "deprecated"},
+  {TOK.Do, "do"},
+  {TOK.Double, "double"},
+  {TOK.Else, "else"},
+  {TOK.Enum, "enum"},
+  {TOK.Export, "export"},
+  {TOK.Extern, "extern"},
+  {TOK.False, "false"},
+  {TOK.Final, "final"},
+  {TOK.Finally, "finally"},
+  {TOK.Float, "float"},
+  {TOK.For, "for"},
+  {TOK.Foreach, "foreach"},
+  {TOK.Foreach_reverse, "foreach_reverse"},
+  {TOK.Function, "function"},
+  {TOK.Goto, "goto"},
+  {TOK.Idouble, "idouble"},
+  {TOK.If, "if"},
+  {TOK.Ifloat, "ifloat"},
+  {TOK.Import, "import"},
+  {TOK.In, "in"},
+  {TOK.Inout, "inout"},
+  {TOK.Int, "int"},
+  {TOK.Interface, "interface"},
+  {TOK.Invariant, "invariant"},
+  {TOK.Ireal, "ireal"},
+  {TOK.Is, "is"},
+  {TOK.Lazy, "lazy"},
+  {TOK.Long, "long"},
+  {TOK.Macro, "macro"}, // D2.0
+  {TOK.Mixin, "mixin"},
+  {TOK.Module, "module"},
+  {TOK.New, "new"},
+  {TOK.Null, "null"},
+  {TOK.Out, "out"},
+  {TOK.Override, "override"},
+  {TOK.Package, "package"},
+  {TOK.Pragma, "pragma"},
+  {TOK.Private, "private"},
+  {TOK.Protected, "protected"},
+  {TOK.Public, "public"},
+  {TOK.Real, "real"},
+  {TOK.Ref, "ref"},
+  {TOK.Return, "return"},
+  {TOK.Scope, "scope"},
+  {TOK.Short, "short"},
+  {TOK.Static, "static"},
+  {TOK.Struct, "struct"},
+  {TOK.Super, "super"},
+  {TOK.Switch, "switch"},
+  {TOK.Synchronized, "synchronized"},
+  {TOK.Template, "template"},
+  {TOK.This, "this"},
+  {TOK.Throw, "throw"},
+  {TOK.Traits, "__traits"}, // D2.0
+  {TOK.True, "true"},
+  {TOK.Try, "try"},
+  {TOK.Typedef, "typedef"},
+  {TOK.Typeid, "typeid"},
+  {TOK.Typeof, "typeof"},
+  {TOK.Ubyte, "ubyte"},
+  {TOK.Ucent, "ucent"},
+  {TOK.Uint, "uint"},
+  {TOK.Ulong, "ulong"},
+  {TOK.Union, "union"},
+  {TOK.Unittest, "unittest"},
+  {TOK.Ushort, "ushort"},
+  {TOK.Version, "version"},
+  {TOK.Void, "void"},
+  {TOK.Volatile, "volatile"},
+  {TOK.Wchar, "wchar"},
+  {TOK.While, "while"},
+  {TOK.With, "with"},
+  // Special tokens:
+  {TOK.Special, "__FILE__"},
+  {TOK.Special, "__LINE__"},
+  {TOK.Special, "__DATE__"},
+  {TOK.Special, "__TIME__"},
+  {TOK.Special, "__TIMESTAMP__"},
+  {TOK.Special, "__VENDOR__"},
+  {TOK.Special, "__VERSION__"},
+];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/Lexer.d	Tue Aug 21 16:28:05 2007 +0000
@@ -0,0 +1,1773 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module Lexer;
+import Token;
+import Information;
+import Keywords;
+import Identifier;
+import Messages;
+import HtmlEntities;
+import std.stdio;
+import std.utf;
+import std.uni;
+import std.c.stdlib;
+import std.string;
+
+const char[3] LS = \u2028;
+const char[3] PS = \u2029;
+
+const dchar LSd = 0x2028;
+const dchar PSd = 0x2029;
+
+const uint _Z_ = 26; /// Control+Z
+
+class Lexer
+{
+  Token* head; /// The head of the doubly linked token list.
+  Token* token; /// Points to the current token in the token list.
+  string text;
+  char* p; /// Points to the current character in the source text.
+  char* end; /// Points one character past the end of the source text.
+
+  uint loc = 1; /// line of code
+
+  char[] fileName;
+
+  Information[] errors;
+
+//   bool reportErrors;
+
+  Identifier[string] idtable;
+
+  this(string text, string fileName)
+  {
+    this.fileName = fileName;
+
+    this.text = text;
+    if (text[$-1] != 0)
+    {
+      this.text.length = this.text.length + 1;
+      this.text[$-1] = 0;
+    }
+
+    this.p = this.text.ptr;
+    this.end = this.p + this.text.length;
+//     this.reportErrors = true;
+    loadKeywords();
+
+    this.head = new Token;
+    this.head.type = TOK.HEAD;
+    this.token = this.head;
+    scanShebang();
+  }
+
+  void scanShebang()
+  {
+    if (*p == '#' && p[1] == '!')
+    {
+      Token* t = new Token;
+      t.start = p;
+      t.type = TOK.Shebang;
+      ++p;
+      while (1)
+      {
+        switch (*++p)
+        {
+        case '\r':
+          if (p[1] == '\n')
+            ++p;
+        case '\n':
+          ++loc;
+          if (p[-1] == '\r')
+            t.end = p-1;
+          else
+            t.end = p;
+          break;
+        case LS[0]:
+          t.end = p;
+          if (p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2]))
+          {
+            ++p; ++p;
+            ++loc;
+          }
+          break;
+        case 0, _Z_:
+          t.end = p;
+          break;
+        default:
+          continue;
+        }
+        break; // Exit loop.
+      }
+      this.head.next = t;
+      t.prev = this.head;
+    }
+  }
+
+  public void scan(out Token t)
+  in
+  {
+    assert(text.ptr <= p && p < end);
+  }
+  out
+  {
+    assert(text.ptr <= t.start && t.start < end);
+    assert(text.ptr < t.end && t.end <= end, std.string.format(t.type));
+  }
+  body
+  {
+    uint c = *p;
+
+    while (1)
+    {
+      t.start = p;
+
+      if (c == 0 || c == _Z_)
+      {
+        assert(*p == 0 || *p == _Z_);
+        t.type = TOK.EOF;
+        t.end = p;
+        assert(t.start == t.end);
+        return;
+      }
+
+      if (c == '\n')
+      {
+        c = *++p;
+        ++loc;
+        continue;
+      }
+      else if (c == '\r')
+      {
+        c = *++p;
+        if (c != '\n')
+          ++loc;
+        continue;
+      }
+      else if (c == LS[0] && p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2]))
+      {
+        p += 3;
+        c = *p;
+        continue;
+      }
+
+      if (isidbeg(c))
+      {
+        if (c == 'r' && p[1] == '"' && ++p)
+          return scanRawStringLiteral(t);
+        if (c == 'x' && p[1] == '"')
+          return scanHexStringLiteral(t);
+      Lidentifier:
+        do
+        { c = *++p; }
+        while (isident(c) || c & 128 && isUniAlpha(decodeUTF8()))
+
+        t.end = p;
+
+        string str = t.srcText;
+        Identifier* id = str in idtable;
+
+        if (!id)
+        {
+          idtable[str] = Identifier.Identifier(TOK.Identifier, str);
+          id = str in idtable;
+        }
+        assert(id);
+        t.type = id.type;
+        return;
+      }
+
+      if (isdigit(c))
+        return scanNumber(t);
+
+      if (c == '/')
+      {
+        c = *++p;
+        switch(c)
+        {
+        case '=':
+          ++p;
+          t.type = TOK.DivAssign;
+          t.end = p;
+          return;
+        case '+':
+          uint level = 1;
+          while (1)
+          {
+            c = *++p;
+          LswitchNC: // only jumped to from default case of next switch(c)
+            switch (c)
+            {
+            case '\r':
+              if (p[1] == '\n')
+                ++p;
+            case '\n':
+              ++loc;
+              continue;
+            case 0, _Z_:
+              error(MID.UnterminatedNestedComment);
+              goto LreturnNC;
+            default:
+            }
+
+            c <<= 8;
+            c |= *++p;
+            switch (c)
+            {
+            case 0x2F2B: // /+
+              ++level;
+              continue;
+            case 0x2B2F: // +/
+              if (--level == 0)
+              {
+                ++p;
+              LreturnNC:
+                t.type = TOK.Comment;
+                t.end = p;
+                return;
+              }
+              continue;
+            case 0xE280: // LS[0..1] || PS[0..1]
+              if (p[1] == LS[2] || p[1] == PS[2])
+              {
+                ++loc;
+                ++p;
+              }
+              continue;
+            default:
+              c &= char.max;
+              goto LswitchNC;
+            }
+          }
+        case '*':
+          while (1)
+          {
+            c = *++p;
+          LswitchBC: // only jumped to from default case of next switch(c)
+            switch (c)
+            {
+            case '\r':
+              if (p[1] == '\n')
+                ++p;
+            case '\n':
+              ++loc;
+              continue;
+            case 0, _Z_:
+              error(MID.UnterminatedBlockComment);
+              goto LreturnBC;
+            default:
+            }
+
+            c <<= 8;
+            c |= *++p;
+            switch (c)
+            {
+            case 0x2A2F: // */
+              ++p;
+            LreturnBC:
+              t.type = TOK.Comment;
+              t.end = p;
+              return;
+            case 0xE280: // LS[0..1] || PS[0..1]
+              if (p[1] == LS[2] || p[1] == PS[2])
+              {
+                ++loc;
+                ++p;
+              }
+              continue;
+            default:
+              c &= char.max;
+              goto LswitchBC;
+            }
+          }
+          assert(0);
+        case '/':
+          while (1)
+          {
+            c = *++p;
+            switch (c)
+            {
+            case '\r':
+              if (p[1] == '\n')
+                ++p;
+            case '\n':
+            case 0, _Z_:
+              break;
+            case LS[0]:
+              if (p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2]))
+                break;
+              continue;
+            default:
+              continue;
+            }
+            t.type = TOK.Comment;
+            t.end = p;
+            return;
+          }
+        default:
+          t.type = TOK.Div;
+          t.end = p;
+          return;
+        }
+      }
+
+      switch (c)
+      {
+      case '\'':
+        return scanCharacterLiteral(t);
+      case '`':
+        return scanRawStringLiteral(t);
+      case '"':
+        return scanNormalStringLiteral(t);
+      case '\\':
+        char[] buffer;
+        do
+        {
+          ++p;
+          c = scanEscapeSequence();
+          if (c < 128)
+            buffer ~= c;
+          else
+            encodeUTF8(buffer, c);
+        } while (*p == '\\')
+        buffer ~= 0;
+        t.type = TOK.String;
+        t.str = buffer;
+        t.end = p;
+        return;
+      case '>': /* >  >=  >>  >>=  >>>  >>>= */
+        c = *++p;
+        switch (c)
+        {
+        case '=':
+          t.type = TOK.GreaterEqual;
+          goto Lcommon;
+        case '>':
+          if (p[1] == '>')
+          {
+            ++p;
+            if (p[1] == '=')
+            { ++p;
+              t.type = TOK.URShiftAssign;
+            }
+            else
+              t.type = TOK.URShift;
+          }
+          else if (p[1] == '=')
+          {
+            ++p;
+            t.type = TOK.RShiftAssign;
+          }
+          else
+            t.type = TOK.RShift;
+          goto Lcommon;
+        default:
+          t.type = TOK.Greater;
+          goto Lcommon2;
+        }
+        assert(0);
+      case '<': /* <  <=  <>  <>=  <<  <<= */
+        c = *++p;
+        switch (c)
+        {
+        case '=':
+          t.type = TOK.LessEqual;
+          goto Lcommon;
+        case '<':
+          if (p[1] == '=') {
+            ++p;
+            t.type = TOK.LShiftAssign;
+          }
+          else
+            t.type = TOK.LShift;
+          goto Lcommon;
+        case '>':
+          if (p[1] == '=') {
+            ++p;
+            t.type = TOK.LorEorG;
+          }
+          else
+            t.type = TOK.LorG;
+          goto Lcommon;
+        default:
+          t.type = TOK.Less;
+          goto Lcommon2;
+        }
+        assert(0);
+      case '!': /* !  !<  !>  !<=  !>=  !<>  !<>= */
+        c = *++p;
+        switch (c)
+        {
+        case '<':
+          c = *++p;
+          if (c == '>')
+          {
+            if (p[1] == '=') {
+              ++p;
+              t.type = TOK.Unordered;
+            }
+            else
+              t.type = TOK.UorE;
+          }
+          else if (c == '=')
+          {
+            t.type = TOK.UorG;
+          }
+          else {
+            t.type = TOK.UorGorE;
+            goto Lcommon2;
+          }
+          goto Lcommon;
+        case '>':
+          if (p[1] == '=')
+          {
+            ++p;
+            t.type = TOK.UorL;
+          }
+          else
+            t.type = TOK.UorLorE;
+          goto Lcommon;
+        case '=':
+          t.type = TOK.NotEqual;
+          goto Lcommon;
+        default:
+          t.type = TOK.Not;
+          goto Lcommon2;
+        }
+        assert(0);
+      case '.': /* .  .[0-9]  ..  ... */
+        if (p[1] == '.')
+        {
+          ++p;
+          if (p[1] == '.') {
+            ++p;
+            t.type = TOK.Ellipses;
+          }
+          else
+            t.type = TOK.Slice;
+        }
+        else if (isdigit(p[1]))
+        {
+          return scanReal(t);
+        }
+        else
+          t.type = TOK.Dot;
+        goto Lcommon;
+      case '|': /* |  ||  |= */
+        c = *++p;
+        if (c == '=')
+          t.type = TOK.OrAssign;
+        else if (c == '|')
+          t.type = TOK.OrLogical;
+        else {
+          t.type = TOK.OrBinary;
+          goto Lcommon2;
+        }
+        goto Lcommon;
+      case '&': /* &  &&  &= */
+        c = *++p;
+        if (c == '=')
+          t.type = TOK.AndAssign;
+        else if (c == '&')
+          t.type = TOK.AndLogical;
+        else {
+          t.type = TOK.AndBinary;
+          goto Lcommon2;
+        }
+        goto Lcommon;
+      case '+': /* +  ++  += */
+        c = *++p;
+        if (c == '=')
+          t.type = TOK.PlusAssign;
+        else if (c == '+')
+          t.type = TOK.PlusPlus;
+        else {
+          t.type = TOK.Plus;
+          goto Lcommon2;
+        }
+        goto Lcommon;
+      case '-': /* -  --  -= */
+        c = *++p;
+        if (c == '=')
+          t.type = TOK.MinusAssign;
+        else if (c == '-')
+          t.type = TOK.MinusMinus;
+        else {
+          t.type = TOK.Minus;
+          goto Lcommon2;
+        }
+        goto Lcommon;
+      case '=': /* =  == */
+        if (p[1] == '=') {
+          ++p;
+          t.type = TOK.Equal;
+        }
+        else
+          t.type = TOK.Assign;
+        goto Lcommon;
+      case '~': /* ~  ~= */
+         if (p[1] == '=') {
+           ++p;
+           t.type = TOK.CatAssign;
+         }
+         else
+           t.type = TOK.Tilde;
+         goto Lcommon;
+      case '*': /* *  *= */
+         if (p[1] == '=') {
+           ++p;
+           t.type = TOK.MulAssign;
+         }
+         else
+           t.type = TOK.Mul;
+         goto Lcommon;
+      case '^': /* ^  ^= */
+         if (p[1] == '=') {
+           ++p;
+           t.type = TOK.XorAssign;
+         }
+         else
+           t.type = TOK.Xor;
+         goto Lcommon;
+      case '%': /* %  %= */
+         if (p[1] == '=') {
+           ++p;
+           t.type = TOK.ModAssign;
+         }
+         else
+           t.type = TOK.Mod;
+         goto Lcommon;
+      // Single character tokens:
+      case '(':
+        t.type = TOK.LParen;
+        goto Lcommon;
+      case ')':
+        t.type = TOK.RParen;
+        goto Lcommon;
+      case '[':
+        t.type = TOK.LBracket;
+        goto Lcommon;
+      case ']':
+        t.type = TOK.RBracket;
+        goto Lcommon;
+      case '{':
+        t.type = TOK.LBrace;
+        goto Lcommon;
+      case '}':
+        t.type = TOK.RBrace;
+        goto Lcommon;
+      case ':':
+        t.type = TOK.Colon;
+        goto Lcommon;
+      case ';':
+        t.type = TOK.Semicolon;
+        goto Lcommon;
+      case '?':
+        t.type = TOK.Question;
+        goto Lcommon;
+      case ',':
+        t.type = TOK.Comma;
+        goto Lcommon;
+      case '$':
+        t.type = TOK.Dollar;
+      Lcommon:
+        ++p;
+      Lcommon2:
+        t.end = p;
+        return;
+      case '#':
+        return scanSpecialToken(t);
+      default:
+      }
+
+      if (c & 128 && isUniAlpha(decodeUTF8()))
+        goto Lidentifier;
+      c = *++p;
+    }
+  }
+
+  void scanNormalStringLiteral(ref Token t)
+  {
+    assert(*p == '"');
+    ++p;
+    char[] buffer;
+    t.type = TOK.String;
+    while (1)
+    {
+      switch (*p)
+      {
+      case '"':
+        ++p;
+      Lreturn:
+        buffer ~= 0;
+        t.str = buffer;
+        t.pf = scanPostfix();
+        t.end = p;
+        return;
+      case '\\':
+        ++p;
+        dchar d = scanEscapeSequence();
+        if (d < 128)
+          buffer ~= d;
+        else
+          encodeUTF8(buffer, d);
+        continue;
+      case '\r':
+        if (p[1] == '\n')
+          ++p;
+      case '\n':
+        ++p;
+        ++loc;
+        buffer ~= '\n'; // Convert EndOfLine to \n.
+        continue;
+      case 0, _Z_:
+        error(MID.UnterminatedString);
+        goto Lreturn;
+      default:
+        if (*p & 128)
+        {
+//           char* begin = p;
+          dchar d = decodeUTF8();
+          if (d == LSd || d == PSd)
+            goto case '\n';
+
+          // We don't copy per pointer because we might include
+          // invalid, skipped utf-8 sequences. See decodeUTF8().
+//           ++p;
+//           buffer ~= begin[0 .. p - begin];
+          ++p;
+          encodeUTF8(buffer, d);
+          continue;
+        }
+        // Copy ASCII character.
+        buffer ~= *p++;
+      }
+    }
+    assert(0);
+  }
+
+  void scanCharacterLiteral(ref Token t)
+  {
+    assert(*p == '\'');
+    MID id = MID.UnterminatedCharacterLiteral;
+    ++p;
+    TOK type = TOK.CharLiteral;
+    switch (*p)
+    {
+    case '\\':
+      ++p;
+      switch (*p)
+      {
+      case 'u':
+        type = TOK.WCharLiteral; break;
+      case 'U':
+        type = TOK.DCharLiteral; break;
+      default:
+      }
+      t.dchar_ = scanEscapeSequence();
+      break;
+    case '\'':
+      ++p;
+      id = MID.EmptyCharacterLiteral;
+    case '\n', '\r', 0, _Z_:
+      goto Lerr;
+    default:
+      uint c = *p;
+      if (c & 128)
+      {
+        c = decodeUTF8();
+        if (c == LSd || c == PSd)
+          goto Lerr;
+        if (c <= 0xFFFF)
+          type = TOK.WCharLiteral;
+        else
+          type = TOK.DCharLiteral;
+      }
+      t.dchar_ = c;
+      ++p;
+    }
+
+    if (*p == '\'')
+      ++p;
+    else
+    Lerr:
+      error(id);
+    t.type = type;
+    t.end = p;
+  }
+
+  char scanPostfix()
+  {
+    switch (*p)
+    {
+    case 'c':
+    case 'w':
+    case 'd':
+      return *p++;
+    default:
+      return 0;
+    }
+    assert(0);
+  }
+
+  void scanRawStringLiteral(ref Token t)
+  {
+    uint delim = *p;
+    assert(delim == '`' || delim == '"' && p[-1] == 'r');
+    t.type = TOK.String;
+    char[] buffer;
+    uint c;
+    while (1)
+    {
+      c = *++p;
+      switch (c)
+      {
+      case '\r':
+        if (p[1] == '\n')
+          ++p;
+        c = '\n'; // Convert '\r' and '\r\n' to '\n'
+      case '\n':
+        ++loc;
+        break;
+      case '`':
+      case '"':
+        if (c == delim)
+        {
+          ++p;
+          t.pf = scanPostfix();
+        Lreturn:
+          t.str = buffer ~ '\0';
+          t.end = p;
+          return;
+        }
+        break;
+      case LS[0]:
+        if (p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2]))
+        {
+          c = '\n';
+          ++p; ++p;
+          ++loc;
+        }
+        break;
+      case 0, _Z_:
+        if (delim == 'r')
+          error(MID.UnterminatedRawString);
+        else
+          error(MID.UnterminatedBackQuoteString);
+        goto Lreturn;
+      default:
+      }
+      buffer ~= c; // copy character to buffer
+    }
+    assert(0);
+  }
+
+  void scanHexStringLiteral(ref Token t)
+  {
+    assert(p[0] == 'x' && p[1] == '"');
+    t.type = TOK.String;
+
+    uint c;
+    ubyte[] buffer;
+    ubyte h; // hex number
+    uint n; // number of hex digits
+
+    ++p;
+    while (1)
+    {
+      c = *++p;
+      switch (c)
+      {
+      case '"':
+        ++p;
+        if (n & 1)
+          error(MID.OddNumberOfDigitsInHexString);
+        t.pf = scanPostfix();
+      Lreturn:
+        buffer ~= 0;
+        t.str = cast(string) buffer;
+        t.end = p;
+        return;
+      case '\r':
+        if (p[1] == '\n')
+          ++p;
+      case '\n':
+        ++loc;
+        continue;
+      default:
+        if (ishexad(c))
+        {
+          if (c <= '9')
+            c -= '0';
+          else if (c <= 'F')
+            c -= 'A' - 10;
+          else
+            c -= 'a' - 10;
+
+          if (n & 1)
+          {
+            h <<= 4;
+            h |= c;
+            buffer ~= h;
+          }
+          else
+            h = cast(ubyte)c;
+          ++n;
+          continue;
+        }
+        else if (isspace(c))
+          continue;
+
+        if (c >= 128)
+        {
+          c = decodeUTF8();
+          if (c == LSd || c == PSd)
+          {
+            ++p; ++p;
+            ++loc;
+            continue;
+          }
+        }
+        else if (c == 0 || c == _Z_)
+        {
+          error(MID.UnterminatedHexString);
+          t.pf = 0;
+          goto Lreturn;
+        }
+        error(MID.NonHexCharInHexString, cast(dchar)c);
+      }
+    }
+    assert(0);
+  }
+
+  dchar scanEscapeSequence()
+  {
+    uint c = char2ev(*p);
+    if (c)
+    {
+      ++p;
+      return c;
+    }
+    uint digits = 2;
+
+    switch (*p)
+    {
+    case 'x':
+      c = 0;
+      while (1)
+      {
+        ++p;
+        if (ishexad(*p))
+        {
+          c *= 16;
+          if (*p <= '9')
+            c += *p - '0';
+          else if (*p <= 'F')
+            c += *p - 'A' + 10;
+          else
+            c += *p - 'a' + 10;
+
+          if (!--digits)
+          {
+            ++p;
+            break;
+          }
+        }
+        else
+        {
+          error(MID.InsufficientHexDigits);
+          break;
+        }
+      }
+      if (!isValidDchar(c))
+        error(MID.InvalidUnicodeCharacter);
+      break;
+    case 'u':
+      digits = 4;
+      goto case 'x';
+    case 'U':
+      digits = 8;
+      goto case 'x';
+    default:
+      if (isoctal(*p))
+      {
+        c = 0;
+        c += *p - '0';
+        ++p;
+        if (!isoctal(*p))
+          return c;
+        c *= 8;
+        c += *p - '0';
+        ++p;
+        if (!isoctal(*p))
+          return c;
+        c *= 8;
+        c += *p - '0';
+        ++p;
+      }
+      else if(*p == '&')
+      {
+        if (isalpha(*++p))
+        {
+          auto begin = p;
+          while (isalnum(*++p))
+          {}
+
+          if (*p == ';')
+          {
+            c = entity2Unicode(begin[0..p - begin]);
+            ++p;
+            if (c == 0xFFFF)
+              error(MID.UndefinedHTMLEntity, (begin-1)[0..p-(begin-1)]);
+          }
+          else
+            error(MID.UnterminatedHTMLEntity);
+        }
+        else
+          error(MID.InvalidBeginHTMLEntity);
+      }
+      else
+        error(MID.UndefinedEscapeSequence);
+    }
+
+    return c;
+  }
+
+  /*
+    IntegerLiteral:= (Dec|Hex|Bin|Oct)Suffix?
+    Dec:= (0|[1-9][0-9_]*)
+    Hex:= 0[xX] HexDigits
+    Bin:= 0[bB][01_]+
+    Oct:= 0[0-7_]+
+    Suffix:= (L[uU]?|[uU]L?)
+    HexDigits:= [0-9a-zA-Z_]+
+
+    Invalid: "0b_", "0x_", "._"
+  */
+  void scanNumber(ref Token t)
+  {
+    ulong ulong_;
+    bool overflow;
+    bool isDecimal;
+    size_t digits;
+
+    if (*p != '0')
+      goto LscanInteger;
+    ++p; // skip zero
+    // check for xX bB ...
+    switch (*p)
+    {
+    case 'x','X':
+      goto LscanHex;
+    case 'b','B':
+      goto LscanBin;
+    case 'L':
+      if (p[1] == 'i')
+        goto LscanReal;
+    case '.':
+      if (p[1] == '.')
+        break;
+    case 'i','f','F', 'e', 'E': // Imaginary and float literal suffix
+      goto LscanReal;
+    default:
+      if (*p == '_' || isoctal(*p))
+        goto LscanOct;
+    }
+
+    // Number 0
+    assert(p[-1] == '0');
+    assert(ulong_ == 0);
+    isDecimal = true;
+    goto Lfinalize;
+
+  LscanInteger:
+    assert(*p != 0 && isdigit(*p));
+    isDecimal = true;
+    goto Lenter_loop_int;
+    while (1)
+    {
+      if (*++p == '_')
+        continue;
+      if (!isdigit(*p))
+        break;
+    Lenter_loop_int:
+      if (ulong_ < ulong.max/10 || (ulong_ == ulong.max/10 && *p <= '5'))
+      {
+        ulong_ *= 10;
+        ulong_ += *p - '0';
+        continue;
+      }
+      // Overflow: skip following digits.
+      overflow = true;
+      while (isdigit(*++p)) {}
+      break;
+    }
+
+    // The number could be a float, so check overflow below.
+    switch (*p)
+    {
+    case '.':
+      if (p[1] != '.')
+        goto LscanReal;
+      break;
+    case 'L':
+      if (p[1] != 'i')
+        break;
+    case 'i', 'f', 'F', 'e', 'E':
+      goto LscanReal;
+    default:
+    }
+
+    if (overflow)
+      error(MID.OverflowDecimalNumber);
+
+    assert((isdigit(p[-1]) || p[-1] == '_') && !isdigit(*p) && *p != '_');
+    goto Lfinalize;
+
+  LscanHex:
+    assert(digits == 0);
+    assert(*p == 'x');
+    while (1)
+    {
+      if (*++p == '_')
+        continue;
+      if (!ishexad(*p))
+        break;
+      ++digits;
+      ulong_ *= 16;
+      if (*p <= '9')
+        ulong_ += *p - '0';
+      else if (*p <= 'F')
+        ulong_ += *p - 'A' + 10;
+      else
+        ulong_ += *p - 'a' + 10;
+    }
+
+    switch (*p)
+    {
+    case '.':
+      if (p[1] != '.')
+        goto LscanHexReal;
+      break;
+    case 'L':
+      if (p[1] != 'i')
+        break;
+    case 'i', 'p', 'P':
+      goto LscanHexReal;
+    default:
+    }
+    if (digits == 0)
+      error(MID.NoDigitsInHexNumber);
+    else if (digits > 16)
+    {
+      // Overflow: skip following digits.
+      error(MID.OverflowHexNumber);
+      while (ishexad(*++p)) {}
+    }
+    goto Lfinalize;
+  LscanHexReal:
+    return scanHexReal(t);
+
+  LscanBin:
+    assert(digits == 0);
+    assert(*p == 'b');
+    while (1)
+    {
+      if (*++p == '0')
+      {
+        ++digits;
+        ulong_ *= 2;
+      }
+      if (*p == '1')
+      {
+        ++digits;
+        ulong_ *= 2;
+        ulong_ += *p - '0';
+      }
+      if (*p == '_')
+        continue;
+      break;
+    }
+
+    if (digits == 0)
+      error(MID.NoDigitsInBinNumber);
+
+    if (digits > 64)
+      error(MID.OverflowBinaryNumber);
+    assert((p[-1] == '0' || p[-1] == '1' || p[-1] == '_') && !(*p == '0' || *p == '1' || *p == '_'));
+    goto Lfinalize;
+
+  LscanOct:
+    assert(*p == '_' || isoctal(*p));
+    if (*p != '_')
+      goto Lenter_loop_oct;
+    while (1)
+    {
+      if (*++p == '_')
+        continue;
+      if (!isoctal(*p))
+        break;
+    Lenter_loop_oct:
+      if (ulong_ < ulong.max/2 || (ulong_ == ulong.max/2 && *p <= '1'))
+      {
+        ulong_ *= 8;
+        ulong_ += *p - '0';
+        ++p;
+        continue;
+      }
+      // Overflow: skip following digits.
+      overflow = true;
+      while (isdigit(*++p)) {}
+      break;
+    }
+
+    bool hasDecimalDigits;
+    if (isdigit(*p))
+    {
+      hasDecimalDigits = true;
+      while (isdigit(*++p)) {}
+    }
+
+    // The number could be a float, so check errors below.
+    switch (*p)
+    {
+    case '.':
+      if (p[1] != '.')
+        goto LscanReal;
+      break;
+    case 'L':
+      if (p[1] != 'i')
+        break;
+    case 'i', 'f', 'F', 'e', 'E':
+      goto LscanReal;
+    default:
+    }
+
+    if (hasDecimalDigits)
+      error(MID.OctalNumberHasDecimals);
+    if (overflow)
+      error(MID.OverflowOctalNumber);
+//     goto Lfinalize;
+
+  Lfinalize:
+    enum Suffix
+    {
+      None     = 0,
+      Unsigned = 1,
+      Long     = 2
+    }
+
+    Suffix suffix;
+    while (1)
+    {
+      switch (*p)
+      {
+      case 'L':
+        if (suffix & Suffix.Long)
+          break;
+        suffix |= Suffix.Long;
+        ++p;
+        continue;
+      case 'u', 'U':
+        if (suffix & Suffix.Unsigned)
+          break;
+        suffix |= Suffix.Unsigned;
+        ++p;
+        continue;
+      default:
+        break;
+      }
+      break;
+    }
+
+    switch (suffix)
+    {
+    case Suffix.None:
+      if (ulong_ & 0x8000000000000000)
+      {
+        if (isDecimal)
+          error(MID.OverflowDecimalSign);
+        t.type = TOK.Uint64;
+      }
+      else if (ulong_ & 0xFFFFFFFF00000000)
+        t.type = TOK.Int64;
+      else if (ulong_ & 0x80000000)
+        t.type = isDecimal ? TOK.Int64 : TOK.Uint32;
+      else
+        t.type = TOK.Int32;
+      break;
+    case Suffix.Unsigned:
+      if (ulong_ & 0xFFFFFFFF00000000)
+        t.type = TOK.Uint64;
+      else
+        t.type = TOK.Uint32;
+      break;
+    case Suffix.Long:
+      if (ulong_ & 0x8000000000000000)
+      {
+        if (isDecimal)
+          error(MID.OverflowDecimalSign);
+        t.type = TOK.Uint64;
+      }
+      else
+        t.type = TOK.Int64;
+      break;
+    case Suffix.Unsigned | Suffix.Long:
+      t.type = TOK.Uint64;
+      break;
+    default:
+      assert(0);
+    }
+    t.ulong_ = ulong_;
+    t.end = p;
+    return;
+  LscanReal:
+    scanReal(t);
+    return;
+  }
+
+  /*
+    FloatLiteral:= Float[fFL]?i?
+    Float:= DecFloat | HexFloat
+    DecFloat:= ([0-9][0-9_]*[.][0-9_]*DecExponent?) | [.][0-9][0-9_]*DecExponent? | [0-9][0-9_]*DecExponent
+    DecExponent:= [eE][+-]?[0-9][0-9_]*
+    HexFloat:= 0[xX](HexDigits[.]HexDigits | [.][0-9a-zA-Z]HexDigits? | HexDigits)HexExponent
+    HexExponent:= [pP][+-]?[0-9][0-9_]*
+  */
+  void scanReal(ref Token t)
+  {
+    if (*p == '.')
+      // This function was called by scan() or scanNumber().
+      while (isdigit(*++p) || *p == '_') {}
+    else
+    {
+      // This function was called by scanNumber().
+      debug switch (*p)
+      {
+      case 'L':
+        if (p[1] != 'i')
+          assert(0);
+      case 'i', 'f', 'F', 'e', 'E': break;
+      default: assert(0);
+      }
+    }
+
+    // Scan exponent.
+    if (*p == 'e' || *p == 'E')
+    {
+      ++p;
+      if (*p == '-' || *p == '+')
+        ++p;
+      if (!isdigit(*p))
+        error(MID.FloatExponentDigitExpected);
+      else
+        while (isdigit(*++p) || *p == '_') {}
+    }
+
+    // Copy string to buffer ignoring underscores.
+    char[] buffer;
+    char* end = p;
+    p = t.start;
+    do
+    {
+      if (*p == '_')
+      {
+        ++p;
+        continue;
+      }
+      buffer ~= *p;
+      ++p;
+    } while (p != end)
+    buffer ~= 0;
+    finalizeFloat(t, buffer);
+  }
+
+  void scanHexReal(ref Token t)
+  {
+    assert(*p == '.' || *p == 'i' || *p == 'p' || *p == 'P' || (*p == 'L' && p[1] == 'i'));
+    MID mid;
+    if (*p == '.')
+      while (ishexad(*++p) || *p == '_') {}
+    if (*p != 'p' && *p != 'P')
+    {
+      mid = MID.HexFloatExponentRequired;
+      goto Lerr;
+    }
+    // Copy mantissa to a buffer ignoring underscores.
+    char* end = p;
+    p = t.start;
+    char[] buffer;
+    do
+    {
+      if (*p == '_')
+      {
+        ++p;
+        continue;
+      }
+      buffer ~= *p;
+      ++p;
+    } while (p != end)
+
+    assert(p == end && (*p == 'p' || *p == 'P'));
+    // Scan and copy the exponent.
+    buffer ~= 'p';
+    size_t bufflen = buffer.length;
+    while (1)
+    {
+      if (*++p == '_')
+        continue;
+      if (isdigit(*p))
+        buffer ~= *p;
+      else
+        break;
+    }
+    // When the buffer length hasn't changed, no digits were copied.
+    if (bufflen == buffer.length) {
+      mid = MID.HexFloatMissingExpDigits;
+      goto Lerr;
+    }
+    buffer ~= 0; // Terminate for C functions.
+    finalizeFloat(t, buffer);
+    return;
+  Lerr:
+    t.type = TOK.Float32;
+    t.end = p;
+    error(mid);
+  }
+
+  void finalizeFloat(ref Token t, string buffer)
+  {
+    // Float number is well-formed. Check suffixes and do conversion.
+    switch (*p)
+    {
+    case 'f', 'F':
+      t.type = TOK.Float32;
+      t.float_ = strtof(buffer.ptr, null);
+      ++p;
+      break;
+    case 'L':
+      t.type = TOK.Float80;
+      t.real_ = strtold(buffer.ptr, null);
+      ++p;
+      break;
+    default:
+      t.type = TOK.Float64;
+      t.double_ = strtod(buffer.ptr, null);
+      break;
+    }
+    if (*p == 'i')
+    {
+      ++p;
+      t.type += 3; // Switch to imaginary counterpart.
+    }
+    if (getErrno == ERANGE)
+      error(MID.OverflowFloatNumber);
+    t.end = p;
+  }
+
+  /// Scan special token: #line Integer [Filespec] EndOfLine
+  void scanSpecialToken(ref Token t)
+  {
+    assert(*p == '#');
+
+    t.type = TOK.HashLine;
+
+    MID mid;
+
+    ++p;
+    if (p[0] != 'l' || p[1] != 'i' || p[2] != 'n' || p[3] != 'e')
+    {
+      mid = MID.ExpectedNumberAfterSTLine;
+      goto Lerr;
+    }
+    p += 3;
+
+    enum State
+    { Number, Filespec, End }
+
+    State state;
+
+  Loop:
+    while (1)
+    {
+      switch (*++p)
+      {
+      case '\r':
+        if (p[1] == '\n')
+          ++p;
+      case '\n', 0, _Z_:
+        break Loop;
+      case LS[0]:
+        if (p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2]))
+        {
+          ++p; ++p;
+          break Loop;
+        }
+        goto default;
+      default:
+        if (isspace(*p))
+          continue;
+        if (state == State.Number)
+        {
+          if (!isdigit(*p))
+          {
+            mid = MID.ExpectedNumberAfterSTLine;
+            goto Lerr;
+          }
+          t.line_num = new Token;
+          scan(*t.line_num);
+          --p;
+          state = State.Filespec;
+        }
+        else if (state == State.Filespec)
+        {
+          if (*p != '"')
+          {
+            mid = MID.ExpectedFilespec;
+            goto Lerr;
+          }
+          t.line_filespec = new Token;
+          t.line_filespec.start = p;
+          t.line_filespec.type = TOK.Filespec;
+          while (1)
+          {
+            switch (*++p)
+            {
+            case '"':
+              break;
+            case LS[0]:
+              if (!(p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2])))
+                goto default;
+            case '\r', '\n', 0, _Z_:
+              mid = MID.UnterminatedFilespec;
+              t.line_filespec.end = p;
+              goto Lerr;
+            default:
+              if (*p & 128)
+                decodeUTF8();
+              continue;
+            }
+            break; // Exit loop.
+          }
+          auto start = t.line_filespec.start +1; // +1 skips '"'
+          t.line_filespec.str = start[0 .. p - start];
+          t.line_filespec.end = p + 1;
+          state = State.End;
+        }
+        else/+ if (state == State.End)+/
+        {
+          mid = MID.UnterminatedSpecialToken;
+          goto Lerr;
+        }
+      }
+    }
+
+    if (state == State.Number)
+    {
+      mid = MID.ExpectedNumberAfterSTLine;
+      goto Lerr;
+    }
+
+    this.loc = t.line_num.uint_ - 1;
+    if (t.line_filespec)
+      this.fileName = t.line_filespec.str;
+    t.end = p;
+
+    return;
+  Lerr:
+    t.end = p;
+    error(mid);
+  }
+
+  dchar decodeUTF8()
+  {
+    assert(*p & 128, "check for ASCII char before calling decodeUTF8().");
+    size_t idx;
+    dchar d;
+    try
+    {
+      d = std.utf.decode(p[0 .. end-p], idx);
+      p += idx -1;
+    }
+    catch (UtfException e)
+    {
+      error(MID.InvalidUTF8Sequence);
+      // Skip to next valid utf-8 sequence
+      while (UTF8stride[*++p] != 0xFF) {}
+      --p;
+    }
+    return d;
+  }
+
+  void loadKeywords()
+  {
+    foreach(k; keywords)
+      idtable[k.str] = k;
+  }
+/+
+  struct State
+  {
+    Lexer lexer;
+    Token token;
+    char* scanPointer;
+    int loc;
+    string fileName;
+    size_t errorLen;
+    static State opCall(Lexer lx)
+    {
+      State s;
+      s.lexer = lx;
+      s.token = lx.token;
+      s.scanPointer = lx.p;
+      s.loc = lx.loc;
+      s.fileName = lx.fileName;
+      s.errorLen = lx.errors.length;
+      return s;
+    }
+    void restore()
+    {
+      lexer.p = scanPointer;
+      lexer.token = token;
+      lexer.loc = loc;
+      lexer.fileName = fileName;
+      lexer.errors = lexer.errors[0..errorLen];
+    }
+  }
+
+  State getState()
+  {
+    return State(this);
+  }
++/
+
+  private void scanNext(ref Token* t)
+  {
+    assert(t !is null);
+    if (t.next)
+      t = t.next;
+    else if (t.type != TOK.EOF)
+    {
+      Token* new_t = new Token;
+      scan(*new_t);
+      new_t.prev = t;
+      t.next = new_t;
+      t = new_t;
+    }
+  }
+
+  void peek(ref Token* t)
+  {
+    scanNext(t);
+  }
+
+  TOK nextToken()
+  {
+    scanNext(this.token);
+    return this.token.type;
+  }
+
+  void error(MID id, ...)
+  {
+//     if (reportErrors)
+    errors ~= new Information(InfoType.Lexer, id, loc, arguments(_arguments, _argptr));
+  }
+
+  unittest
+  {
+    string sourceText = "unittest { }";
+    auto lx = new Lexer(sourceText, null);
+
+    Token next;
+    lx.peek(next);
+    assert(next == TOK.Unittest);
+    lx.peek(next);
+    assert(next == TOK.LBrace);
+    lx.peek(next);
+    assert(next == TOK.RBrace);
+    lx.peek(next);
+    assert(next == TOK.EOF);
+    writefln("end of peek() unittest");
+  }
+
+  Token* getTokens()
+  {
+    while (nextToken() != TOK.EOF)
+    {}
+    return head;
+  }
+
+  private void encodeUTF8(inout char[] str, dchar d)
+  {
+    char[6] b;
+    assert(d > 0x7F, "check for ASCII char before calling encodeUTF8().");
+    if (d < 0x800)
+    {
+      b[0] = 0xC0 | (d >> 6);
+      b[1] = 0x80 | (d & 0x3F);
+      str ~= b[0..2];
+    }
+    else if (d < 0x10000)
+    {
+      b[0] = 0xE0 | (d >> 12);
+      b[1] = 0x80 | ((d >> 6) & 0x3F);
+      b[2] = 0x80 | (d & 0x3F);
+      str ~= b[0..3];
+    }
+    else if (d < 0x200000)
+    {
+      b[0] = 0xF0 | (d >> 18);
+      b[1] = 0x80 | ((d >> 12) & 0x3F);
+      b[2] = 0x80 | ((d >> 6) & 0x3F);
+      b[3] = 0x80 | (d & 0x3F);
+      str ~= b[0..4];
+    }
+    else if (d < 0x4000000)
+    {
+      b[0] = 0xF8 | (d >> 24);
+      b[1] = 0x80 | ((d >> 18) & 0x3F);
+      b[2] = 0x80 | ((d >> 12) & 0x3F);
+      b[3] = 0x80 | ((d >> 6) & 0x3F);
+      b[4] = 0x80 | (d & 0x3F);
+      str ~= b[0..5];
+    }
+    else if (d < 0x80000000)
+    {
+      b[0] = 0xFC | (d >> 30);
+      b[1] = 0x80 | ((d >> 24) & 0x3F);
+      b[2] = 0x80 | ((d >> 18) & 0x3F);
+      b[3] = 0x80 | ((d >> 12) & 0x3F);
+      b[4] = 0x80 | ((d >> 6) & 0x3F);
+      b[5] = 0x80 | (d & 0x3F);
+      str ~= b[0..6];
+    }
+    else
+      error(MID.InvalidUnicodeCharacter);
+  }
+}
+
+unittest
+{
+  string[] toks = [
+    ">",    ">=", ">>",  ">>=", ">>>", ">>>=", "<",   "<=",  "<>",
+    "<>=",  "<<", "<<=", "!",   "!<",  "!>",   "!<=", "!>=", "!<>",
+    "!<>=", ".",  "..",  "...", "&",   "&&",   "&=",  "+",   "++",
+    "+=",   "-",  "--",  "-=",  "=",   "==",   "~",   "~=",  "*",
+    "*=",   "/",  "/=",  "^",   "^=",  "%",    "%=",  "(",   ")",
+    "[",    "]",  "{",   "}",   ":",   ";",    "?",   ",",   "$"
+  ];
+
+  char[] src;
+
+  foreach (op; toks)
+    src ~= op ~ " ";
+
+  auto lx = new Lexer(src, "");
+  auto tokens = lx.getTokens();
+
+  tokens = tokens[0..$-1]; // exclude TOK.EOF
+
+  assert(tokens.length == toks.length );
+
+  foreach (i, t; tokens)
+    assert(t.srcText == toks[i], std.string.format("Lexed '%s' but expected '%s'", t.srcText, toks[i]));
+}
+
+unittest
+{
+  // Numbers unittest
+  // 0L 0ULi 0_L 0_UL 0x0U 0x0p2 0_Fi 0_e2 0_F 0_i
+  // 0u 0U 0uL 0UL 0L 0LU 0Lu
+  // 0Li 0f 0F 0fi 0Fi 0i
+  // 0b_1_LU 0b1000u
+  // 0x232Lu
+}
+
+/// ASCII character properties table.
+static const int ptable[256] = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,32, 0,32,32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+32, 0, 0x2200, 0, 0, 0, 0, 0x2700, 0, 0, 0, 0, 0, 0, 0, 0,
+ 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 0, 0, 0, 0, 0, 0x3f00,
+ 0,12,12,12,12,12,12, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0x5c00, 0, 0,16,
+ 0, 0x70c, 0x80c,12,12,12, 0xc0c, 8, 8, 8, 8, 8, 8, 8, 0xa08, 8,
+ 8, 8, 0xd08, 8, 0x908, 8, 0xb08, 8, 8, 8, 8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+];
+
+enum CProperty
+{
+       Octal = 1,
+       Digit = 1<<1,
+         Hex = 1<<2,
+       Alpha = 1<<3,
+  Underscore = 1<<4,
+  Whitespace = 1<<5
+}
+
+const uint EVMask = 0xFF00; // Bit mask for escape value
+
+private alias CProperty CP;
+int isoctal(char c) { return ptable[c] & CP.Octal; }
+int isdigit(char c) { return ptable[c] & CP.Digit; }
+int ishexad(char c) { return ptable[c] & CP.Hex; }
+int isalpha(char c) { return ptable[c] & CP.Alpha; }
+int isalnum(char c) { return ptable[c] & (CP.Alpha | CP.Digit); }
+int isidbeg(char c) { return ptable[c] & (CP.Alpha | CP.Underscore); }
+int isident(char c) { return ptable[c] & (CP.Alpha | CP.Underscore | CP.Digit); }
+int isspace(char c) { return ptable[c] & CP.Whitespace; }
+int char2ev(char c) { return ptable[c] >> 8; /*(ptable[c] & EVMask) >> 8;*/ }
+
+version(gen_ptable)
+static this()
+{
+  alias ptable p;
+  // Initialize character properties table.
+  for (int i; i < p.length; ++i)
+  {
+    p[i] = 0;
+    if ('0' <= i && i <= '7')
+      p[i] |= CP.Octal;
+    if ('0' <= i && i <= '9')
+      p[i] |= CP.Digit;
+    if (isdigit(i) || 'a' <= i && i <= 'f' || 'A' <= i && i <= 'F')
+      p[i] |= CP.Hex;
+    if ('a' <= i && i <= 'z' || 'A' <= i && i <= 'Z')
+      p[i] |= CP.Alpha;
+    if (i == '_')
+      p[i] |= CP.Underscore;
+    if (i == ' ' || i == '\t' || i == '\v' || i == '\f')
+      p[i] |= CP.Whitespace;
+  }
+  // Store escape sequence values in second byte.
+  assert(CProperty.max <= ubyte.max, "character property flags and escape value byte overlap.");
+  p['\''] |= 39 << 8;
+  p['"'] |= 34 << 8;
+  p['?'] |= 63 << 8;
+  p['\\'] |= 92 << 8;
+  p['a'] |= 7 << 8;
+  p['b'] |= 8 << 8;
+  p['f'] |= 12 << 8;
+  p['n'] |= 10 << 8;
+  p['r'] |= 13 << 8;
+  p['t'] |= 9 << 8;
+  p['v'] |= 11 << 8;
+  // Print a formatted array literal.
+  char[] array = "[\n";
+  for (int i; i < p.length; ++i)
+  {
+    int c = p[i];
+    array ~= std.string.format(c>255?" 0x%x,":"%2d,", c, ((i+1) % 16) ? "":"\n");
+  }
+  array[$-2..$] = "\n]";
+  writefln(array);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/Messages.d	Tue Aug 21 16:28:05 2007 +0000
@@ -0,0 +1,108 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module Messages;
+import Settings;
+import std.stdarg;
+
+/// Index into table of compiler messages.
+enum MID
+{
+  // Lexer messages:
+  InvalidUnicodeCharacter,
+  InvalidUTF8Sequence,
+  // ''
+  UnterminatedCharacterLiteral,
+  EmptyCharacterLiteral,
+  // #line
+  ExpectedIdentifierSTLine,
+  ExpectedNumberAfterSTLine,
+  ExpectedFilespec,
+  UnterminatedFilespec,
+  UnterminatedSpecialToken,
+  // ""
+  UnterminatedString,
+  // x""
+  NonHexCharInHexString,
+  OddNumberOfDigitsInHexString,
+  UnterminatedHexString,
+  // /* */ /+ +/
+  UnterminatedBlockComment,
+  UnterminatedNestedComment,
+  // `` r""
+  UnterminatedRawString,
+  UnterminatedBackQuoteString,
+  // \x \u \U
+  UndefinedEscapeSequence,
+  InsufficientHexDigits,
+  // \&[a-zA-Z][a-zA-Z0-9]+;
+  UndefinedHTMLEntity,
+  UnterminatedHTMLEntity,
+  InvalidBeginHTMLEntity,
+  // integer overflows
+  OverflowDecimalSign,
+  OverflowDecimalNumber,
+  OverflowHexNumber,
+  OverflowBinaryNumber,
+  OverflowOctalNumber,
+  OverflowFloatNumber,
+  OctalNumberHasDecimals,
+  NoDigitsInHexNumber,
+  NoDigitsInBinNumber,
+  HexFloatExponentRequired,
+  HexFloatMissingExpDigits,
+  FloatExponentDigitExpected,
+
+  // Parser messages:
+  ExpectedButFound,
+  RedundantStorageClass,
+
+  // Help messages:
+  HelpMain,
+}
+
+string GetMsg(MID mid)
+{
+  assert(mid < GlobalSettings.messages.length);
+  return GlobalSettings.messages[mid];
+}
+
+char[] format(MID mid, ...)
+{
+  auto args = arguments(_arguments, _argptr);
+  return format_args(GetMsg(mid), args);
+}
+
+char[] format(char[] format_str, ...)
+{
+  auto args = arguments(_arguments, _argptr);
+  return format_args(format_str, args);
+}
+
+char[] format_args(char[] format_str, char[][] args)
+{
+  char[] result = format_str;
+
+  foreach (i, arg; args)
+    result = std.string.replace(result, std.string.format("{%s}", i+1), arg);
+
+  return result;
+}
+
+char[][] arguments(TypeInfo[] tinfos, void* argptr)
+{
+  char[][] args;
+  foreach (ti; tinfos)
+  {
+    if (ti == typeid(char[]))
+      args ~= va_arg!(char[])(argptr);
+    else if (ti == typeid(int))
+      args ~= std.string.format(va_arg!(int)(argptr));
+    else if (ti == typeid(dchar))
+      args ~= std.string.format(va_arg!(dchar)(argptr));
+    else
+      assert(0, "argument type not supported yet.");
+  }
+  return args;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/Parser.d	Tue Aug 21 16:28:05 2007 +0000
@@ -0,0 +1,4193 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module Parser;
+import Lexer;
+import SyntaxTree;
+import Token;
+import Messages;
+import Information;
+import Declarations;
+import Statements;
+import Expressions;
+import Types;
+import std.stdio;
+
+private alias TOK T;
+
+class Parser
+{
+  Lexer lx;
+  Token* token; /// Current non-whitespace token.
+  Token* prevToken; /// Previous non-whitespace token.
+
+  Information[] errors;
+
+  this(char[] srcText, string fileName)
+  {
+    lx = new Lexer(srcText, fileName);
+  }
+
+  debug char* prev;
+
+  void start()
+  {
+    debug prev = lx.text.ptr;
+    nT();
+    prevToken = token;
+  }
+
+  void nT()
+  {
+    prevToken = token;
+    do
+    {
+      lx.nextToken();
+      token = lx.token;
+
+debug if (!trying)
+{
+      writef("\33[32m%s\33[0m", token.type);
+      writef("%s", prev[0 .. token.end - prev]);
+      prev = token.end;
+}
+    } while (token.isWhitespace) // Skip whitespace
+  }
+
+  void skipToOnePast(TOK tok)
+  {
+    for (; token.type != tok && token.type != T.EOF; nT())
+    {}
+    nT();
+  }
+
+  int trying;
+  int errorCount;
+
+  ReturnType try_(ReturnType)(lazy ReturnType parseMethod, out bool success)
+  {
+debug writef("\33[31mtry_\33[0m");
+    ++trying;
+//     auto len = errors.length;
+    auto oldToken = token;
+    auto oldPrevToken = prevToken;
+    auto oldCount = errorCount;
+//     auto lexerState = lx.getState();
+    auto result = parseMethod();
+    // If the length of the array changed we know an error occurred.
+    if (errorCount != oldCount)
+    {
+//       lexerState.restore(); // Restore state of the Lexer object.
+//       errors = errors[0..len]; // Remove errors that were added when parseMethod() was called.
+      token = oldToken;
+      prevToken = oldPrevToken;
+      lx.token = oldToken;
+      errorCount = oldCount;
+      success = false;
+    }
+    else
+      success = true;
+    --trying;
+debug writef("\33[34m%s\33[0m", success);
+    return result;
+  }
+
+  Class set(Class)(Class node, Token* begin)
+  {
+    node.setTokens(begin, this.prevToken);
+    return node;
+  }
+
+  TOK peekNext()
+  {
+    Token* next = token;
+    do
+      lx.peek(next);
+    while (next.isWhitespace) // Skip whitespace
+    return next.type;
+  }
+
+  /++++++++++++++++++++++++++++++
+  + Declaration parsing methods +
+  ++++++++++++++++++++++++++++++/
+
+  Declarations parseModule()
+  {
+    auto decls = new Declarations;
+
+    if (token.type == T.Module)
+    {
+      auto begin = token;
+      ModuleName moduleName;
+      do
+      {
+        nT();
+        moduleName ~= requireId();
+      } while (token.type == T.Dot)
+      require(T.Semicolon);
+      decls ~= set(new ModuleDeclaration(moduleName), begin);
+    }
+    decls ~= parseDeclarationDefinitions();
+    return decls;
+  }
+
+  Declarations parseDeclarationDefinitions()
+  {
+    auto decls = new Declarations;
+    while (token.type != T.EOF)
+      decls ~= parseDeclarationDefinition();
+    return decls;
+  }
+
+  /*
+    DeclDefsBlock:
+        { }
+        { DeclDefs }
+  */
+  Declarations parseDeclarationDefinitionsBlock()
+  {
+    auto decls = new Declarations;
+    require(T.LBrace);
+    while (token.type != T.RBrace && token.type != T.EOF)
+      decls ~= parseDeclarationDefinition();
+    require(T.RBrace);
+    return decls;
+  }
+
+  Declaration parseDeclarationDefinition()
+  {
+    auto begin = token;
+    Declaration decl;
+    switch (token.type)
+    {
+    case T.Align,
+         T.Pragma,
+         // Protection attributes
+         T.Export,
+         T.Private,
+         T.Package,
+         T.Protected,
+         T.Public:
+      decl = parseAttributeSpecifier();
+      break;
+    // Storage classes
+    case T.Extern,
+         T.Deprecated,
+         T.Override,
+         T.Abstract,
+         T.Synchronized,
+         //T.Static,
+         T.Final,
+         T.Const,
+         //T.Invariant, // D 2.0
+         T.Auto,
+         T.Scope:
+    case_StaticAttribute:
+    case_InvariantAttribute: // D 2.0
+      decl = parseStorageAttribute();
+      break;
+    case T.Alias:
+      nT();
+      // TODO: parse StorageClasses?
+      decl = new AliasDeclaration(parseDeclaration());
+      break;
+    case T.Typedef:
+      nT();
+      // TODO: parse StorageClasses?
+      decl = new TypedefDeclaration(parseDeclaration());
+      break;
+    case T.Static:
+      switch (peekNext())
+      {
+      case T.Import:
+        goto case T.Import;
+      case T.This:
+        decl = parseStaticConstructorDeclaration();
+        break;
+      case T.Tilde:
+        decl = parseStaticDestructorDeclaration();
+        break;
+      case T.If:
+        decl = parseStaticIfDeclaration();
+        break;
+      case T.Assert:
+        decl = parseStaticAssertDeclaration();
+        break;
+      default:
+        goto case_StaticAttribute;
+      }
+      break;
+    case T.Import:
+      decl = parseImportDeclaration();
+      break;
+    case T.Enum:
+      decl = parseEnumDeclaration();
+      break;
+    case T.Class:
+      decl = parseClassDeclaration();
+      break;
+    case T.Interface:
+      decl = parseInterfaceDeclaration();
+      break;
+    case T.Struct, T.Union:
+      decl = parseAggregateDeclaration();
+      break;
+    case T.This:
+      decl = parseConstructorDeclaration();
+      break;
+    case T.Tilde:
+      decl = parseDestructorDeclaration();
+      break;
+    case T.Invariant:
+    version(D2)
+    {
+      auto next = token;
+      lx.peek(next);
+      if (next.type == T.LParen)
+      {
+        lx.peek(next);
+        if (next.type != T.RParen)
+          goto case_Declaration;
+      }
+      else
+        goto case_InvariantAttribute;
+    }
+      decl = parseInvariantDeclaration();
+      break;
+    case T.Unittest:
+      decl = parseUnittestDeclaration();
+      break;
+    case T.Debug:
+      decl = parseDebugDeclaration();
+      break;
+    case T.Version:
+      decl = parseVersionDeclaration();
+      break;
+    case T.Template:
+      decl = parseTemplateDeclaration();
+      break;
+    case T.New:
+      decl = parseNewDeclaration();
+      break;
+    case T.Delete:
+      decl = parseDeleteDeclaration();
+      break;
+    case T.Mixin:
+      decl = parseMixin!(MixinDeclaration)();
+      break;
+    case T.Semicolon:
+      nT();
+      decl = new EmptyDeclaration();
+      break;
+    // Declaration
+    case T.Identifier, T.Dot, T.Typeof:
+    // BasicType
+    case T.Char,   T.Wchar,   T.Dchar,  T.Bool,
+         T.Byte,   T.Ubyte,   T.Short,  T.Ushort,
+         T.Int,    T.Uint,    T.Long,   T.Ulong,
+         T.Float,  T.Double,  T.Real,
+         T.Ifloat, T.Idouble, T.Ireal,
+         T.Cfloat, T.Cdouble, T.Creal, T.Void:
+    case_Declaration:
+      decl = parseDeclaration();
+      break;
+    /+case T.Module:
+      // TODO: Error: module is optional and can appear only once at the top of the source file.
+      break;+/
+    default:
+      error(MID.ExpectedButFound, "Declaration", token.srcText);
+      decl = new IllegalDeclaration(token);
+      nT();
+    }
+//     writef("§%s§", decl.classinfo.name);
+    set(decl, begin);
+    return decl;
+  }
+
+  /*
+    DeclarationsBlock:
+        : DeclDefs
+        { }
+        { DeclDefs }
+        DeclDef
+  */
+  Declaration parseDeclarationsBlock()
+  {
+    Declaration d;
+    switch (token.type)
+    {
+    case T.LBrace:
+      d = parseDeclarationDefinitionsBlock();
+      break;
+    case T.Colon:
+      nT();
+      auto decls = new Declarations;
+      while (token.type != T.RBrace && token.type != T.EOF)
+        decls ~= parseDeclarationDefinition();
+      d = decls;
+      break;
+    default:
+      d = parseDeclarationDefinition();
+    }
+    return d;
+  }
+
+  Declaration parseDeclaration(StorageClass stc = StorageClass.None)
+  {
+    Type type;
+    Token* ident;
+
+    // Check for AutoDeclaration
+    if (stc != StorageClass.None &&
+        token.type == T.Identifier &&
+        peekNext() == T.Assign)
+    {
+      ident = token;
+      nT();
+    }
+    else
+    {
+      type = parseType();
+      ident = requireId();
+      // Type FunctionName ( ParameterList ) FunctionBody
+      if (token.type == T.LParen)
+      {
+        // It's a function declaration
+        TemplateParameters tparams;
+        if (tokenAfterParenIs(T.LParen))
+        {
+          // ( TemplateParameterList ) ( ParameterList )
+          tparams = parseTemplateParameterList();
+        }
+
+        auto params = parseParameterList();
+        // ReturnType FunctionName ( ParameterList )
+        auto funcBody = parseFunctionBody();
+        return new FunctionDeclaration(type, ident, tparams, params, funcBody);
+      }
+      type = parseDeclaratorSuffix(type);
+    }
+
+    // It's a variable declaration.
+    Token*[] 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();
+    LenterLoop:
+      if (token.type == T.Assign)
+      {
+        nT();
+        values ~= parseInitializer();
+      }
+      else
+        values ~= null;
+    }
+    require(T.Semicolon);
+    return new VariableDeclaration(type, idents, values);
+  }
+
+  Expression parseInitializer()
+  {
+    if (token.type == T.Void)
+    {
+      auto begin = token;
+      auto next = peekNext();
+      if (next == T.Comma || next == T.Semicolon)
+      {
+        nT();
+        return set(new VoidInitializer(), begin);
+      }
+    }
+    return parseNonVoidInitializer();
+  }
+
+  Expression parseNonVoidInitializer()
+  {
+    auto begin = token;
+    Expression init;
+    switch (token.type)
+    {
+    case T.LBracket:
+      // ArrayInitializer:
+      //         [ ]
+      //         [ ArrayMemberInitializations ]
+      Expression[] keys;
+      Expression[] values;
+
+      nT();
+      while (token.type != T.RBracket)
+      {
+        auto e = parseNonVoidInitializer();
+        if (token.type == T.Colon)
+        {
+          nT();
+          keys ~= e;
+          values ~= parseNonVoidInitializer();
+        }
+        else
+        {
+          keys ~= null;
+          values ~= e;
+        }
+
+        if (token.type != T.Comma)
+          break;
+        nT();
+      }
+      require(T.RBracket);
+      init = new ArrayInitializer(keys, values);
+      break;
+    case T.LBrace:
+      // StructInitializer:
+      //         { }
+      //         { StructMemberInitializers }
+      Expression parseStructInitializer()
+      {
+        Token*[] idents;
+        Expression[] values;
+
+        nT();
+        while (token.type != T.RBrace)
+        {
+          if (token.type == T.Identifier)
+          {
+            // Peek for colon to see if this is a member identifier.
+            if (peekNext() == T.Colon)
+            {
+              idents ~= token;
+              nT();
+              nT();
+            }
+          }
+          // NonVoidInitializer
+          values ~= parseNonVoidInitializer();
+
+          if (token.type != T.Comma)
+            break;
+          nT();
+        }
+        require(T.RBrace);
+        return new StructInitializer(idents, values);
+      }
+
+      bool success;
+      auto si = try_(parseStructInitializer(), success);
+      if (success)
+      {
+        init = si;
+        break;
+      }
+      assert(token.type == T.LBrace);
+      //goto default;
+    default:
+      init = parseAssignExpression();
+    }
+    set(init, begin);
+    return init;
+  }
+
+  FunctionBody parseFunctionBody()
+  {
+    auto begin = token;
+    auto func = new FunctionBody;
+    while (1)
+    {
+      switch (token.type)
+      {
+      case T.LBrace:
+        func.funcBody = parseStatements();
+        break;
+      case T.Semicolon:
+        nT();
+        break;
+      case T.In:
+        //if (func.inBody)
+          // TODO: issue error msg.
+        nT();
+        func.inBody = parseStatements();
+        continue;
+      case T.Out:
+        //if (func.outBody)
+          // TODO: issue error msg.
+        nT();
+        if (token.type == T.LParen)
+        {
+          nT();
+          func.outIdent = requireId();
+          require(T.RParen);
+        }
+        func.outBody = parseStatements();
+        continue;
+      case T.Body:
+        nT();
+        goto case T.LBrace;
+      default:
+        error(MID.ExpectedButFound, "FunctionBody", token.srcText);
+      }
+      break; // exit while loop
+    }
+    set(func, begin);
+    func.finishConstruction();
+    return func;
+  }
+
+  Declaration parseStorageAttribute()
+  {
+    StorageClass stc, tmp;
+
+    void addStorageClass()
+    {
+      if (stc & tmp)
+      {
+        error(MID.RedundantStorageClass, token.srcText);
+      }
+      else
+        stc |= tmp;
+    }
+
+    Declaration parse()
+    {
+      Declaration decl;
+      switch (token.type)
+      {
+      case T.Extern:
+        tmp = StorageClass.Extern;
+        addStorageClass();
+        nT();
+        Linkage linkage;
+        if (token.type == T.LParen)
+        {
+          nT();
+          auto ident = requireId();
+          switch (ident ? ident.identifier : null)
+          {
+          case "C":
+            if (token.type == T.PlusPlus)
+            {
+              nT();
+              linkage = Linkage.Cpp;
+              break;
+            }
+            linkage = Linkage.C;
+            break;
+          case "D":
+            linkage = Linkage.D;
+            break;
+          case "Windows":
+            linkage = Linkage.Windows;
+            break;
+          case "Pascal":
+            linkage = Linkage.Pascal;
+            break;
+          case "System":
+            linkage = Linkage.System;
+            break;
+          default:
+            // TODO: issue error msg. Unrecognized LinkageType.
+          }
+          require(T.RParen);
+        }
+        decl = new ExternDeclaration(linkage, parse());
+        break;
+      case T.Override:
+        tmp = StorageClass.Override;
+        goto Lcommon;
+      case T.Deprecated:
+        tmp = StorageClass.Deprecated;
+        goto Lcommon;
+      case T.Abstract:
+        tmp = StorageClass.Abstract;
+        goto Lcommon;
+      case T.Synchronized:
+        tmp = StorageClass.Synchronized;
+        goto Lcommon;
+      case T.Static:
+        tmp = StorageClass.Static;
+        goto Lcommon;
+      case T.Final:
+        tmp = StorageClass.Final;
+        goto Lcommon;
+      case T.Const:
+      version(D2)
+      {
+        if (peekNext() == T.LParen)
+          goto case_Declaration;
+      }
+        tmp = StorageClass.Const;
+        goto Lcommon;
+      version(D2)
+      {
+      case T.Invariant: // D 2.0
+        if (peekNext() == T.LParen)
+          goto case_Declaration;
+        tmp = StorageClass.Invariant;
+        goto Lcommon;
+      }
+      case T.Auto:
+        tmp = StorageClass.Auto;
+        goto Lcommon;
+      case T.Scope:
+        tmp = StorageClass.Scope;
+        goto Lcommon;
+      Lcommon:
+        addStorageClass();
+        auto tok = token.type;
+        nT();
+        decl = new AttributeDeclaration(tok, parse());
+        break;
+      case T.Identifier:
+      case_Declaration:
+        // This could be a normal Declaration or an AutoDeclaration
+        decl = parseDeclaration(stc);
+        break;
+      default:
+        decl = parseDeclarationsBlock();
+      }
+      return decl;
+    }
+    return parse();
+  }
+
+  Token* parseAlignAttribute()
+  {
+    assert(token.type == T.Align);
+    nT(); // Skip align keyword.
+    Token* tok;
+    if (token.type == T.LParen)
+    {
+      nT();
+      if (token.type == T.Int32)
+      {
+        tok = token;
+        nT();
+      }
+      else
+        expected(T.Int32);
+      require(T.RParen);
+    }
+    return tok;
+  }
+
+  Declaration parseAttributeSpecifier()
+  {
+    Declaration decl;
+
+    switch (token.type)
+    {
+    case T.Align:
+      int size = -1;
+      auto intTok = parseAlignAttribute();
+      if (intTok)
+        size = intTok.int_;
+      decl = new AlignDeclaration(size, parseDeclarationsBlock());
+      break;
+    case T.Pragma:
+      // Pragma:
+      //     pragma ( Identifier )
+      //     pragma ( Identifier , ExpressionList )
+      // ExpressionList:
+      //     AssignExpression
+      //     AssignExpression , ExpressionList
+      nT();
+      Token* ident;
+      Expression[] args;
+      Declaration decls;
+
+      require(T.LParen);
+      ident = requireId();
+
+      if (token.type == T.Comma)
+      {
+        // Parse at least one argument.
+        nT();
+        args ~= parseAssignExpression();
+      }
+
+      if (token.type == T.Comma)
+        args ~= parseArguments(T.RParen);
+      else
+        require(T.RParen);
+
+      if (token.type == T.Semicolon)
+      {
+        nT();
+        decls = new EmptyDeclaration();
+      }
+      else
+        decls = parseDeclarationsBlock();
+
+      decl = new PragmaDeclaration(ident, args, decls);
+      break;
+    // Protection attributes
+    case T.Private:
+    case T.Package:
+    case T.Protected:
+    case T.Public:
+    case T.Export:
+      auto tok = token.type;
+      nT();
+      decl = new AttributeDeclaration(tok, parseDeclarationsBlock());
+      break;
+    default:
+      assert(0);
+    }
+    return decl;
+  }
+
+  Declaration parseImportDeclaration()
+  {
+    assert(token.type == T.Import || token.type == T.Static);
+
+    bool isStatic;
+
+    if (token.type == T.Static)
+    {
+      isStatic = true;
+      nT();
+    }
+
+    ModuleName[] moduleNames;
+    Token*[] moduleAliases;
+    Token*[] bindNames;
+    Token*[] bindAliases;
+
+    nT(); // Skip import keyword.
+    while (1)
+    {
+      ModuleName moduleName;
+      Token* moduleAlias;
+
+      moduleAlias = requireId();
+
+      // AliasName = ModuleName
+      if (token.type == T.Assign)
+      {
+        nT();
+        moduleName ~= requireId();
+      }
+      else // import Identifier [^=]
+      {
+        moduleName ~= moduleAlias;
+        moduleAlias = null;
+      }
+
+      // Identifier(.Identifier)*
+      while (token.type == T.Dot)
+      {
+        nT();
+        moduleName ~= requireId();
+      }
+
+      // Push identifiers.
+      moduleNames ~= moduleName;
+      moduleAliases ~= moduleAlias;
+
+      if (token.type == T.Colon)
+        break;
+      if (token.type != T.Comma)
+        break;
+      nT();
+    }
+
+    if (token.type == T.Colon)
+    {
+      // BindAlias = BindName(, BindAlias = BindName)*;
+      // BindName(, BindName)*;
+      Token* bindName, bindAlias;
+      do
+      {
+        nT();
+        bindAlias = requireId();
+
+        if (token.type == T.Assign)
+        {
+          nT();
+          bindName = requireId();
+        }
+        else
+        {
+          bindName = bindAlias;
+          bindAlias = null;
+        }
+
+        // Push identifiers.
+        bindNames ~= bindName;
+        bindAliases ~= bindAlias;
+      } while (token.type == T.Comma)
+    }
+
+    require(T.Semicolon);
+
+    return new ImportDeclaration(moduleNames, moduleAliases, bindNames, bindAliases);
+  }
+
+  Declaration parseEnumDeclaration()
+  {
+    assert(token.type == T.Enum);
+
+    Token* enumName;
+    Type baseType;
+    Token*[] members;
+    Expression[] values;
+    bool hasBody;
+
+    nT(); // Skip enum keyword.
+
+    if (token.type == T.Identifier)
+    {
+      enumName = token;
+      nT();
+    }
+
+    if (token.type == T.Colon)
+    {
+      nT();
+      baseType = parseBasicType();
+    }
+
+    if (token.type == T.Semicolon)
+    {
+      if (enumName is null)
+        expected(T.Identifier);
+      nT();
+    }
+    else if (token.type == T.LBrace)
+    {
+      hasBody = true;
+      nT();
+      do
+      {
+        members ~= requireId();
+
+        if (token.type == T.Assign)
+        {
+          nT();
+          values ~= parseAssignExpression();
+        }
+        else
+          values ~= null;
+
+        if (token.type == T.Comma)
+          nT();
+        else if (token.type != T.RBrace)
+        {
+          expected(T.RBrace);
+          break;
+        }
+      } while (token.type != T.RBrace)
+      nT();
+    }
+    else
+      error(MID.ExpectedButFound, "enum declaration", token.srcText);
+
+    return new EnumDeclaration(enumName, baseType, members, values, hasBody);
+  }
+
+  Declaration parseClassDeclaration()
+  {
+    assert(token.type == T.Class);
+
+    Token* className;
+    TemplateParameters tparams;
+    BaseClass[] bases;
+    Declarations decls;
+    bool hasBody;
+
+    nT(); // Skip class keyword.
+    className = requireId();
+
+    if (token.type == T.LParen)
+    {
+      tparams = parseTemplateParameterList();
+    }
+
+    if (token.type == T.Colon)
+      bases = parseBaseClasses();
+
+    if (token.type == T.Semicolon)
+    {
+      //if (bases.length != 0)
+        // TODO: Error: bases classes are not allowed in forward declarations.
+      nT();
+    }
+    else if (token.type == T.LBrace)
+    {
+      hasBody = true;
+      // TODO: think about setting a member status variable to a flag InClassBody... this way we can check for DeclDefs that are illegal in class bodies in the parsing phase.
+      decls = parseDeclarationDefinitionsBlock();
+    }
+    else
+      expected(T.LBrace); // TODO: better error msg
+
+    return new ClassDeclaration(className, tparams, bases, decls, hasBody);
+  }
+
+  BaseClass[] parseBaseClasses(bool colonLeadsOff = true)
+  {
+    if (colonLeadsOff)
+    {
+      assert(token.type == T.Colon);
+      nT(); // Skip colon
+    }
+
+    BaseClass[] bases;
+
+    while (1)
+    {
+      Protection prot = Protection.Public;
+      switch (token.type)
+      {
+      case T.Identifier, T.Dot, T.Typeof: goto LparseBasicType;
+      case T.Private:   prot = Protection.Private;   break;
+      case T.Protected: prot = Protection.Protected; break;
+      case T.Package:   prot = Protection.Package;   break;
+      case T.Public:  /*prot = Protection.Public;*/  break;
+      default:
+        // TODO: issue error msg
+        return bases;
+      }
+      nT(); // Skip protection attribute.
+    LparseBasicType:
+      auto type = parseBasicType();
+      //if (type.tid != TID.DotList)
+        // TODO: issue error msg. base classes can only be one or more identifiers or template instances separated by dots.
+      bases ~= new BaseClass(prot, type);
+      if (token.type != T.Comma)
+        break;
+    }
+    return bases;
+  }
+
+  Declaration parseInterfaceDeclaration()
+  {
+    assert(token.type == T.Interface);
+
+    Token* name;
+    TemplateParameters tparams;
+    BaseClass[] bases;
+    Declarations decls;
+    bool hasBody;
+
+    nT(); // Skip interface keyword.
+    name = requireId();
+
+    if (token.type == T.LParen)
+    {
+      tparams = parseTemplateParameterList();
+    }
+
+    if (token.type == T.Colon)
+      bases = parseBaseClasses();
+
+    if (token.type == T.Semicolon)
+    {
+      //if (bases.length != 0)
+        // TODO: error: base classes are not allowed in forward declarations.
+      nT();
+    }
+    else if (token.type == T.LBrace)
+    {
+      hasBody = true;
+      decls = parseDeclarationDefinitionsBlock();
+    }
+    else
+      expected(T.LBrace); // TODO: better error msg
+
+    return new InterfaceDeclaration(name, tparams, bases, decls, hasBody);
+  }
+
+  Declaration parseAggregateDeclaration()
+  {
+    assert(token.type == T.Struct || token.type == T.Union);
+
+    TOK tok = token.type;
+
+    Token* name;
+    TemplateParameters tparams;
+    Declarations decls;
+    bool hasBody;
+
+    nT(); // Skip struct or union keyword.
+    // name is optional.
+    if (token.type == T.Identifier)
+    {
+      name = token;
+      nT();
+      if (token.type == T.LParen)
+      {
+        tparams = parseTemplateParameterList();
+      }
+    }
+
+    if (token.type == T.Semicolon)
+    {
+      //if (name.length == 0)
+        // TODO: error: forward declarations must have a name.
+      nT();
+    }
+    else if (token.type == T.LBrace)
+    {
+      hasBody = true;
+      decls = parseDeclarationDefinitionsBlock();
+    }
+    else
+      expected(T.LBrace); // TODO: better error msg
+
+    if (tok == T.Struct)
+      return new StructDeclaration(name, tparams, decls, hasBody);
+    else
+      return new UnionDeclaration(name, tparams, decls, hasBody);
+  }
+
+  Declaration parseConstructorDeclaration()
+  {
+    assert(token.type == T.This);
+    nT(); // Skip 'this' keyword.
+    auto parameters = parseParameterList();
+    auto funcBody = parseFunctionBody();
+    return new ConstructorDeclaration(parameters, funcBody);
+  }
+
+  Declaration parseDestructorDeclaration()
+  {
+    assert(token.type == T.Tilde);
+    nT(); // Skip ~
+    require(T.This);
+    require(T.LParen);
+    require(T.RParen);
+    auto funcBody = parseFunctionBody();
+    return new DestructorDeclaration(funcBody);
+  }
+
+  Declaration parseStaticConstructorDeclaration()
+  {
+    assert(token.type == T.Static);
+    nT(); // Skip static keyword.
+    nT(); // Skip 'this' keyword.
+    require(T.LParen);
+    require(T.RParen);
+    auto funcBody = parseFunctionBody();
+    return new StaticConstructorDeclaration(funcBody);
+  }
+
+  Declaration parseStaticDestructorDeclaration()
+  {
+    assert(token.type == T.Static);
+    nT(); // Skip static keyword.
+    nT(); // Skip ~
+    require(T.This);
+    require(T.LParen);
+    require(T.RParen);
+    auto funcBody = parseFunctionBody();
+    return new StaticDestructorDeclaration(funcBody);
+  }
+
+  Declaration parseInvariantDeclaration()
+  {
+    assert(token.type == T.Invariant);
+    nT(); // Skip invariant keyword.
+    // Optional () for getting ready porting to D 2.0
+    if (token.type == T.LParen)
+      requireNext(T.RParen);
+    auto funcBody = parseFunctionBody();
+    return new InvariantDeclaration(funcBody);
+  }
+
+  Declaration parseUnittestDeclaration()
+  {
+    assert(token.type == T.Unittest);
+
+    nT(); // Skip unittest keyword.
+    auto funcBody = parseFunctionBody();
+    return new UnittestDeclaration(funcBody);
+  }
+
+  Declaration parseDebugDeclaration()
+  {
+    assert(token.type == T.Debug);
+
+    nT(); // Skip debug keyword.
+
+    Token* spec; // debug = Integer ;
+                 // debug = Identifier ;
+    Token* cond; // debug ( Integer )
+                 // debug ( Identifier )
+    Declaration decls, elseDecls;
+
+    void parseIdentOrInt(ref Token* tok)
+    {
+      nT();
+      if (token.type == T.Int32 ||
+          token.type == T.Identifier)
+      {
+        tok = token;
+        nT();
+      }
+      else
+        expected(T.Identifier); // TODO: better error msg
+    }
+
+    if (token.type == T.Assign)
+    {
+      parseIdentOrInt(spec);
+      require(T.Semicolon);
+    }
+    else
+    {
+      // Condition:
+      //     Integer
+      //     Identifier
+      // ( Condition )
+      if (token.type == T.LParen)
+      {
+        parseIdentOrInt(cond);
+        require(T.RParen);
+      }
+
+      // debug DeclarationsBlock
+      // debug ( Condition ) DeclarationsBlock
+      decls = parseDeclarationsBlock();
+
+      // else DeclarationsBlock
+      if (token.type == T.Else)
+      {
+        nT();
+        //if (token.type == T.Colon)
+          // TODO: avoid "else:"?
+        elseDecls = parseDeclarationsBlock();
+      }
+    }
+
+    return new DebugDeclaration(spec, cond, decls, elseDecls);
+  }
+
+  Declaration parseVersionDeclaration()
+  {
+    assert(token.type == T.Version);
+
+    nT(); // Skip version keyword.
+
+    Token* spec; // version = Integer ;
+                 // version = Identifier ;
+    Token* cond; // version ( Integer )
+                 // version ( Identifier )
+    Declaration decls, elseDecls;
+
+    void parseIdentOrInt(ref Token* tok)
+    {
+      if (token.type == T.Int32 ||
+          token.type == T.Identifier)
+      {
+        tok = token;
+        nT();
+      }
+      else
+        expected(T.Identifier); // TODO: better error msg
+    }
+
+    if (token.type == T.Assign)
+    {
+      nT();
+      parseIdentOrInt(spec);
+      require(T.Semicolon);
+    }
+    else
+    {
+      // Condition:
+      //     Integer
+      //     Identifier
+
+      // ( Condition )
+      require(T.LParen);
+      parseIdentOrInt(cond);
+      require(T.RParen);
+
+      // version ( Condition ) DeclarationsBlock
+      decls = parseDeclarationsBlock();
+
+      // else DeclarationsBlock
+      if (token.type == T.Else)
+      {
+        nT();
+        //if (token.type == T.Colon)
+          // TODO: avoid "else:"?
+        elseDecls = parseDeclarationsBlock();
+      }
+    }
+
+    return new VersionDeclaration(spec, cond, decls, elseDecls);
+  }
+
+  Declaration parseStaticIfDeclaration()
+  {
+    assert(token.type == T.Static);
+
+    nT(); // Skip static keyword.
+    nT(); // Skip if keyword.
+
+    Expression condition;
+    Declaration ifDecls, elseDecls;
+
+    require(T.LParen);
+    condition = parseAssignExpression();
+    require(T.RParen);
+
+    if (token.type != T.Colon)
+      ifDecls = parseDeclarationsBlock();
+    else
+      expected(T.LBrace); // TODO: better error msg
+
+    if (token.type == T.Else)
+    {
+      nT();
+      if (token.type != T.Colon)
+        elseDecls = parseDeclarationsBlock();
+      else
+        expected(T.LBrace); // TODO: better error msg
+    }
+
+    return new StaticIfDeclaration(condition, ifDecls, elseDecls);
+  }
+
+  Declaration parseStaticAssertDeclaration()
+  {
+    assert(token.type == T.Static);
+
+    nT(); // Skip static keyword.
+    nT(); // Skip assert keyword.
+
+    Expression condition, message;
+
+    require(T.LParen);
+
+    condition = parseAssignExpression();
+
+    if (token.type == T.Comma)
+    {
+      nT();
+      message = parseAssignExpression();
+    }
+
+    require(T.RParen);
+    require(T.Semicolon);
+
+    return new StaticAssertDeclaration(condition, message);
+  }
+
+  Declaration parseTemplateDeclaration()
+  {
+    assert(token.type == T.Template);
+    nT(); // Skip template keyword.
+    auto templateName = requireId();
+    auto templateParams = parseTemplateParameterList();
+    auto decls = parseDeclarationDefinitionsBlock();
+    return new TemplateDeclaration(templateName, templateParams, decls);
+  }
+
+  Declaration parseNewDeclaration()
+  {
+    assert(token.type == T.New);
+    nT(); // Skip new keyword.
+    auto parameters = parseParameterList();
+    auto funcBody = parseFunctionBody();
+    return new NewDeclaration(parameters, funcBody);
+  }
+
+  Declaration parseDeleteDeclaration()
+  {
+    assert(token.type == T.Delete);
+    nT(); // Skip delete keyword.
+    auto parameters = parseParameterList();
+    // TODO: only one parameter of type void* allowed. Check in parsing or semantic phase?
+    auto funcBody = parseFunctionBody();
+    return new DeleteDeclaration(parameters, funcBody);
+  }
+
+  /+
+    DotListExpression:
+            . DotListItems
+            DotListItems
+            Typeof
+            Typeof . DotListItems
+    DotListItems:
+            DotListItem
+            DotListItem . DotListItems
+    DotListItem:
+            Identifier
+            TemplateInstance
+            NewExpression
+    TemplateInstance:
+            Identifier !( TemplateArguments )
+  +/
+  DotListExpression parseDotListExpression()
+  {
+    assert(token.type == T.Identifier || token.type == T.Dot || token.type == T.Typeof);
+    Expression[] identList;
+    if (token.type == T.Dot)
+    {
+      identList ~= new IdentifierExpression(token);
+      nT();
+    }
+    else if (token.type == T.Typeof)
+    {
+      requireNext(T.LParen);
+      auto type = new TypeofType(parseExpression());
+      require(T.RParen);
+      identList ~= new TypeofExpression(type);
+      if (token.type != T.Dot)
+        goto Lreturn;
+      nT();
+    }
+
+    while (1)
+    {
+      auto begin2 = token;
+      auto ident = requireId();
+      Expression e;
+      if (token.type == T.Not && peekNext() == T.LParen) // Identifier !( TemplateArguments )
+      {
+        nT(); // Skip !.
+        e = set(new TemplateInstanceExpression(ident, parseTemplateArguments()), begin2);
+      }
+      else // Identifier
+        e = set(new IdentifierExpression(ident), begin2);
+
+      identList ~= e;
+
+    LnewExpressionLoop:
+      if (token.type != T.Dot)
+        break;
+      nT(); // Skip dot.
+
+      if (token.type == T.New)
+      {
+        identList ~= parseNewExpression();
+        goto LnewExpressionLoop;
+      }
+    }
+
+  Lreturn:
+    return new DotListExpression(identList);
+  }
+
+  /+
+    DotListType:
+            . TypeItems
+            TypeItems
+            Typeof
+            Typeof . TypeItems
+    TypeItems:
+            TypeItem
+            TypeItem . TypeItems
+    TypeItem:
+            Identifier
+            TemplateInstance
+    TemplateInstance:
+            Identifier !( TemplateArguments )
+  +/
+  DotListType parseDotListType()
+  {
+    Type[] identList;
+    if (token.type == T.Dot)
+    {
+      identList ~= new IdentifierType(token);
+      nT();
+    }
+    else if (token.type == T.Typeof)
+    {
+      requireNext(T.LParen);
+      identList ~= new TypeofType(parseExpression());
+      require(T.RParen);
+      if (token.type != T.Dot)
+        goto Lreturn;
+      nT();
+    }
+
+    while (1)
+    {
+      auto begin2 = token;
+      auto ident = requireId();
+      // 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()), begin2);
+      }
+      else // Identifier
+        identList ~= set(new IdentifierType(ident), begin2);
+
+      if (token.type != T.Dot)
+        break;
+      nT();
+    }
+  Lreturn:
+    return new DotListType(identList);
+  }
+
+  /*
+    TemplateMixin:
+            mixin ( AssignExpression ) ;
+            mixin TemplateIdentifier ;
+            mixin TemplateIdentifier MixinIdentifier ;
+            mixin TemplateIdentifier !( TemplateArguments ) ;
+            mixin TemplateIdentifier !( TemplateArguments ) MixinIdentifier ;
+  */
+  Class parseMixin(Class)()
+  {
+    assert(token.type == T.Mixin);
+    auto begin = token;
+    nT(); // Skip mixin keyword.
+
+  static if (is(Class == MixinDeclaration))
+  {
+    if (token.type == T.LParen)
+    {
+      // TODO: What about mixin(...).ident;?
+      nT();
+      auto e = parseAssignExpression();
+      require(T.RParen);
+      require(T.Semicolon);
+      return new MixinDeclaration(e);
+    }
+  }
+
+    Expression[] templateIdent;
+    Token* mixinIdent;
+
+    // This code is similar to parseDotListType().
+    if (token.type == T.Dot)
+    {
+      templateIdent ~= new IdentifierExpression(token);
+      nT();
+    }
+
+    while (1)
+    {
+      auto ident = requireId();
+      Expression e;
+      if (token.type == T.Not) // Identifier !( TemplateArguments )
+      {
+        // No need to peek for T.LParen. This must be a template instance.
+        nT();
+        e = new TemplateInstanceExpression(ident, parseTemplateArguments());
+      }
+      else // Identifier
+        e = new IdentifierExpression(ident);
+
+      templateIdent ~= e;
+
+      if (token.type != T.Dot)
+        break;
+      nT();
+    }
+
+    if (token.type == T.Identifier)
+    {
+      mixinIdent = token;
+      nT();
+    }
+
+    require(T.Semicolon);
+
+    return new Class(templateIdent, mixinIdent);
+  }
+
+  /+++++++++++++++++++++++++++++
+  + Statement parsing methods  +
+  +++++++++++++++++++++++++++++/
+
+  Statements parseStatements()
+  {
+    auto begin = token;
+    require(T.LBrace);
+    auto statements = new Statements();
+    while (token.type != T.RBrace && token.type != T.EOF)
+      statements ~= parseStatement();
+    require(T.RBrace);
+    return set(statements, begin);
+  }
+
+  Statement parseStatement()
+  {
+// writefln("°parseStatement:(%d)token='%s'°", lx.loc, token.srcText);
+    auto begin = token;
+    Statement s;
+    Declaration d;
+    switch (token.type)
+    {
+    case T.Align:
+      int size = -1;
+      auto intTok = parseAlignAttribute();
+      if (intTok)
+        size = intTok.int_;
+      // Restrict align attribute to structs in parsing phase.
+      Declaration structDecl;
+      if (token.type == T.Struct)
+        structDecl = parseAggregateDeclaration();
+      else
+        expected(T.Struct);
+      d = new AlignDeclaration(size, structDecl ? structDecl : new Declarations);
+      goto case_DeclarationStatement;
+/+ Not applicable for statements.
+//          T.Private,
+//          T.Package,
+//          T.Protected,
+//          T.Public,
+//          T.Export,
+//          T.Deprecated,
+//          T.Override,
+//          T.Abstract,
++/
+    case T.Extern,
+         T.Final,
+         T.Const,
+         T.Auto:
+         //T.Scope
+         //T.Static
+    case_parseAttribute:
+      s = parseAttributeStatement();
+      return s;
+    case T.Identifier:
+      if (peekNext() == T.Colon)
+      {
+        auto ident = token;
+        nT(); // Skip Identifier
+        nT(); // Skip :
+        s = new LabeledStatement(ident, parseNoScopeOrEmptyStatement());
+        break;
+      }
+      goto case T.Dot;
+    case T.Dot, T.Typeof:
+      bool success;
+      d = try_(parseDeclaration(), success);
+      if (success)
+        goto case_DeclarationStatement; // Declaration
+      else
+        goto default; // Expression
+    // BasicType
+    case T.Char,   T.Wchar,   T.Dchar,  T.Bool,
+         T.Byte,   T.Ubyte,   T.Short,  T.Ushort,
+         T.Int,    T.Uint,    T.Long,   T.Ulong,
+         T.Float,  T.Double,  T.Real,
+         T.Ifloat, T.Idouble, T.Ireal,
+         T.Cfloat, T.Cdouble, T.Creal, T.Void:
+    case_parseDeclaration:
+      d = parseDeclaration();
+      goto case_DeclarationStatement;
+    case T.If:
+      s = parseIfStatement();
+      break;
+    case T.While:
+      s = parseWhileStatement();
+      break;
+    case T.Do:
+      s = parseDoWhileStatement();
+      break;
+    case T.For:
+      s = parseForStatement();
+      break;
+    case T.Foreach, T.Foreach_reverse:
+      s = parseForeachStatement();
+      break;
+    case T.Switch:
+      s = parseSwitchStatement();
+      break;
+    case T.Case:
+      s = parseCaseStatement();
+      break;
+    case T.Default:
+      s = parseDefaultStatement();
+      break;
+    case T.Continue:
+      s = parseContinueStatement();
+      break;
+    case T.Break:
+      s = parseBreakStatement();
+      break;
+    case T.Return:
+      s = parseReturnStatement();
+      break;
+    case T.Goto:
+      s = parseGotoStatement();
+      break;
+    case T.With:
+      s = parseWithStatement();
+      break;
+    case T.Synchronized:
+      s = parseSynchronizedStatement();
+      break;
+    case T.Try:
+      s = parseTryStatement();
+      break;
+    case T.Throw:
+      s = parseThrowStatement();
+      break;
+    case T.Scope:
+      if (peekNext() != T.LParen)
+        goto case_parseAttribute;
+      s = parseScopeGuardStatement();
+      break;
+    case T.Volatile:
+      s = parseVolatileStatement();
+      break;
+    case T.Asm:
+      s = parseAsmStatement();
+      break;
+    case T.Pragma:
+      s = parsePragmaStatement();
+      break;
+    case T.Mixin:
+      if (peekNext() == T.LParen)
+        goto default; // Parse as expression.
+      s = parseMixin!(MixinStatement)();
+      break;
+    case T.Static:
+      switch (peekNext())
+      {
+      case T.If:
+        s = parseStaticIfStatement();
+        break;
+      case T.Assert:
+        s = parseStaticAssertStatement();
+        break;
+      default:
+        goto case_parseAttribute;
+      }
+      break;
+    case T.Debug:
+      s = parseDebugStatement();
+      break;
+    case T.Version:
+      s = parseVersionStatement();
+      break;
+    // DeclDef
+    case T.Alias, T.Typedef:
+      d = parseDeclarationDefinition();
+      goto case_DeclarationStatement;
+    case T.Enum:
+      d = parseEnumDeclaration();
+      goto case_DeclarationStatement;
+    case T.Class:
+      d = parseClassDeclaration();
+      goto case_DeclarationStatement;
+    case T.Interface:
+      d = parseInterfaceDeclaration();
+      goto case_DeclarationStatement;
+    case T.Struct, T.Union:
+      d = parseAggregateDeclaration();
+      goto case_DeclarationStatement;
+    case_DeclarationStatement:
+      set(d, begin);
+      s = new DeclarationStatement(d);
+      break;
+    case T.LBrace:
+      s = parseScopeStatement();
+      break;
+    case T.Semicolon:
+      nT();
+      s = new EmptyStatement();
+      break;
+    default:
+      bool success;
+      auto expression = try_(parseExpression(), success);
+// writefln("parseExpression()=", failed?"failed":"success");
+      if (success)
+      {
+        require(T.Semicolon);
+        s = new ExpressionStatement(expression);
+      }
+      else
+      {
+        error(MID.ExpectedButFound, "Statement", token.srcText);
+        s = new IllegalStatement(token);
+        nT();
+      }
+    }
+    assert(s !is null);
+//     writef("§%s§", s.classinfo.name);
+    set(s, begin);
+    return s;
+  }
+
+  /+
+    ScopeStatement:
+        NoScopeStatement
+  +/
+  Statement parseScopeStatement()
+  {
+    return new ScopeStatement(parseNoScopeStatement());
+  }
+
+  /+
+    NoScopeStatement:
+        NonEmptyStatement
+        BlockStatement
+    BlockStatement:
+        { }
+        { StatementList }
+  +/
+  Statement parseNoScopeStatement()
+  {
+    Statement s;
+    if (token.type == T.LBrace)
+    {
+      nT();
+      auto ss = new Statements();
+      while (token.type != T.RBrace && token.type != T.EOF)
+        ss ~= parseStatement();
+      require(T.RBrace);
+      s = ss;
+    }
+    else if (token.type == T.Semicolon)
+    {
+      error(MID.ExpectedButFound, "non-empty statement", ";");
+      s = new EmptyStatement();
+      nT();
+    }
+    else
+      s = parseStatement();
+    return s;
+  }
+
+  /+
+    NoScopeOrEmptyStatement:
+        ;
+        NoScopeStatement
+  +/
+  Statement parseNoScopeOrEmptyStatement()
+  {
+    if (token.type == T.Semicolon)
+    {
+      nT();
+      return new EmptyStatement();
+    }
+    else
+      return parseNoScopeStatement();
+  }
+
+  Statement parseAttributeStatement()
+  {
+    StorageClass stc, tmp;
+
+    void addStorageClass()
+    {
+      if (stc & tmp)
+      {
+        error(MID.RedundantStorageClass, token.srcText);
+      }
+      else
+        stc |= tmp;
+    }
+
+    Statement parse()
+    {
+      auto begin = token;
+      Statement s;
+      switch (token.type)
+      {
+      case T.Extern:
+        tmp = StorageClass.Extern;
+        addStorageClass();
+        nT();
+        Linkage linkage;
+        if (token.type == T.LParen)
+        {
+          nT();
+          auto ident = requireId();
+          switch (ident ? ident.identifier : null)
+          {
+          case "C":
+            if (token.type == T.PlusPlus)
+            {
+              nT();
+              linkage = Linkage.Cpp;
+              break;
+            }
+            linkage = Linkage.C;
+            break;
+          case "D":
+            linkage = Linkage.D;
+            break;
+          case "Windows":
+            linkage = Linkage.Windows;
+            break;
+          case "Pascal":
+            linkage = Linkage.Pascal;
+            break;
+          case "System":
+            linkage = Linkage.System;
+            break;
+          default:
+            // TODO: issue error msg. Unrecognized LinkageType.
+          }
+          require(T.RParen);
+        }
+        s = new ExternStatement(linkage, parse());
+        break;
+      case T.Static:
+        tmp = StorageClass.Static;
+        goto Lcommon;
+      case T.Final:
+        tmp = StorageClass.Final;
+        goto Lcommon;
+      case T.Const:
+      version(D2)
+      {
+        if (peekNext() == T.LParen)
+          goto case_Declaration;
+      }
+        tmp = StorageClass.Const;
+        goto Lcommon;
+      version(D2)
+      {
+      case T.Invariant: // D 2.0
+        if (peekNext() == T.LParen)
+          goto case_Declaration;
+        tmp = StorageClass.Invariant;
+        goto Lcommon;
+      }
+      case T.Auto:
+        tmp = StorageClass.Auto;
+        goto Lcommon;
+      case T.Scope:
+        tmp = StorageClass.Scope;
+        goto Lcommon;
+      Lcommon:
+        addStorageClass();
+        auto tok = token.type;
+        nT();
+        s = new AttributeStatement(tok, parse());
+        break;
+      // TODO: allow "scope class", "abstract scope class" in function bodies?
+      //case T.Class:
+      default:
+      case_Declaration:
+        s = new DeclarationStatement(parseDeclaration(stc));
+      }
+      set(s, begin);
+      return s;
+    }
+    return parse();
+  }
+
+  Statement parseIfStatement()
+  {
+    assert(token.type == T.If);
+    nT();
+
+    Statement variable;
+    Expression condition;
+    Statement ifBody, elseBody;
+
+    require(T.LParen);
+
+    Token* ident;
+    // auto Identifier = Expression
+    if (token.type == T.Auto)
+    {
+      auto a = new AttributeStatement(token.type, null);
+      nT();
+      ident = requireId();
+      require(T.Assign);
+      auto init = parseExpression();
+      a.statement = new DeclarationStatement(new VariableDeclaration(null, [ident], [init]));
+      variable = a;
+    }
+    else
+    {
+      // Declarator = Expression
+      Type parseDeclaratorAssign()
+      {
+        auto type = parseDeclarator(ident);
+        require(T.Assign);
+        return type;
+      }
+      bool success;
+      auto type = try_(parseDeclaratorAssign(), success);
+      if (success)
+      {
+        auto init = parseExpression();
+        variable = new DeclarationStatement(new VariableDeclaration(type, [ident], [init]));
+      }
+      else
+        condition = parseExpression();
+    }
+    require(T.RParen);
+    ifBody = parseScopeStatement();
+    if (token.type == T.Else)
+    {
+      nT();
+      elseBody = parseScopeStatement();
+    }
+    return new IfStatement(variable, condition, ifBody, elseBody);
+  }
+
+  Statement parseWhileStatement()
+  {
+    assert(token.type == T.While);
+    nT();
+    require(T.LParen);
+    auto condition = parseExpression();
+    require(T.RParen);
+    return new WhileStatement(condition, parseScopeStatement());
+  }
+
+  Statement parseDoWhileStatement()
+  {
+    assert(token.type == T.Do);
+    nT();
+    auto doBody = parseScopeStatement();
+    require(T.While);
+    require(T.LParen);
+    auto condition = parseExpression();
+    require(T.RParen);
+    return new DoWhileStatement(condition, doBody);
+  }
+
+  Statement parseForStatement()
+  {
+    assert(token.type == T.For);
+    nT();
+    require(T.LParen);
+
+    Statement init, forBody;
+    Expression condition, increment;
+
+    if (token.type != T.Semicolon)
+      init = parseNoScopeStatement();
+    else
+      nT(); // Skip ;
+    if (token.type != T.Semicolon)
+      condition = parseExpression();
+    require(T.Semicolon);
+    if (token.type != T.RParen)
+      increment = parseExpression();
+    require(T.RParen);
+    forBody = parseScopeStatement();
+    return new ForStatement(init, condition, increment, forBody);
+  }
+
+  Statement parseForeachStatement()
+  {
+    assert(token.type == T.Foreach || token.type == T.Foreach_reverse);
+    TOK tok = token.type;
+    nT();
+
+    auto params = new Parameters;
+    Expression e; // Aggregate or LwrExpression
+
+    require(T.LParen);
+    while (1)
+    {
+      auto paramBegin = token;
+      Token* stcTok;
+      Type type;
+      Token* ident;
+
+      switch (token.type)
+      {
+      case T.Ref, T.Inout:
+        stcTok = token;
+        nT();
+        // fall through
+      case T.Identifier:
+        auto next = peekNext();
+        if (next == T.Comma || next == T.Semicolon || next == T.RParen)
+        {
+          ident = token;
+          nT();
+          break;
+        }
+        // fall through
+      default:
+        type = parseDeclarator(ident);
+      }
+
+      params ~= set(new Parameter(stcTok, type, ident, null), paramBegin);
+
+      if (token.type != T.Comma)
+        break;
+      nT();
+    }
+    require(T.Semicolon);
+    e = parseExpression();
+  version(D2)
+  { //Foreach (ForeachType; LwrExpression .. UprExpression ) ScopeStatement
+    if (token.type == T.Slice)
+    {
+      // if (params.length != 1)
+        // error(MID.XYZ); // TODO: issue error msg
+      nT();
+      auto upper = parseExpression();
+      require(T.RParen);
+      auto forBody = parseScopeStatement();
+      return new ForeachRangeStatement(tok, params, e, upper, forBody);
+    }
+  }
+    // Foreach (ForeachTypeList; Aggregate) ScopeStatement
+    require(T.RParen);
+    auto forBody = parseScopeStatement();
+    return new ForeachStatement(tok, params, e, forBody);
+  }
+
+  Statement parseSwitchStatement()
+  {
+    assert(token.type == T.Switch);
+    nT();
+
+    require(T.LParen);
+    auto condition = parseExpression();
+    require(T.RParen);
+    auto switchBody = parseScopeStatement();
+    return new SwitchStatement(condition, switchBody);
+  }
+
+  Statement parseCaseDefaultBody()
+  {
+    // This function is similar to parseNoScopeStatement()
+    auto s = new Statements();
+    while (token.type != T.Case &&
+            token.type != T.Default &&
+            token.type != T.RBrace &&
+            token.type != T.EOF)
+      s ~= parseStatement();
+    return new ScopeStatement(s);
+  }
+
+  Statement parseCaseStatement()
+  {
+    assert(token.type == T.Case);
+    // T.Case skipped in do-while.
+    Expression[] values;
+    do
+    {
+      nT();
+      values ~= parseAssignExpression();
+    } while (token.type == T.Comma)
+    require(T.Colon);
+
+    auto caseBody = parseCaseDefaultBody();
+    return new CaseStatement(values, caseBody);
+  }
+
+  Statement parseDefaultStatement()
+  {
+    assert(token.type == T.Default);
+    nT();
+    require(T.Colon);
+    return new DefaultStatement(parseCaseDefaultBody());
+  }
+
+  Statement parseContinueStatement()
+  {
+    assert(token.type == T.Continue);
+    nT();
+    Token* ident;
+    if (token.type == T.Identifier)
+    {
+      ident = token;
+      nT();
+    }
+    require(T.Semicolon);
+    return new ContinueStatement(ident);
+  }
+
+  Statement parseBreakStatement()
+  {
+    assert(token.type == T.Break);
+    nT();
+    Token* ident;
+    if (token.type == T.Identifier)
+    {
+      ident = token;
+      nT();
+    }
+    require(T.Semicolon);
+    return new BreakStatement(ident);
+  }
+
+  Statement parseReturnStatement()
+  {
+    assert(token.type == T.Return);
+    nT();
+    Expression expr;
+    if (token.type != T.Semicolon)
+      expr = parseExpression();
+    require(T.Semicolon);
+    return new ReturnStatement(expr);
+  }
+
+  Statement parseGotoStatement()
+  {
+    assert(token.type == T.Goto);
+    nT();
+    Token* ident;
+    Expression caseExpr;
+    switch (token.type)
+    {
+    case T.Case:
+      nT();
+      if (token.type == T.Semicolon)
+        break;
+      caseExpr = parseExpression();
+      break;
+    case T.Default:
+      nT();
+      break;
+    default:
+      ident = requireId();
+    }
+    require(T.Semicolon);
+    return new GotoStatement(ident, caseExpr);
+  }
+
+  Statement parseWithStatement()
+  {
+    assert(token.type == T.With);
+    nT();
+    require(T.LParen);
+    auto expr = parseExpression();
+    require(T.RParen);
+    return new WithStatement(expr, parseScopeStatement());
+  }
+
+  Statement parseSynchronizedStatement()
+  {
+    assert(token.type == T.Synchronized);
+    nT();
+    Expression expr;
+
+    if (token.type == T.LParen)
+    {
+      nT();
+      expr = parseExpression();
+      require(T.RParen);
+    }
+    return new SynchronizedStatement(expr, parseScopeStatement());
+  }
+
+  Statement parseTryStatement()
+  {
+    assert(token.type == T.Try);
+    nT();
+
+    auto tryBody = parseScopeStatement();
+    CatchBody[] catchBodies;
+    FinallyBody finBody;
+
+    while (token.type == T.Catch)
+    {
+      nT();
+      Parameter param;
+      if (token.type == T.LParen)
+      {
+        nT();
+        Token* ident;
+        auto type = parseDeclarator(ident);
+        param = new Parameter(null, type, ident, null);
+        require(T.RParen);
+      }
+      catchBodies ~= new CatchBody(param, parseNoScopeStatement());
+      if (param is null)
+        break; // This is a LastCatch
+    }
+
+    if (token.type == T.Finally)
+    {
+      nT();
+      finBody = new FinallyBody(parseNoScopeStatement());
+    }
+
+    if (catchBodies.length == 0 || finBody is null)
+    {
+      // TODO: issue error msg.
+    }
+
+    return new TryStatement(tryBody, catchBodies, finBody);
+  }
+
+  Statement parseThrowStatement()
+  {
+    assert(token.type == T.Throw);
+    nT();
+    auto expr = parseExpression();
+    require(T.Semicolon);
+    return new ThrowStatement(expr);
+  }
+
+  Statement parseScopeGuardStatement()
+  {
+    assert(token.type == T.Scope);
+    nT();
+    assert(token.type == T.LParen);
+    nT();
+
+    Token* condition = requireId();
+    if (condition)
+      switch (condition.identifier)
+      {
+      case "exit":
+      case "success":
+      case "failure":
+        break;
+      default:
+        // TODO: issue error msg.
+      }
+    require(T.RParen);
+    Statement scopeBody;
+    if (token.type == T.LBrace)
+      scopeBody = parseScopeStatement();
+    else
+      scopeBody = parseNoScopeStatement();
+    return new ScopeGuardStatement(condition, scopeBody);
+  }
+
+  Statement parseVolatileStatement()
+  {
+    assert(token.type == T.Volatile);
+    nT();
+    Statement volatileBody;
+    if (token.type == T.Semicolon)
+      nT();
+    else if (token.type == T.LBrace)
+      volatileBody = parseScopeStatement();
+    else
+      volatileBody = parseStatement();
+    return new VolatileStatement(volatileBody);
+  }
+
+  Statement parsePragmaStatement()
+  {
+    assert(token.type == T.Pragma);
+    nT();
+
+    Token* ident;
+    Expression[] args;
+    Statement pragmaBody;
+
+    require(T.LParen);
+    ident = requireId();
+
+    if (token.type == T.Comma)
+    {
+      // Parse at least one argument.
+      nT();
+      args ~= parseAssignExpression();
+    }
+
+    if (token.type == T.Comma)
+      args ~= parseArguments(T.RParen);
+    else
+      require(T.RParen);
+
+    pragmaBody = parseNoScopeOrEmptyStatement();
+
+    return new PragmaStatement(ident, args, pragmaBody);
+  }
+
+  Statement parseStaticIfStatement()
+  {
+    assert(token.type == T.Static);
+    nT();
+    assert(token.type == T.If);
+    nT();
+    Expression condition;
+    Statement ifBody, elseBody;
+
+    require(T.LParen);
+    condition = parseExpression();
+    require(T.RParen);
+    ifBody = parseNoScopeStatement();
+    if (token.type == T.Else)
+    {
+      nT();
+      elseBody = parseNoScopeStatement();
+    }
+    return new StaticIfStatement(condition, ifBody, elseBody);
+  }
+
+  Statement parseStaticAssertStatement()
+  {
+    assert(token.type == T.Static);
+    nT();
+    assert(token.type == T.Assert);
+    nT();
+    Expression condition, message;
+    require(T.LParen);
+    condition = parseAssignExpression();
+    if (token.type == T.Comma)
+    {
+      nT();
+      message = parseAssignExpression();
+    }
+    require(T.RParen);
+    require(T.Semicolon);
+    return new StaticAssertStatement(condition, message);
+  }
+
+  Statement parseDebugStatement()
+  {
+    assert(token.type == T.Debug);
+    nT(); // Skip debug keyword.
+
+    Token* cond; // debug ( Integer )
+                 // debug ( Identifier )
+    Statement debugBody, elseBody;
+
+    void parseIdentOrInt(ref Token* tok)
+    {
+      nT();
+      if (token.type == T.Int32 ||
+          token.type == T.Identifier)
+      {
+        tok = token;
+        nT();
+      }
+      else
+        expected(T.Identifier); // TODO: better error msg
+    }
+
+//     if (token.type == T.Assign)
+//     {
+//       parseIdentOrInt(identSpec, levelSpec);
+//       require(T.Semicolon);
+//     }
+//     else
+    {
+      // Condition:
+      //     Integer
+      //     Identifier
+
+      // ( Condition )
+      if (token.type == T.LParen)
+      {
+        parseIdentOrInt(cond);
+        require(T.RParen);
+      }
+
+      // debug Statement
+      // debug ( Condition ) Statement
+      debugBody = parseNoScopeStatement();
+
+      // else Statement
+      if (token.type == T.Else)
+      {
+        // debug without condition and else body makes no sense
+        //if (levelCond == -1 && identCond.length == 0)
+          // TODO: issue error msg
+        nT();
+        elseBody = parseNoScopeStatement();
+      }
+    }
+
+    return new DebugStatement(cond, debugBody, elseBody);
+  }
+
+  Statement parseVersionStatement()
+  {
+    assert(token.type == T.Version);
+
+    nT(); // Skip version keyword.
+
+    Token* cond; // version ( Integer )
+                 // version ( Identifier )
+    Statement versionBody, elseBody;
+
+    void parseIdentOrInt(ref Token* tok)
+    {
+      if (token.type == T.Int32 ||
+          token.type == T.Identifier)
+      {
+        tok = token;
+        nT();
+      }
+      else
+        expected(T.Identifier); // TODO: better error msg
+    }
+
+//     if (token.type == T.Assign)
+//     {
+//       parseIdentOrInt(identSpec, levelSpec);
+//       require(T.Semicolon);
+//     }
+//     else
+    {
+      // Condition:
+      //     Integer
+      //     Identifier
+
+      // ( Condition )
+      require(T.LParen);
+      parseIdentOrInt(cond);
+      require(T.RParen);
+
+      // version ( Condition ) Statement
+      versionBody = parseNoScopeStatement();
+
+      // else Statement
+      if (token.type == T.Else)
+      {
+        nT();
+        elseBody = parseNoScopeStatement();
+      }
+    }
+
+    return new VersionStatement(cond, versionBody, elseBody);
+  }
+
+  /+++++++++++++++++++++++++++++
+  + Assembler parsing methods  +
+  +++++++++++++++++++++++++++++/
+
+  Statement parseAsmStatement()
+  {
+    assert(token.type == T.Asm);
+    nT(); // Skip asm keyword.
+    require(T.LBrace);
+    auto ss = new Statements;
+    while (token.type != T.RBrace && token.type != T.EOF)
+      ss ~= parseAsmInstruction();
+    require(T.RBrace);
+    return new AsmStatement(ss);
+  }
+
+  Statement parseAsmInstruction()
+  {
+    auto begin = token;
+    Statement s;
+    switch (token.type)
+    {
+    case T.Identifier:
+      auto ident = token;
+      auto next = peekNext();
+      if (next == T.Colon)
+      {
+        // Identifier : AsmInstruction
+        nT(); // Skip Identifier
+        nT(); // Skip :
+        s = new LabeledStatement(ident, parseAsmInstruction());
+        break;
+      }
+
+      // Opcode ;
+      // Opcode Operands ;
+      // Opcode
+      //     Identifier
+      Expression[] es;
+      if (next != T.Semicolon)
+      {
+        while (1)
+        {
+          es ~= parseAsmExpression();
+          if (token.type != T.Comma)
+            break;
+          nT();
+        }
+      }
+      require(T.Semicolon);
+      s = new AsmInstruction(ident, es);
+      break;
+    case T.Semicolon:
+      s = new EmptyStatement();
+      nT();
+      break;
+    default:
+      error(MID.ExpectedButFound, "AsmStatement", token.srcText);
+      s = new IllegalAsmInstruction(token);
+      nT();
+    }
+    set(s, begin);
+    return s;
+  }
+
+  Expression parseAsmExpression()
+  {
+    auto begin = token;
+    auto e = parseOrOrExpression();
+    if (token.type == T.Question)
+    {
+      auto tok = token;
+      nT();
+      auto iftrue = parseAsmExpression();
+      require(T.Colon);
+      auto iffalse = parseAsmExpression();
+      e = new CondExpression(e, iftrue, iffalse, tok);
+      set(e, begin);
+    }
+    // TODO: create AsmExpression that contains e?
+    return e;
+  }
+
+  Expression parseAsmOrOrExpression()
+  {
+    auto begin = token;
+    alias parseAsmAndAndExpression parseNext;
+    auto e = parseNext();
+    while (token.type == T.OrLogical)
+    {
+      auto tok = token;
+      nT();
+      e = new OrOrExpression(e, parseNext(), tok);
+      set(e, begin);
+    }
+    return e;
+  }
+
+  Expression parseAsmAndAndExpression()
+  {
+    auto begin = token;
+    alias parseAsmOrExpression parseNext;
+    auto e = parseNext();
+    while (token.type == T.AndLogical)
+    {
+      auto tok = token;
+      nT();
+      e = new AndAndExpression(e, parseNext(), tok);
+      set(e, begin);
+    }
+    return e;
+  }
+
+  Expression parseAsmOrExpression()
+  {
+    auto begin = token;
+    alias parseAsmXorExpression parseNext;
+    auto e = parseNext();
+    while (token.type == T.OrBinary)
+    {
+      auto tok = token;
+      nT();
+      e = new OrExpression(e, parseNext(), tok);
+      set(e, begin);
+    }
+    return e;
+  }
+
+  Expression parseAsmXorExpression()
+  {
+    alias parseAsmAndExpression parseNext;
+    auto begin = token;
+    auto e = parseNext();
+    while (token.type == T.Xor)
+    {
+      auto tok = token;
+      nT();
+      e = new XorExpression(e, parseNext(), tok);
+      set(e, begin);
+    }
+    return e;
+  }
+
+  Expression parseAsmAndExpression()
+  {
+    alias parseAsmCmpExpression parseNext;
+    auto begin = token;
+    auto e = parseNext();
+    while (token.type == T.AndBinary)
+    {
+      auto tok = token;
+      nT();
+      e = new AndExpression(e, parseNext(), tok);
+      set(e, begin);
+    }
+    return e;
+  }
+
+  Expression parseAsmCmpExpression()
+  {
+    alias parseAsmShiftExpression parseNext;
+    auto begin = token;
+    auto e = parseNext();
+
+    auto operator = token;
+    switch (operator.type)
+    {
+    case T.Equal, T.NotEqual:
+      nT();
+      e = new EqualExpression(e, parseNext(), operator);
+      break;
+    case T.LessEqual, T.Less, T.GreaterEqual, T.Greater:
+      nT();
+      e = new RelExpression(e, parseNext(), operator);
+      break;
+    default:
+      return e;
+    }
+    set(e, begin);
+    return e;
+  }
+
+  Expression parseAsmShiftExpression()
+  {
+    alias parseAsmAddExpression parseNext;
+    auto begin = token;
+    auto e = parseNext();
+    while (1)
+    {
+      auto operator = token;
+      switch (operator.type)
+      {
+      case T.LShift:  nT(); e = new LShiftExpression(e, parseNext(), operator); break;
+      case T.RShift:  nT(); e = new RShiftExpression(e, parseNext(), operator); break;
+      case T.URShift: nT(); e = new URShiftExpression(e, parseNext(), operator); break;
+      default:
+        return e;
+      }
+      set(e, begin);
+    }
+    assert(0);
+  }
+
+  Expression parseAsmAddExpression()
+  {
+    alias parseAsmMulExpression parseNext;
+    auto begin = token;
+    auto e = parseNext();
+    while (1)
+    {
+      auto operator = token;
+      switch (operator.type)
+      {
+      case T.Plus:  nT(); e = new PlusExpression(e, parseNext(), operator); break;
+      case T.Minus: nT(); e = new MinusExpression(e, parseNext(), operator); break;
+      // Not allowed in asm
+      //case T.Tilde: nT(); e = new CatExpression(e, parseNext(), operator); break;
+      default:
+        return e;
+      }
+      set(e, begin);
+    }
+    assert(0);
+  }
+
+  Expression parseAsmMulExpression()
+  {
+    alias parseAsmPostExpression parseNext;
+    auto begin = token;
+    auto e = parseNext();
+    while (1)
+    {
+      auto operator = token;
+      switch (operator.type)
+      {
+      case T.Mul: nT(); e = new MulExpression(e, parseNext(), operator); break;
+      case T.Div: nT(); e = new DivExpression(e, parseNext(), operator); break;
+      case T.Mod: nT(); e = new ModExpression(e, parseNext(), operator); break;
+      default:
+        return e;
+      }
+      set(e, begin);
+    }
+    assert(0);
+  }
+
+  Expression parseAsmPostExpression()
+  {
+    auto begin = token;
+    auto e = parseAsmUnaryExpression();
+    while (token.type == T.RBracket)
+    {
+      nT();
+      e = parseAsmExpression();
+      e = new AsmPostBracketExpression(e);
+      require(T.RBracket);
+      set(e, begin);
+    }
+    return e;
+  }
+
+  Expression parseAsmUnaryExpression()
+  {
+    auto begin = token;
+    Expression e;
+    switch (token.type)
+    {
+    case T.Identifier:
+      switch (token.identifier)
+      {
+      case "near", "far",   "byte",  "short",  "int",
+           "word", "dword", "float", "double", "real":
+        nT();
+        if (token.type == T.Identifier && token.identifier == "ptr")
+          nT();
+        else
+          error(MID.ExpectedButFound, "ptr", token.srcText);
+        e = new AsmTypeExpression(parseAsmUnaryExpression());
+        break;
+      case "offset":
+        nT();
+        e = new AsmOffsetExpression(parseAsmUnaryExpression());
+        break;
+      case "seg":
+        nT();
+        e = new AsmSegExpression(parseAsmUnaryExpression());
+        break;
+      default:
+      }
+      goto default;
+    case T.Minus:
+    case T.Plus:
+      nT();
+      e = new SignExpression(parseAsmUnaryExpression());
+      break;
+    case T.Not:
+      nT();
+      e = new NotExpression(parseAsmUnaryExpression());
+      break;
+    case T.Tilde:
+      nT();
+      e = new CompExpression(parseAsmUnaryExpression());
+    default:
+      e = parseAsmPrimaryExpression();
+      return e;
+    }
+    set(e, begin);
+    return e;
+  }
+
+  Expression parseAsmPrimaryExpression()
+  {
+    auto begin = token;
+    Expression e;
+    switch (token.type)
+    {
+    case T.Int32, T.Int64, T.Uint32, T.Uint64:
+      e = new IntNumberExpression(token.type, token.ulong_);
+      nT();
+      break;
+    case T.Float32, T.Float64, T.Float80,
+         T.Imaginary32, T.Imaginary64, T.Imaginary80:
+      e = new RealNumberExpression(token.type, token.real_);
+      nT();
+      break;
+    case T.Dollar:
+      e = new DollarExpression();
+      nT();
+      break;
+    case T.LBracket:
+      // [ AsmExpression ]
+      nT();
+      e = parseAsmExpression();
+      require(T.RBracket);
+      e = new AsmBracketExpression(e);
+      break;
+    case T.Identifier:
+      switch (token.identifier)
+      {
+      // __LOCAL_SIZE
+      case "__LOCAL_SIZE":
+        e = new AsmLocalSizeExpression();
+        nT();
+        break;
+      // Register
+      case "ST":
+        auto register = token;
+        nT();
+        // (1) - (7)
+        Token* number;
+        if (token.type == T.LParen)
+        {
+          nT();
+          if (token.type == T.Int32)
+          {
+            number = token;
+            nT();
+          }
+          else
+            expected(T.Int32);
+          require(T.RParen);
+        }
+        e = new AsmRegisterExpression(register, number);
+        break;
+      case "AL", "AH", "AX", "EAX",
+           "BL", "BH", "BX", "EBX",
+           "CL", "CH", "CX", "ECX",
+           "DL", "DH", "DX", "EDX",
+           "BP", "EBP",
+           "SP", "ESP",
+           "DI", "EDI",
+           "SI", "ESI",
+           "ES", "CS", "SS", "DS", "GS", "FS",
+           "CR0", "CR2", "CR3", "CR4",
+           "DR0", "DR1", "DR2", "DR3", "DR6", "DR7",
+           "TR3", "TR4", "TR5", "TR6", "TR7",
+           "MM0", "MM1", "MM2", "MM3", "MM4", "MM5", "MM6", "MM7",
+           "XMM0", "XMM1", "XMM2", "XMM3", "XMM4", "XMM5", "XMM6", "XMM7":
+          e = new AsmRegisterExpression(token);
+          nT();
+        break;
+      default:
+        // DotIdentifier
+        auto begin2 = token;
+        Expression[] identList;
+        goto LenterLoop;
+        while (token.type == T.Dot)
+        {
+          nT();
+          begin2 = token;
+          auto ident = requireId();
+        LenterLoop:
+          e = new IdentifierExpression(token);
+          nT();
+          set(e, begin2);
+          identList ~= e;
+        }
+        e = new DotListExpression(identList);
+      }
+      break;
+    default:
+      error(MID.ExpectedButFound, "Expression", token.srcText);
+      e = new EmptyExpression();
+      break;
+    }
+    set(e, begin);
+    return e;
+  }
+
+  /+++++++++++++++++++++++++++++
+  + Expression parsing methods +
+  +++++++++++++++++++++++++++++/
+
+  Expression parseExpression()
+  {
+    auto begin = token;
+    auto e = parseAssignExpression();
+    while (token.type == T.Comma)
+    {
+      auto comma = token;
+      nT();
+      e = new CommaExpression(e, parseAssignExpression(), comma);
+      set(e, begin);
+    }
+// if (!trying)
+// writef("§%s§", e.classinfo.name);
+    return e;
+  }
+
+  Expression parseAssignExpression()
+  {
+    auto begin = token;
+    auto e = parseCondExpression();
+    while (1)
+    {
+      switch (token.type)
+      {
+      case T.Assign:
+        nT(); e = new AssignExpression(e, parseAssignExpression());
+        break;
+      case T.LShiftAssign:
+        nT(); e = new LShiftAssignExpression(e, parseAssignExpression());
+        break;
+      case T.RShiftAssign:
+        nT(); e = new RShiftAssignExpression(e, parseAssignExpression());
+        break;
+      case T.URShiftAssign:
+        nT(); e = new URShiftAssignExpression(e, parseAssignExpression());
+        break;
+      case T.OrAssign:
+        nT(); e = new OrAssignExpression(e, parseAssignExpression());
+        break;
+      case T.AndAssign:
+        nT(); e = new AndAssignExpression(e, parseAssignExpression());
+        break;
+      case T.PlusAssign:
+        nT(); e = new PlusAssignExpression(e, parseAssignExpression());
+        break;
+      case T.MinusAssign:
+        nT(); e = new MinusAssignExpression(e, parseAssignExpression());
+        break;
+      case T.DivAssign:
+        nT(); e = new DivAssignExpression(e, parseAssignExpression());
+        break;
+      case T.MulAssign:
+        nT(); e = new MulAssignExpression(e, parseAssignExpression());
+        break;
+      case T.ModAssign:
+        nT(); e = new ModAssignExpression(e, parseAssignExpression());
+        break;
+      case T.XorAssign:
+        nT(); e = new XorAssignExpression(e, parseAssignExpression());
+        break;
+      case T.CatAssign:
+        nT(); e = new CatAssignExpression(e, parseAssignExpression());
+        break;
+      default:
+        return e;
+      }
+      set(e, begin);
+    }
+    return e;
+  }
+
+  Expression parseCondExpression()
+  {
+    auto begin = token;
+    auto e = parseOrOrExpression();
+    if (token.type == T.Question)
+    {
+      auto tok = token;
+      nT();
+      auto iftrue = parseExpression();
+      require(T.Colon);
+      auto iffalse = parseCondExpression();
+      e = new CondExpression(e, iftrue, iffalse, tok);
+      set(e, begin);
+    }
+    return e;
+  }
+
+  Expression parseOrOrExpression()
+  {
+    auto begin = token;
+    alias parseAndAndExpression parseNext;
+    auto e = parseNext();
+    while (token.type == T.OrLogical)
+    {
+      auto tok = token;
+      nT();
+      e = new OrOrExpression(e, parseNext(), tok);
+      set(e, begin);
+    }
+    return e;
+  }
+
+  Expression parseAndAndExpression()
+  {
+    auto begin = token;
+    alias parseOrExpression parseNext;
+    auto e = parseNext();
+    while (token.type == T.AndLogical)
+    {
+      auto tok = token;
+      nT();
+      e = new AndAndExpression(e, parseNext(), tok);
+      set(e, begin);
+    }
+    return e;
+  }
+
+  Expression parseOrExpression()
+  {
+    auto begin = token;
+    alias parseXorExpression parseNext;
+    auto e = parseNext();
+    while (token.type == T.OrBinary)
+    {
+      auto tok = token;
+      nT();
+      e = new OrExpression(e, parseNext(), tok);
+      set(e, begin);
+    }
+    return e;
+  }
+
+  Expression parseXorExpression()
+  {
+    auto begin = token;
+    alias parseAndExpression parseNext;
+    auto e = parseNext();
+    while (token.type == T.Xor)
+    {
+      auto tok = token;
+      nT();
+      e = new XorExpression(e, parseNext(), tok);
+      set(e, begin);
+    }
+    return e;
+  }
+
+  Expression parseAndExpression()
+  {
+    auto begin = token;
+    alias parseCmpExpression parseNext;
+    auto e = parseNext();
+    while (token.type == T.AndBinary)
+    {
+      auto tok = token;
+      nT();
+      e = new AndExpression(e, parseNext(), tok);
+      set(e, begin);
+    }
+    return e;
+  }
+
+  Expression parseCmpExpression()
+  {
+    auto begin = token;
+    auto e = parseShiftExpression();
+
+    auto operator = token;
+    switch (operator.type)
+    {
+    case T.Equal, T.NotEqual:
+      nT();
+      e = new EqualExpression(e, parseShiftExpression(), operator);
+      break;
+    case T.Not:
+      if (peekNext() != T.Is)
+        break;
+      nT();
+      // fall through
+    case T.Is:
+      nT();
+      e = new IdentityExpression(e, parseShiftExpression(), operator);
+      break;
+    case T.LessEqual, T.Less, T.GreaterEqual, T.Greater,
+         T.Unordered, T.UorE, T.UorG, T.UorGorE,
+         T.UorL, T.UorLorE, T.LorEorG, T.LorG:
+      nT();
+      e = new RelExpression(e, parseShiftExpression(), operator);
+      break;
+    case T.In:
+      nT();
+      e = new InExpression(e, parseShiftExpression(), operator);
+      break;
+    default:
+      return e;
+    }
+    set(e, begin);
+    return e;
+  }
+
+  Expression parseShiftExpression()
+  {
+    auto begin = token;
+    auto e = parseAddExpression();
+    while (1)
+    {
+      auto operator = token;
+      switch (operator.type)
+      {
+      case T.LShift:  nT(); e = new LShiftExpression(e, parseAddExpression(), operator); break;
+      case T.RShift:  nT(); e = new RShiftExpression(e, parseAddExpression(), operator); break;
+      case T.URShift: nT(); e = new URShiftExpression(e, parseAddExpression(), operator); break;
+      default:
+        return e;
+      }
+      set(e, begin);
+    }
+    assert(0);
+  }
+
+  Expression parseAddExpression()
+  {
+    auto begin = token;
+    auto e = parseMulExpression();
+    while (1)
+    {
+      auto operator = token;
+      switch (operator.type)
+      {
+      case T.Plus:  nT(); e = new PlusExpression(e, parseMulExpression(), operator); break;
+      case T.Minus: nT(); e = new MinusExpression(e, parseMulExpression(), operator); break;
+      case T.Tilde: nT(); e = new CatExpression(e, parseMulExpression(), operator); break;
+      default:
+        return e;
+      }
+      set(e, begin);
+    }
+    assert(0);
+  }
+
+  Expression parseMulExpression()
+  {
+    auto begin = token;
+    auto e = parseUnaryExpression();
+    while (1)
+    {
+      auto operator = token;
+      switch (operator.type)
+      {
+      case T.Mul: nT(); e = new MulExpression(e, parseUnaryExpression(), operator); break;
+      case T.Div: nT(); e = new DivExpression(e, parseUnaryExpression(), operator); break;
+      case T.Mod: nT(); e = new ModExpression(e, parseUnaryExpression(), operator); break;
+      default:
+        return e;
+      }
+      set(e, begin);
+    }
+    assert(0);
+  }
+
+  Expression parseUnaryExpression()
+  {
+    auto begin = token;
+    Expression e;
+    switch (token.type)
+    {
+    case T.AndBinary:
+      nT();
+      e = new AddressExpression(parseUnaryExpression());
+      break;
+    case T.PlusPlus:
+      nT();
+      e = new PreIncrExpression(parseUnaryExpression());
+      break;
+    case T.MinusMinus:
+      nT();
+      e = new PreDecrExpression(parseUnaryExpression());
+      break;
+    case T.Mul:
+      nT();
+      e = new DerefExpression(parseUnaryExpression());
+      break;
+    case T.Minus:
+    case T.Plus:
+      nT();
+      e = new SignExpression(parseUnaryExpression());
+      break;
+    case T.Not:
+      nT();
+      e = new NotExpression(parseUnaryExpression());
+      break;
+    case T.Tilde:
+      nT();
+      e = new CompExpression(parseUnaryExpression());
+      break;
+    case T.New:
+      e = parseNewExpression();
+      return e;
+    case T.Delete:
+      nT();
+      e = new DeleteExpression(parseUnaryExpression());
+      break;
+    case T.Cast:
+      requireNext(T.LParen);
+      Type type;
+      switch (token.type)
+      {
+      version(D2)
+      {
+      auto begin2 = token;
+      case T.Const:
+        type = new ConstType(null);
+        goto case_break;
+      case T.Invariant:
+        type = new InvariantType(null);
+      case_break:
+        nT();
+        set(type, begin2);
+        break;
+      }
+      default:
+       type = parseType();
+      }
+      require(T.RParen);
+      e = new CastExpression(parseUnaryExpression(), type);
+      break;
+    case T.LParen:
+      // ( Type ) . Identifier
+      Type parseType_()
+      {
+        nT();
+        auto type = parseType();
+        require(T.RParen);
+        require(T.Dot);
+        return type;
+      }
+      bool success;
+      auto type = try_(parseType_(), success);
+      if (success)
+      {
+        auto ident = requireId();
+        e = new TypeDotIdExpression(type, ident);
+        break;
+      }
+      goto default;
+    default:
+      e = parsePostExpression(parsePrimaryExpression());
+      return e;
+    }
+    assert(e !is null);
+    set(e, begin);
+    return e;
+  }
+
+  Expression parsePostExpression(Expression e)
+  {
+    typeof(token) begin;
+    while (1)
+    {
+      begin = token;
+      switch (token.type)
+      {
+/*
+// Commented out because parseDotListExpression() handles this.
+      case T.Dot:
+        nT();
+        if (token.type == T.Identifier)
+        {
+          string ident = token.identifier;
+          nT();
+          if (token.type == T.Not && peekNext() == T.LParen) // Identifier !( TemplateArguments )
+          {
+            nT(); // Skip !.
+            e = new DotTemplateInstanceExpression(e, ident, parseTemplateArguments());
+          }
+          else
+          {
+            e = new DotIdExpression(e, ident);
+            nT();
+          }
+        }
+        else if (token.type == T.New)
+          e = parseNewExpression(e);
+        else
+          expected(T.Identifier);
+        continue;
+*/
+      case T.Dot:
+        e = new PostDotListExpression(e, parseDotListExpression());
+        goto Lset;
+      case T.PlusPlus:
+        e = new PostIncrExpression(e);
+        break;
+      case T.MinusMinus:
+        e = new PostDecrExpression(e);
+        break;
+      case T.LParen:
+        e = new CallExpression(e, parseArguments(T.RParen));
+        goto Lset;
+      case T.LBracket:
+        // parse Slice- and IndexExpression
+        nT();
+        if (token.type == T.RBracket)
+        {
+          e = new SliceExpression(e, null, null);
+          break;
+        }
+
+        Expression[] es = [parseAssignExpression()];
+
+        if (token.type == T.Slice)
+        {
+          nT();
+          e = new SliceExpression(e, es[0], parseAssignExpression());
+          require(T.RBracket);
+          goto Lset;
+        }
+        else if (token.type == T.Comma)
+        {
+           es ~= parseArguments(T.RBracket);
+        }
+        else
+          require(T.RBracket);
+
+        e = new IndexExpression(e, es);
+        goto Lset;
+      default:
+        return e;
+      }
+      nT();
+    Lset:
+      set(e, begin);
+    }
+    assert(0);
+  }
+
+  Expression parsePrimaryExpression()
+  {
+    auto begin = token;
+    Expression e;
+    switch (token.type)
+    {
+/*
+// Commented out because parseDotListExpression() handles this.
+    case T.Identifier:
+      string ident = token.identifier;
+      nT();
+      if (token.type == T.Not && peekNext() == T.LParen) // Identifier !( TemplateArguments )
+      {
+        nT(); // Skip !.
+        e = new TemplateInstanceExpression(ident, parseTemplateArguments());
+      }
+      else
+        e = new IdentifierExpression(ident);
+      break;
+    case T.Dot:
+      nT();
+      e = new IdentifierExpression(".");
+      break;
+*/
+    case T.Identifier, T.Dot, T.Typeof:
+      e = parseDotListExpression();
+      break;
+    case T.This:
+      nT();
+      e = new ThisExpression();
+      break;
+    case T.Super:
+      nT();
+      e = new SuperExpression();
+      break;
+    case T.Null:
+      nT();
+      e = new NullExpression();
+      break;
+    case T.True, T.False:
+      nT();
+      e = new BoolExpression();
+      break;
+    case T.Dollar:
+      nT();
+      e = new DollarExpression();
+      break;
+    case T.Int32, T.Int64, T.Uint32, T.Uint64:
+      e = new IntNumberExpression(token.type, token.ulong_);
+      nT();
+      break;
+    case T.Float32, T.Float64, T.Float80,
+         T.Imaginary32, T.Imaginary64, T.Imaginary80:
+      e = new RealNumberExpression(token.type, token.real_);
+      nT();
+      break;
+    case T.CharLiteral, T.WCharLiteral, T.DCharLiteral:
+      nT();
+      e = new CharLiteralExpression();
+      break;
+    case T.String:
+      Token*[] stringLiterals;
+      do
+      {
+        stringLiterals ~= token;
+        nT();
+      } while (token.type == T.String)
+      e = new StringLiteralsExpression(stringLiterals);
+      break;
+    case T.LBracket:
+      Expression[] values;
+
+      nT();
+      if (token.type != T.RBracket)
+      {
+        e = parseAssignExpression();
+        if (token.type == T.Colon)
+          goto LparseAssocArray;
+        else if (token.type == T.Comma)
+          values = [e] ~ parseArguments(T.RBracket);
+        else
+          require(T.RBracket);
+      }
+      else
+        nT();
+
+      e = new ArrayLiteralExpression(values);
+      break;
+
+    LparseAssocArray:
+      Expression[] keys;
+
+      keys ~= e;
+      nT(); // Skip colon.
+      goto LenterLoop;
+
+      while (1)
+      {
+        keys ~= parseAssignExpression();
+        require(T.Colon);
+      LenterLoop:
+        values ~= parseAssignExpression();
+        if (token.type != T.Comma)
+          break;
+        nT();
+      }
+      require(T.RBracket);
+      e = new AssocArrayLiteralExpression(keys, values);
+      break;
+    case T.LBrace:
+      // DelegateLiteral := { Statements }
+      auto funcBody = parseFunctionBody();
+      e = new FunctionLiteralExpression(funcBody);
+      break;
+    case T.Function, T.Delegate:
+      // FunctionLiteral := (function|delegate) Type? '(' ArgumentList ')' '{' Statements '}'
+      nT(); // Skip function|delegate token.
+      Type returnType;
+      Parameters parameters;
+      if (token.type != T.LBrace)
+      {
+        if (token.type != T.LParen) // Optional return type
+          returnType = parseType();
+        parameters = parseParameterList();
+      }
+      auto funcBody = parseFunctionBody();
+      e = new FunctionLiteralExpression(returnType, parameters, funcBody);
+      break;
+    case T.Assert:
+      Expression msg;
+      requireNext(T.LParen);
+      e = parseAssignExpression();
+      if (token.type == T.Comma)
+      {
+        nT();
+        msg = parseAssignExpression();
+      }
+      require(T.RParen);
+      e = new AssertExpression(e, msg);
+      break;
+    case T.Mixin:
+      requireNext(T.LParen);
+      e = parseAssignExpression();
+      require(T.RParen);
+      e = new MixinExpression(e);
+      break;
+    case T.Import:
+      requireNext(T.LParen);
+      e = parseAssignExpression();
+      require(T.RParen);
+      e = new ImportExpression(e);
+      break;
+    case T.Typeid:
+      requireNext(T.LParen);
+      auto type = parseType();
+      require(T.RParen);
+      e = new TypeidExpression(type);
+      break;
+/*
+// Commented out because parseDotListExpression() handles this.
+    case T.Typeof:
+      requireNext(T.LParen);
+      auto type = new TypeofType(parseExpression());
+      require(T.RParen);
+      if (token.type == T.Dot)
+      { // typeof ( Expression ) . Identifier
+        nT();
+        string ident = requireIdentifier;
+        e = new TypeDotIdExpression(type, ident);
+      }
+      else // typeof ( Expression )
+        e = new TypeofExpression(type);
+      break;
+*/
+    case T.Is:
+      requireNext(T.LParen);
+
+      Type type, specType;
+      Token* ident; // optional Identifier
+      Token* opTok, specTok;
+
+      type = parseDeclarator(ident, true);
+
+      switch (token.type)
+      {
+      case T.Colon, T.Equal:
+        opTok = token;
+        nT();
+        switch (token.type)
+        {
+        case T.Typedef,
+             T.Struct,
+             T.Union,
+             T.Class,
+             T.Interface,
+             T.Enum,
+             T.Function,
+             T.Delegate,
+             T.Super,
+             T.Return:
+          specTok = token;
+          nT();
+          break;
+        default:
+          specType = parseType();
+        }
+      default:
+      }
+      require(T.RParen);
+      e = new IsExpression(type, ident, opTok, specTok, specType);
+      break;
+    case T.LParen:
+      if (tokenAfterParenIs(T.LBrace))
+      {
+        auto parameters = parseParameterList();
+        // ( ParameterList ) FunctionBody
+        auto funcBody = parseFunctionBody();
+        e = new FunctionLiteralExpression(null, parameters, funcBody);
+      }
+      else
+      {
+        // ( Expression )
+        nT();
+        e = parseExpression();
+        require(T.RParen);
+        // TODO: create ParenExpression?
+      }
+      break;
+    // BasicType . Identifier
+    case T.Char,   T.Wchar,   T.Dchar,  T.Bool,
+         T.Byte,   T.Ubyte,   T.Short,  T.Ushort,
+         T.Int,    T.Uint,    T.Long,   T.Ulong,
+         T.Float,  T.Double,  T.Real,
+         T.Ifloat, T.Idouble, T.Ireal,
+         T.Cfloat, T.Cdouble, T.Creal, T.Void:
+      auto type = new IntegralType(token.type);
+      nT();
+      set(type, begin);
+      require(T.Dot);
+      auto ident = requireId();
+
+      e = new TypeDotIdExpression(type, ident);
+      break;
+    version(D2)
+    {
+    case T.Traits:
+      nT();
+      require(T.LParen);
+      auto id = requireId();
+      TemplateArguments args;
+      if (token.type == T.Comma)
+      {
+        args = parseTemplateArguments2();
+      }
+      else
+        require(T.RParen);
+      e = new TraitsExpression(id, args);
+      break;
+    }
+    case T.Special:
+      e = new SpecialTokenExpression(token);
+      nT();
+      break;
+    default:
+      // TODO: issue error msg.
+      error(MID.ExpectedButFound, "Expression", token.srcText);
+      e = new EmptyExpression();
+    }
+    set(e, begin);
+    return e;
+  }
+
+  Expression parseNewExpression(/*Expression e*/)
+  {
+    auto begin = token;
+    assert(token.type == T.New);
+    nT(); // Skip new keyword.
+
+    Expression[] newArguments;
+    Expression[] ctorArguments;
+
+    if (token.type == T.LParen)
+      newArguments = parseArguments(T.RParen);
+
+    // NewAnonClassExpression:
+    //         new (ArgumentList)opt class (ArgumentList)opt SuperClassopt InterfaceClassesopt ClassBody
+    if (token.type == T.Class)
+    {
+      nT();
+      if (token.type == T.LParen)
+        ctorArguments = parseArguments(T.RParen);
+
+      BaseClass[] bases = token.type != T.LBrace ? parseBaseClasses(false) : null ;
+
+      auto decls = parseDeclarationDefinitionsBlock();
+      return set(new NewAnonClassExpression(/*e, */newArguments, bases, ctorArguments, decls), begin);
+    }
+
+    // NewExpression:
+    //         NewArguments Type [ AssignExpression ]
+    //         NewArguments Type ( ArgumentList )
+    //         NewArguments Type
+    auto type = parseType();
+
+    if (token.type == T.LParen)
+      ctorArguments = parseArguments(T.RParen);
+
+    return set(new NewExpression(/*e, */newArguments, type, ctorArguments), begin);
+  }
+
+  Type parseType()
+  {
+    return parseBasicType2(parseBasicType());
+  }
+
+  Type parseBasicType()
+  {
+    auto begin = token;
+    Type t;
+//     IdentifierType tident;
+
+    switch (token.type)
+    {
+    case T.Char,   T.Wchar,   T.Dchar,  T.Bool,
+         T.Byte,   T.Ubyte,   T.Short,  T.Ushort,
+         T.Int,    T.Uint,    T.Long,   T.Ulong,
+         T.Float,  T.Double,  T.Real,
+         T.Ifloat, T.Idouble, T.Ireal,
+         T.Cfloat, T.Cdouble, T.Creal, T.Void:
+      t = new IntegralType(token.type);
+      nT();
+      set(t, begin);
+      break;
+    case T.Identifier, T.Typeof, T.Dot:
+      t = parseDotListType();
+      break;
+    version(D2)
+    {
+    case T.Const:
+      // const ( Type )
+      nT();
+      require(T.LParen);
+      t = parseType();
+      require(T.RParen);
+      t = new ConstType(t);
+      set(t, begin);
+      break;
+    case T.Invariant:
+      // invariant ( Type )
+      nT();
+      require(T.LParen);
+      t = parseType();
+      require(T.RParen);
+      t = new InvariantType(t);
+      set(t, begin);
+      break;
+    }
+    default:
+      // TODO: issue error msg.
+      error(MID.ExpectedButFound, "BasicType", token.srcText);
+      t = new UndefinedType();
+      nT();
+      set(t, begin);
+    }
+    return t;
+  }
+
+  Type parseBasicType2(Type t)
+  {
+    typeof(token) begin;
+    while (1)
+    {
+      begin = token;
+      switch (token.type)
+      {
+      case T.Mul:
+        t = new PointerType(t);
+        nT();
+        break;
+      case T.LBracket:
+        t = parseArrayType(t);
+        continue;
+      case T.Function, T.Delegate:
+        TOK tok = token.type;
+        nT();
+        auto parameters = parseParameterList();
+        if (tok == T.Function)
+          t = new FunctionType(t, parameters);
+        else
+          t = new DelegateType(t, parameters);
+        break;
+      default:
+        return t;
+      }
+      set(t, begin);
+    }
+    assert(0);
+  }
+
+  bool tokenAfterParenIs(TOK tok)
+  {
+    // We count nested parentheses tokens because template types may appear inside parameter lists; e.g. (int x, Foo!(int) y).
+    assert(token.type == T.LParen);
+    Token* next = token;
+    uint level = 1;
+    while (1)
+    {
+      lx.peek(next);
+      switch (next.type)
+      {
+      case T.RParen:
+        if (--level == 0)
+        { // Closing parentheses found.
+          lx.peek(next);
+          break;
+        }
+        continue;
+      case T.LParen:
+        ++level;
+        continue;
+      case T.EOF:
+        break;
+      default:
+        continue;
+      }
+      break;
+    }
+
+    return next.type == tok;
+  }
+
+  Type parseDeclaratorSuffix(Type t)
+  {
+    switch (token.type)
+    {
+    case T.LBracket:
+      // Type Identifier ArrayType
+      // ArrayType := [] or [Type] or [Expression..Expression]
+      do
+        t = parseArrayType(t);
+      while (token.type == T.LBracket)
+      break;
+/+ // parsed in parseDeclaration()
+    case T.LParen:
+      TemplateParameters tparams;
+      if (tokenAfterParenIs(T.LParen))
+      {
+        // ( TemplateParameterList ) ( ParameterList )
+        tparams = parseTemplateParameterList();
+      }
+
+      auto params = parseParameterList();
+      // ReturnType FunctionName ( ParameterList )
+      t = new FunctionType(t, params, tparams);
+      break;
++/
+    default:
+      break;
+    }
+    return t;
+  }
+
+  Type parseArrayType(Type t)
+  {
+    assert(token.type == T.LBracket);
+    auto begin = token;
+    nT();
+    if (token.type == T.RBracket)
+    {
+      t = new ArrayType(t);
+      nT();
+    }
+    else
+    {
+      bool success;
+      auto assocType = try_(parseType(), success);
+      if (success)
+        t = new ArrayType(t, assocType);
+      else
+      {
+        Expression e = parseExpression(), e2;
+        if (token.type == T.Slice)
+        {
+          nT();
+          e2 = parseExpression();
+        }
+        t = new ArrayType(t, e, e2);
+      }
+      require(T.RBracket);
+    }
+    set(t, begin);
+    return t;
+  }
+
+  Type parseDeclarator(ref Token* ident, bool identOptional = false)
+  {
+    auto t = parseType();
+
+    if (token.type == T.Identifier)
+    {
+      ident = token;
+      nT();
+      t = parseDeclaratorSuffix(t);
+    }
+    else if (!identOptional)
+      expected(T.Identifier);
+
+    return t;
+  }
+
+  Expression[] parseArguments(TOK terminator)
+  {
+    assert(token.type == T.LParen || token.type == T.LBracket || token.type == T.Comma);
+    assert(terminator == T.RParen || terminator == T.RBracket);
+    Expression[] args;
+
+    nT();
+    if (token.type == terminator)
+    {
+      nT();
+      return null;
+    }
+
+    goto LenterLoop;
+    do
+    {
+      nT();
+    LenterLoop:
+      args ~= parseAssignExpression();
+    } while (token.type == T.Comma)
+
+    require(terminator);
+    return args;
+  }
+
+  Parameters parseParameterList()
+  out(params)
+  {
+    if (params.length > 1)
+      foreach (param; params.items[0..$-1])
+      {
+        if (param.isVariadic())
+          assert(0, "variadic arguments can only appear at the end of the parameter list.");
+      }
+  }
+  body
+  {
+    auto begin = token;
+    require(T.LParen);
+
+    auto params = new Parameters();
+
+    if (token.type == T.RParen)
+    {
+      nT();
+      return set(params, begin);
+    }
+
+    while (1)
+    {
+      auto paramBegin = token;
+      Token* stcTok;
+      StorageClass stc, tmp;
+
+      if (token.type == T.Ellipses)
+      {
+        nT();
+        params ~= set(new Parameter(null, null, null, null), paramBegin);
+        break; // Exit loop.
+      }
+
+    Lstc_loop:
+      switch (token.type)
+      {
+      version(D2)
+      {
+      case T.Invariant: // D2.0
+        if (peekNext() == T.LParen)
+          goto default;
+        tmp = StorageClass.Invariant;
+        goto Lcommon;
+      case T.Const: // D2.0
+        if (peekNext() == T.LParen)
+          goto default;
+        tmp = StorageClass.Const;
+        goto Lcommon;
+      case T.Final: // D2.0
+        tmp = StorageClass.Final;
+        goto Lcommon;
+      case T.Scope: // D2.0
+        tmp = StorageClass.Scope;
+        goto Lcommon;
+      case T.Static: // D2.0
+        tmp = StorageClass.Static;
+        goto Lcommon;
+      case T.In:
+        tmp = StorageClass.In;
+        goto Lcommon;
+      case T.Out:
+        tmp = StorageClass.Out;
+        goto Lcommon;
+      case T.Inout, T.Ref:
+        tmp = StorageClass.Ref;
+        goto Lcommon;
+      case T.Lazy:
+        tmp = StorageClass.Lazy;
+        goto Lcommon;
+      Lcommon:
+        if (stc & tmp)
+          error(MID.RedundantStorageClass, token.srcText);
+        else
+          stc |= tmp;
+        nT();
+        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;
+      }
+      default:
+      version(D2)
+      {
+        if (stc != StorageClass.None)
+          stcTok = begin;
+      }
+        Token* ident;
+        auto type = parseDeclarator(ident, true);
+
+        Expression assignExpr;
+        if (token.type == T.Assign)
+        {
+          nT();
+          assignExpr = 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.
+        }
+
+        params ~= set(new Parameter(stcTok, type, ident, assignExpr), paramBegin);
+
+        if (token.type != T.Comma)
+          break; // Exit loop.
+        nT();
+        continue;
+      }
+      break; // Exit loop.
+    }
+    require(T.RParen);
+    return set(params, begin);
+  }
+
+  TemplateArguments parseTemplateArguments()
+  {
+    auto begin = token;
+    auto args = new TemplateArguments;
+
+    require(T.LParen);
+    if (token.type != T.RParen)
+    {
+      while (1)
+      {
+        bool success;
+        auto typeArgument = try_(parseType(), success);
+        if (success)
+        {
+          // TemplateArgument:
+          //         Type
+          //         Symbol
+          args ~= typeArgument;
+        }
+        else
+        {
+          // TemplateArgument:
+          //         AssignExpression
+          args ~= parseAssignExpression();
+        }
+        if (token.type != T.Comma)
+          break; // Exit loop.
+        nT();
+      }
+    }
+    require(T.RParen);
+    set(args, begin);
+    return args;
+  }
+version(D2)
+{
+  TemplateArguments parseTemplateArguments2()
+  {
+    assert(token.type == T.Comma);
+    nT();
+    auto begin = token;
+    auto args = new TemplateArguments;
+
+    if (token.type != T.RParen)
+    {
+      while (1)
+      {
+        bool success;
+        auto typeArgument = try_(parseType(), success);
+        if (success)
+        {
+          // TemplateArgument:
+          //         Type
+          //         Symbol
+          args ~= typeArgument;
+        }
+        else
+        {
+          // TemplateArgument:
+          //         AssignExpression
+          args ~= parseAssignExpression();
+        }
+        if (token.type != T.Comma)
+          break; // Exit loop.
+        nT();
+      }
+    }
+    else
+      error(MID.ExpectedButFound, "Type/Expression", ")");
+    require(T.RParen);
+    set(args, begin);
+    return args;
+  }
+} // version(D2)
+  TemplateParameters parseTemplateParameterList()
+  {
+    auto begin = token;
+    auto tparams = new TemplateParameters;
+
+    require(T.LParen);
+    if (token.type == T.RParen)
+      return tparams;
+
+    while (1)
+    {
+      auto paramBegin = token;
+      TP tp;
+      Token* ident;
+      Type valueType;
+      Type specType, defType;
+      Expression specValue, defValue;
+
+      switch (token.type)
+      {
+      case T.Alias:
+        // TemplateAliasParameter:
+        //         alias Identifier
+        tp = TP.Alias;
+        nT(); // Skip alias keyword.
+        ident = requireId();
+        // : SpecializationType
+        if (token.type == T.Colon)
+        {
+          nT();
+          specType = parseType();
+        }
+        // = DefaultType
+        if (token.type == T.Assign)
+        {
+          nT();
+          defType = parseType();
+        }
+        break;
+      case T.Identifier:
+        ident = token;
+        switch (peekNext())
+        {
+        case T.Ellipses:
+          // TemplateTupleParameter:
+          //         Identifier ...
+          tp = TP.Tuple;
+          nT(); // Skip Identifier.
+          nT(); // Skip Ellipses.
+          // if (token.type == T.Comma)
+          //  error(); // TODO: issue error msg for variadic param not being last.
+          break;
+        case T.Comma, T.RParen, T.Colon, T.Assign:
+          // TemplateTypeParameter:
+          //         Identifier
+          tp = TP.Type;
+          nT(); // Skip Identifier.
+          // : SpecializationType
+          if (token.type == T.Colon)
+          {
+            nT();
+            specType = parseType();
+          }
+          // = DefaultType
+          if (token.type == T.Assign)
+          {
+            nT();
+            defType = parseType();
+          }
+          break;
+        default:
+          // TemplateValueParameter:
+          //         Declarator
+          ident = null;
+          goto LTemplateValueParameter;
+        }
+        break;
+      default:
+      LTemplateValueParameter:
+        // TemplateValueParameter:
+        //         Declarator
+        tp = TP.Value;
+        valueType = parseDeclarator(ident);
+        // : SpecializationValue
+        if (token.type == T.Colon)
+        {
+          nT();
+          specValue = parseCondExpression();
+        }
+        // = DefaultValue
+        if (token.type == T.Assign)
+        {
+          nT();
+          defValue = parseCondExpression();
+        }
+      }
+
+      tparams ~= set(new TemplateParameter(tp, valueType, ident, specType, defType, specValue, defValue), paramBegin);
+
+      if (token.type != T.Comma)
+        break;
+      nT();
+    }
+    require(T.RParen);
+    set(tparams, begin);
+    return tparams;
+  }
+
+  void expected(TOK tok)
+  {
+    if (token.type != tok)
+      error(MID.ExpectedButFound, Token.Token.toString(tok), token.srcText);
+  }
+
+  void require(TOK tok)
+  {
+    if (token.type == tok)
+      nT();
+    else
+      error(MID.ExpectedButFound, Token.Token.toString(tok), token.srcText);
+  }
+
+  void requireNext(TOK tok)
+  {
+    nT();
+    require(tok);
+  }
+
+  string requireIdentifier()
+  {
+    string identifier;
+    if (token.type == T.Identifier)
+    {
+      identifier = token.identifier;
+      nT();
+    }
+    else
+      error(MID.ExpectedButFound, "Identifier", token.srcText);
+    return identifier;
+  }
+
+  Token* requireId()
+  {
+    if (token.type == T.Identifier)
+    {
+      auto id = token;
+      nT();
+      return id;
+    }
+    else
+      error(MID.ExpectedButFound, "Identifier", token.srcText);
+    return null;
+  }
+
+  void error(MID id, ...)
+  {
+    if (trying)
+    {
+      ++errorCount;
+      return;
+    }
+
+//     if (errors.length == 10)
+//       return;
+    errors ~= new Information(InfoType.Parser, id, lx.loc, arguments(_arguments, _argptr));
+//     writefln("(%d)P: ", lx.loc, errors[$-1].getMsg);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/Settings.d	Tue Aug 21 16:28:05 2007 +0000
@@ -0,0 +1,104 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module Settings;
+import Messages;
+import Parser, SyntaxTree, Declarations, Expressions;
+import std.metastrings;
+
+version(D2)
+{
+  const VERSION_MAJOR = 2;
+  const VERSION_MINOR = 0;
+}
+else
+{
+  const VERSION_MAJOR = 1;
+  const VERSION_MINOR = 0;
+}
+const string VERSION = Format!("%s.%s", VERSION_MAJOR, VERSION_MINOR);
+
+const COMPILED_WITH = __VENDOR__;
+const COMPILED_VERSION = Format!("%s.%s", __VERSION__/1000, __VERSION__%1000);
+const COMPILED_DATE = __TIMESTAMP__;
+
+const usageHighlight = "highlight (hl) file.d";
+
+struct GlobalSettings
+{
+static:
+  string language; /// Language of messages catalogue to load.
+  string[] messages; /// Table of localized compiler messages.
+  void load()
+  {
+    auto fileName = "config.d"[];
+    auto sourceText = cast(char[]) std.file.read(fileName);
+    auto parser = new Parser(sourceText, fileName);
+    parser.start();
+    auto root = parser.parseModule();
+
+    if (parser.errors.length || parser.lx.errors.length)
+    {
+      throw new Exception("There are errors in " ~ fileName ~ ".");
+    }
+
+    foreach (decl; root.children)
+    {
+      auto v = Cast!(VariableDeclaration)(decl);
+      if (v && v.idents[0].srcText == "language")
+      {
+        auto e = v.values[0];
+        if (!e)
+          throw new Exception("language variable has no value set.");
+        auto val = Cast!(StringLiteralsExpression)(e);
+        if (val)
+        {
+          GlobalSettings.language = val.getString();
+          break;
+        }
+      }
+    }
+
+    // Load messages
+    if (GlobalSettings.language.length)
+    {
+      fileName = "lang_" ~ GlobalSettings.language ~ ".d";
+      sourceText = cast(char[]) std.file.read(fileName);
+      parser = new Parser(sourceText, fileName);
+      parser.start();
+      root = parser.parseModule();
+
+      if (parser.errors.length || parser.lx.errors.length)
+      {
+        throw new Exception("There are errors in "~fileName~".");
+      }
+
+      char[][] messages;
+      foreach (decl; root.children)
+      {
+        auto v = Cast!(VariableDeclaration)(decl);
+        if (v && v.idents[0].srcText == "messages")
+        {
+          auto e = v.values[0];
+          if (!e)
+            throw new Exception("messages variable in "~fileName~" has no value set.");
+          if (auto array = Cast!(ArrayInitializer)(e))
+          {
+            foreach (value; array.values)
+            {
+              if (auto str = Cast!(StringLiteralsExpression)(value))
+                messages ~= str.getString();
+            }
+          }
+          else
+            throw new Exception("messages variable is set to "~e.classinfo.name~" instead of an ArrayInitializer.");
+        }
+      }
+      if (messages.length != MID.max+1)
+        throw new Exception(std.string.format("messages table in %s must exactly have %d entries, but %s were found.", fileName, MID.max, messages.length));
+      GlobalSettings.messages = messages;
+    }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/Statements.d	Tue Aug 21 16:28:05 2007 +0000
@@ -0,0 +1,567 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module Statements;
+import SyntaxTree;
+import Expressions;
+import Declarations;
+import Types;
+import Token;
+
+abstract class Statement : Node
+{
+  this()
+  {
+    super(NodeCategory.Statement);
+  }
+}
+
+class Statements : Statement
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+
+  void opCatAssign(Statement s)
+  {
+    this.children ~= s;
+  }
+}
+
+class IllegalStatement : Statement
+{
+  Token* tok;
+  this(Token* tok)
+  {
+    mixin(set_kind);
+    this.tok = tok;
+  }
+}
+
+class EmptyStatement : Statement
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+}
+
+class FunctionBody : Node
+{
+  Statement funcBody, inBody, outBody;
+  Token* outIdent;
+  this()
+  {
+    super(NodeCategory.Other);
+    mixin(set_kind);
+  }
+
+  void finishConstruction()
+  {
+    if (funcBody)
+      this.children ~= funcBody;
+    if (inBody)
+      this.children ~= inBody;
+    if (outBody)
+      this.children ~= outBody;
+  }
+}
+
+class ScopeStatement : Statement
+{
+  Statement s;
+  this(Statement s)
+  {
+    mixin(set_kind);
+    this.children = [s];
+    this.s = s;
+  }
+}
+
+class LabeledStatement : Statement
+{
+  Token* label;
+  Statement s;
+  this(Token* label, Statement s)
+  {
+    mixin(set_kind);
+    this.children = [s];
+    this.label = label;
+    this.s = s;
+  }
+}
+
+class ExpressionStatement : Statement
+{
+  Expression expression;
+  this(Expression expression)
+  {
+    mixin(set_kind);
+    this.children = [expression];
+    this.expression = expression;
+  }
+}
+
+class DeclarationStatement : Statement
+{
+  Declaration declaration;
+  this(Declaration declaration)
+  {
+    mixin(set_kind);
+    this.children = [declaration];
+    this.declaration = declaration;
+  }
+}
+
+class IfStatement : Statement
+{
+  Statement variable; // AutoDeclaration or VariableDeclaration
+  Expression condition;
+  Statement ifBody;
+  Statement elseBody;
+  this(Statement variable, Expression condition, Statement ifBody, Statement elseBody)
+  {
+    mixin(set_kind);
+    if (variable)
+      this.children ~= variable;
+    else
+      this.children ~= condition;
+    this.children ~= ifBody;
+    if (elseBody)
+      this.children ~= elseBody;
+    this.variable = variable;
+    this.condition = condition;
+    this.ifBody = ifBody;
+    this.elseBody = elseBody;
+  }
+}
+
+class WhileStatement : Statement
+{
+  Expression condition;
+  Statement whileBody;
+  this(Expression condition, Statement whileBody)
+  {
+    mixin(set_kind);
+    this.children = [cast(Node)condition, whileBody];
+    this.condition = condition;
+    this.whileBody = whileBody;
+  }
+}
+
+class DoWhileStatement : Statement
+{
+  Expression condition;
+  Statement doBody;
+  this(Expression condition, Statement doBody)
+  {
+    mixin(set_kind);
+    this.children = [cast(Node)condition, doBody];
+    this.condition = condition;
+    this.doBody = doBody;
+  }
+}
+
+class ForStatement : Statement
+{
+  Statement init;
+  Expression condition, increment;
+  Statement forBody;
+
+  this(Statement init, Expression condition, Expression increment, Statement forBody)
+  {
+    mixin(set_kind);
+    if (init)
+      this.children ~= init;
+    if (condition)
+      this.children ~= condition;
+    if (increment)
+      this.children ~= increment;
+    this.children ~= forBody;
+    this.init = init;
+    this.condition = condition;
+    this.increment = increment;
+    this.forBody = forBody;
+  }
+}
+
+class ForeachStatement : Statement
+{
+  TOK tok;
+  Parameters params;
+  Expression aggregate;
+  Statement forBody;
+
+  this(TOK tok, Parameters params, Expression aggregate, Statement forBody)
+  {
+    mixin(set_kind);
+    this.children = [cast(Node)params, aggregate, forBody];
+    this.tok = tok;
+    this.params = params;
+    this.aggregate = aggregate;
+    this.forBody = forBody;
+  }
+}
+
+version(D2)
+{
+class ForeachRangeStatement : Statement
+{
+  TOK tok;
+  Parameters params;
+  Expression lower, upper;
+  Statement forBody;
+
+  this(TOK tok, Parameters params, Expression lower, Expression upper, Statement forBody)
+  {
+    mixin(set_kind);
+    this.children = [cast(Node)params, lower, upper, forBody];
+    this.tok = tok;
+    this.params = params;
+    this.lower = lower;
+    this.upper = upper;
+    this.forBody = forBody;
+  }
+}
+}
+
+class SwitchStatement : Statement
+{
+  Expression condition;
+  Statement switchBody;
+
+  this(Expression condition, Statement switchBody)
+  {
+    mixin(set_kind);
+    this.children = [cast(Node)condition, switchBody];
+    this.condition = condition;
+    this.switchBody = switchBody;
+  }
+}
+
+class CaseStatement : Statement
+{
+  Expression[] values;
+  Statement caseBody;
+
+  this(Expression[] values, Statement caseBody)
+  {
+    mixin(set_kind);
+    this.children = cast(Node[])values ~ [caseBody];
+    this.values = values;
+    this.caseBody = caseBody;
+  }
+}
+
+class DefaultStatement : Statement
+{
+  Statement defaultBody;
+  this(Statement defaultBody)
+  {
+    mixin(set_kind);
+    this.children = [defaultBody];
+    this.defaultBody = defaultBody;
+  }
+}
+
+class ContinueStatement : Statement
+{
+  Token* ident;
+  this(Token* ident)
+  {
+    mixin(set_kind);
+    this.ident = ident;
+  }
+}
+
+class BreakStatement : Statement
+{
+  Token* ident;
+  this(Token* ident)
+  {
+    mixin(set_kind);
+    this.ident = ident;
+  }
+}
+
+class ReturnStatement : Statement
+{
+  Expression expr;
+  this(Expression expr)
+  {
+    mixin(set_kind);
+    if (expr)
+      this.children = [expr];
+    this.expr = expr;
+  }
+}
+
+class GotoStatement : Statement
+{
+  Token* ident;
+  Expression caseExpr;
+  this(Token* ident, Expression caseExpr)
+  {
+    mixin(set_kind);
+    if (caseExpr)
+      this.children = [caseExpr];
+    this.ident = ident;
+    this.caseExpr = caseExpr;
+  }
+}
+
+class WithStatement : Statement
+{
+  Expression expr;
+  Statement withBody;
+  this(Expression expr, Statement withBody)
+  {
+    mixin(set_kind);
+    this.children = [cast(Node)expr, withBody];
+    this.expr = expr;
+    this.withBody = withBody;
+  }
+}
+
+class SynchronizedStatement : Statement
+{
+  Expression expr;
+  Statement syncBody;
+  this(Expression expr, Statement withBody)
+  {
+    mixin(set_kind);
+    this.children = [cast(Node)expr, syncBody];
+    this.expr = expr;
+    this.syncBody = syncBody;
+  }
+}
+
+class TryStatement : Statement
+{
+  Statement tryBody;
+  CatchBody[] catchBodies;
+  FinallyBody finallyBody;
+  this(Statement tryBody, CatchBody[] catchBodies, FinallyBody finallyBody)
+  {
+    mixin(set_kind);
+    this.children = [tryBody];
+    if (catchBodies.length)
+      this.children ~= catchBodies;
+    if (finallyBody)
+      this.children ~= finallyBody;
+    this.tryBody = tryBody;
+    this.catchBodies = catchBodies;
+    this.finallyBody = finallyBody;
+  }
+}
+
+class CatchBody : Statement
+{
+  Parameter param;
+  Statement catchBody;
+  this(Parameter param, Statement catchBody)
+  {
+    mixin(set_kind);
+    this.children = [cast(Node)param, catchBody];
+    this.param = param;
+    this.catchBody = catchBody;
+  }
+}
+
+class FinallyBody : Statement
+{
+  Statement finallyBody;
+  this(Statement finallyBody)
+  {
+    mixin(set_kind);
+    this.children = [finallyBody];
+    this.finallyBody = finallyBody;
+  }
+}
+
+class ScopeGuardStatement : Statement
+{
+  Token* condition;
+  Statement scopeBody;
+  this(Token* condition, Statement scopeBody)
+  {
+    mixin(set_kind);
+    this.children = [scopeBody];
+    this.condition = condition;
+    this.scopeBody = scopeBody;
+  }
+}
+
+class ThrowStatement : Statement
+{
+  Expression expr;
+  this(Expression expr)
+  {
+    mixin(set_kind);
+    this.children = [expr];
+    this.expr = expr;
+  }
+}
+
+class VolatileStatement : Statement
+{
+  Statement volatileBody;
+  this(Statement volatileBody)
+  {
+    mixin(set_kind);
+    if (volatileBody)
+      this.children = [volatileBody];
+    this.volatileBody = volatileBody;
+  }
+}
+
+class AsmStatement : Statement
+{
+  Statements statements;
+  this(Statements statements)
+  {
+    mixin(set_kind);
+    this.children = [statements];
+    this.statements = statements;
+  }
+}
+
+class AsmInstruction : Statement
+{
+  Token* ident;
+  Expression[] operands;
+  this(Token* ident, Expression[] operands)
+  {
+    mixin(set_kind);
+    this.children = operands;
+    this.ident = ident;
+    this.operands = operands;
+  }
+}
+
+class IllegalAsmInstruction : IllegalStatement
+{
+  this(Token* token)
+  {
+    super(token);
+    mixin(set_kind);
+  }
+}
+
+class PragmaStatement : Statement
+{
+  Token* ident;
+  Expression[] args;
+  Statement pragmaBody;
+  this(Token* ident, Expression[] args, Statement pragmaBody)
+  {
+    mixin(set_kind);
+    if (args.length)
+      this.children = args;
+    this.children ~= pragmaBody;
+    this.ident = ident;
+    this.args = args;
+    this.pragmaBody = pragmaBody;
+  }
+}
+
+class MixinStatement : Statement
+{
+  Expression[] templateIdents;
+  Token* mixinIdent;
+  this(Expression[] templateIdents, Token* mixinIdent)
+  {
+    mixin(set_kind);
+    this.children = templateIdents;
+    this.templateIdents = templateIdents;
+    this.mixinIdent = mixinIdent;
+  }
+}
+
+class StaticIfStatement : Statement
+{
+  Expression condition;
+  Statement ifBody, elseBody;
+  this(Expression condition, Statement ifBody, Statement elseBody)
+  {
+    mixin(set_kind);
+    this.children = [cast(Node)condition, ifBody];
+    if (elseBody)
+      this.children ~= elseBody;
+    this.condition = condition;
+    this.ifBody = ifBody;
+    this.elseBody = elseBody;
+  }
+}
+
+class StaticAssertStatement : Statement
+{
+  Expression condition, message;
+  this(Expression condition, Expression message)
+  {
+    mixin(set_kind);
+    this.children = [condition];
+    if (message)
+      this.children ~= message;
+    this.condition = condition;
+    this.message = message;
+  }
+}
+
+class DebugStatement : Statement
+{
+  Token* cond;
+  Statement debugBody, elseBody;
+  this(Token* cond, Statement debugBody, Statement elseBody)
+  {
+    mixin(set_kind);
+    this.children = [debugBody];
+    if (elseBody)
+      this.children ~= elseBody;
+    this.cond = cond;
+    this.debugBody = debugBody;
+    this.elseBody = elseBody;
+  }
+}
+
+class VersionStatement : Statement
+{
+  Token* cond;
+  Statement versionBody, elseBody;
+  this(Token* cond, Statement versionBody, Statement elseBody)
+  {
+    mixin(set_kind);
+    this.children = [versionBody];
+    if (elseBody)
+      this.children ~= [elseBody];
+    this.cond = cond;
+    this.versionBody = versionBody;
+    this.elseBody = elseBody;
+  }
+}
+
+class AttributeStatement : Statement
+{
+  TOK tok;
+  Statement statement;
+  this(TOK tok, Statement statement)
+  {
+    mixin(set_kind);
+    this.children = [statement];
+    this.tok = tok;
+    this.statement = statement;
+  }
+}
+
+class ExternStatement : AttributeStatement
+{
+  Linkage linkage;
+  this(Linkage linkage, Statement statement)
+  {
+    super(TOK.Extern, statement);
+    mixin(set_kind);
+    this.linkage = linkage;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/SyntaxTree.d	Tue Aug 21 16:28:05 2007 +0000
@@ -0,0 +1,238 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module SyntaxTree;
+import Token;
+
+enum NodeCategory
+{
+  Declaration,
+  Statement,
+  Expression,
+  Type,
+  Other
+}
+
+enum NodeKind
+{
+  // Declarations:
+  Declarations,
+  EmptyDeclaration,
+  IllegalDeclaration,
+  ModuleDeclaration,
+  ImportDeclaration,
+  AliasDeclaration,
+  TypedefDeclaration,
+  EnumDeclaration,
+  ClassDeclaration,
+  InterfaceDeclaration,
+  StructDeclaration,
+  UnionDeclaration,
+  ConstructorDeclaration,
+  StaticConstructorDeclaration,
+  DestructorDeclaration,
+  StaticDestructorDeclaration,
+  FunctionDeclaration,
+  VariableDeclaration,
+  InvariantDeclaration,
+  UnittestDeclaration,
+  DebugDeclaration,
+  VersionDeclaration,
+  StaticIfDeclaration,
+  StaticAssertDeclaration,
+  TemplateDeclaration,
+  NewDeclaration,
+  DeleteDeclaration,
+  AttributeDeclaration,
+  ExternDeclaration,
+  AlignDeclaration,
+  PragmaDeclaration,
+  MixinDeclaration,
+
+  // Statements:
+  Statements,
+  IllegalStatement,
+  EmptyStatement,
+  ScopeStatement,
+  LabeledStatement,
+  ExpressionStatement,
+  DeclarationStatement,
+  IfStatement,
+  ConditionalStatement,
+  WhileStatement,
+  DoWhileStatement,
+  ForStatement,
+  ForeachStatement,
+  ForeachRangeStatement, // D2.0
+  SwitchStatement,
+  CaseStatement,
+  DefaultStatement,
+  ContinueStatement,
+  BreakStatement,
+  ReturnStatement,
+  GotoStatement,
+  WithStatement,
+  SynchronizedStatement,
+  TryStatement,
+  CatchBody,
+  FinallyBody,
+  ScopeGuardStatement,
+  ThrowStatement,
+  VolatileStatement,
+  AsmStatement,
+  AsmInstruction,
+  IllegalAsmInstruction,
+  PragmaStatement,
+  MixinStatement,
+  StaticIfStatement,
+  StaticAssertStatement,
+  DebugStatement,
+  VersionStatement,
+  AttributeStatement,
+  ExternStatement,
+
+  // Expressions:
+  EmptyExpression,
+  BinaryExpression,
+  CondExpression,
+  CommaExpression,
+  OrOrExpression,
+  AndAndExpression,
+  OrExpression,
+  XorExpression,
+  AndExpression,
+  CmpExpression,
+  EqualExpression,
+  IdentityExpression,
+  RelExpression,
+  InExpression,
+  LShiftExpression,
+  RShiftExpression,
+  URShiftExpression,
+  PlusExpression,
+  MinusExpression,
+  CatExpression,
+  MulExpression,
+  DivExpression,
+  ModExpression,
+  AssignExpression,
+  LShiftAssignExpression,
+  RShiftAssignExpression,
+  URShiftAssignExpression,
+  OrAssignExpression,
+  AndAssignExpression,
+  PlusAssignExpression,
+  MinusAssignExpression,
+  DivAssignExpression,
+  MulAssignExpression,
+  ModAssignExpression,
+  XorAssignExpression,
+  CatAssignExpression,
+  UnaryExpression,
+  AddressExpression,
+  PreIncrExpression,
+  PreDecrExpression,
+  PostIncrExpression,
+  PostDecrExpression,
+  DerefExpression,
+  SignExpression,
+  NotExpression,
+  CompExpression,
+  PostDotListExpression,
+  CallExpression,
+  NewExpression,
+  NewAnonClassExpression,
+  DeleteExpression,
+  CastExpression,
+  IndexExpression,
+  SliceExpression,
+  PrimaryExpressio,
+  IdentifierExpression,
+  SpecialTokenExpression,
+  DotListExpression,
+  TemplateInstanceExpression,
+  ThisExpression,
+  SuperExpression,
+  NullExpression,
+  DollarExpression,
+  BoolExpression,
+  IntNumberExpression,
+  RealNumberExpression,
+  CharLiteralExpression,
+  StringLiteralsExpression,
+  ArrayLiteralExpression,
+  AssocArrayLiteralExpression,
+  AssertExpression,
+  MixinExpression,
+  ImportExpression,
+  TypeofExpression,
+  TypeDotIdExpression,
+  TypeidExpression,
+  IsExpression,
+  FunctionLiteralExpression,
+  TraitsExpression, // D2.0
+  VoidInitializer,
+  ArrayInitializer,
+  StructInitializer,
+  AsmTypeExpression,
+  AsmOffsetExpression,
+  AsmSegExpression,
+  AsmPostBracketExpression,
+  AsmBracketExpression,
+  AsmLocalSizeExpression,
+  AsmRegisterExpression,
+
+  // Types:
+  IntegralType,
+  UndefinedType,
+  DotListType,
+  IdentifierType,
+  TypeofType,
+  TemplateInstanceType,
+  PointerType,
+  ArrayType,
+  FunctionType,
+  DelegateType,
+  ConstType, // D2.0
+  InvariantType, // D2.0
+
+  // Other:
+  FunctionBody,
+  Parameter,
+  Parameters,
+  BaseClass,
+  TemplateParameter,
+  TemplateParameters,
+  TemplateArguments,
+}
+
+/// This string is mixed into the constructor of a class that inherits from Node.
+const string set_kind = `this.kind = mixin("NodeKind." ~ typeof(this).stringof);`;
+
+Class Cast(Class)(Node n)
+{
+  assert(n !is null);
+  if (n.kind == mixin("NodeKind." ~ typeof(Class).stringof))
+    return cast(Class)cast(void*)n;
+  return null;
+}
+
+class Node
+{
+  NodeCategory category;
+  NodeKind kind;
+  Node[] children;
+  Token* begin, end;
+
+  this(NodeCategory category)
+  {
+    this.category = category;
+  }
+
+  void setTokens(Token* begin, Token* end)
+  {
+    this.begin = begin;
+    this.end = end;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/Token.d	Tue Aug 21 16:28:05 2007 +0000
@@ -0,0 +1,257 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module Token;
+import std.c.stdlib : malloc, free;
+import std.outofmemory;
+
+struct Position
+{
+  size_t loc;
+  size_t col;
+}
+
+enum TOK : ushort
+{
+  Invalid,
+
+  /// Flag for whitespace tokens that must be ignored in the parsing phase.
+  Whitespace = 0x8000,
+  Comment = 1 | Whitespace,
+  Shebang = 2 | Whitespace,
+  HashLine = 3 | Whitespace,
+  Filespec = 4 | Whitespace,
+
+  Identifier = 5,
+  String,
+  Special,
+  CharLiteral, WCharLiteral, DCharLiteral,
+
+  // Numbers
+  Int32, Int64, Uint32, Uint64,
+  // Floating point number scanner relies on this order. (FloatXY + 3 == ImaginaryXY)
+  Float32, Float64, Float80,
+  Imaginary32, Imaginary64, Imaginary80,
+
+
+  // Brackets
+  LParen,
+  RParen,
+  LBracket,
+  RBracket,
+  LBrace,
+  RBrace,
+
+  Dot, Slice, Ellipses,
+
+  // Floating point number operators
+  Unordered,
+  UorE,
+  UorG,
+  UorGorE,
+  UorL,
+  UorLorE,
+  LorEorG,
+  LorG,
+
+  // Normal operators
+  Assign, Equal, NotEqual, Not,
+  LessEqual, Less,
+  GreaterEqual, Greater,
+  LShiftAssign, LShift,
+  RShiftAssign,RShift,
+  URShiftAssign, URShift,
+  OrAssign, OrLogical, OrBinary,
+  AndAssign, AndLogical, AndBinary,
+  PlusAssign, PlusPlus, Plus,
+  MinusAssign, MinusMinus, Minus,
+  DivAssign, Div,
+  MulAssign, Mul,
+  ModAssign, Mod,
+  XorAssign, Xor,
+  CatAssign, Catenate,
+  Tilde,
+  Identity, NotIdentity,
+
+  Colon,
+  Semicolon,
+  Question,
+  Comma,
+  Dollar,
+
+  /* Keywords:
+     NB.: Token.isKeyword() depends on this list being contiguous.
+  */
+  Abstract,Alias,Align,Asm,Assert,Auto,Body,
+  Bool,Break,Byte,Case,Cast,Catch,Cdouble,
+  Cent,Cfloat,Char,Class,Const,Continue,Creal,
+  Dchar,Debug,Default,Delegate,Delete,Deprecated,Do,
+  Double,Else,Enum,Export,Extern,False,Final,
+  Finally,Float,For,Foreach,Foreach_reverse,Function,Goto,
+  Idouble,If,Ifloat,Import,In,Inout,Int,
+  Interface,Invariant,Ireal,Is,Lazy,Long,Macro/+D2.0+/,
+  Mixin,Module,New,Null,Out,Override,Package,
+  Pragma,Private,Protected,Public,Real,Ref/+D2.0+/,Return,
+  Scope,Short,Static,Struct,Super,Switch,Synchronized,
+  Template,This,Throw,Traits/+D2.0+/,True,Try,Typedef,Typeid,
+  Typeof,Ubyte,Ucent,Uint,Ulong,Union,Unittest,
+  Ushort,Version,Void,Volatile,Wchar,While,With,
+
+  HEAD, // start of linked list
+  EOF
+}
+
+alias TOK.Abstract KeywordsBegin;
+alias TOK.With KeywordsEnd;
+
+struct Token
+{
+  TOK type;
+//   Position pos;
+
+  Token* next, prev;
+
+  char* start;
+  char* end;
+
+  union
+  {
+    struct
+    {
+      Token* line_num; // #line number
+      Token* line_filespec; // #line number filespec
+    }
+    struct
+    {
+      string str;
+      char pf;
+    }
+    dchar  dchar_;
+    long   long_;
+    ulong  ulong_;
+    int    int_;
+    uint   uint_;
+    float  float_;
+    double double_;
+    real   real_;
+  }
+
+  alias srcText identifier;
+
+  string srcText()
+  {
+    assert(start && end);
+    return start[0 .. end - start];
+  }
+
+  static string toString(TOK tok)
+  {
+    return tokToString[tok];
+  }
+
+  bool isKeyword()
+  {
+    return KeywordsBegin <= type && type <= KeywordsEnd;
+  }
+
+  bool isWhitespace()
+  {
+    return !!(type & TOK.Whitespace);
+  }
+
+  int opEquals(TOK type2)
+  {
+    return type == type2;
+  }
+
+  new(size_t size)
+  {
+    void* p = malloc(size);
+    if (p is null)
+      throw new OutOfMemoryException();
+    *cast(Token*)p = Token.init;
+    return p;
+  }
+
+  delete(void* p)
+  {
+    free(p);
+  }
+}
+
+string[] tokToString = [
+  "Invalid",
+
+  "Comment",
+  "#! /shebang/",
+  "#line",
+
+  "Identifier",
+  "String",
+  "Special",
+  "CharLiteral", "WCharLiteral", "DCharLiteral",
+
+  "Int32", "Int64", "Uint32", "Uint64",
+  "Float32", "Float64", "Float80",
+  "Imaginary32", "Imaginary64", "Imaginary80",
+
+  "(",
+  ")",
+  "[",
+  "]",
+  "{",
+  "}",
+
+  ".", "..", "...",
+
+  "Unordered",
+  "UorE",
+  "UorG",
+  "UorGorE",
+  "UorL",
+  "UorLorE",
+  "LorEorG",
+  "LorG",
+
+  "=", "==", "!=", "!",
+  "<=", "<",
+  ">=", ">",
+  "<<=", "<<",
+  ">>=",">>",
+  ">>>=", ">>>",
+  "|=", "||", "|",
+  "&=", "&&", "&",
+  "+=", "++", "+",
+  "-=", "--", "-",
+  "/=", "/",
+  "*=", "*",
+  "%=", "%",
+  "^=", "^",
+  "~=", "~",
+  "~",
+  "is", "!is",
+
+  ":",
+  ";",
+  "?",
+  ",",
+  "$",
+
+  "abstract","alias","align","asm","assert","auto","body",
+  "bool","break","byte","case","cast","catch","cdouble",
+  "cent","cfloat","char","class","const","continue","creal",
+  "dchar","debug","default","delegate","delete","deprecated","do",
+  "double","else","enum","export","extern","false","final",
+  "finally","float","for","foreach","foreach_reverse","function","goto",
+  "idouble","if","ifloat","import","in","inout","int",
+  "interface","invariant","ireal","is","lazy","long","macro",
+  "mixin","module","new","null","out","override","package",
+  "pragma","private","protected","public","real","ref","return",
+  "scope","short","static","struct","super","switch","synchronized",
+  "template","this","throw","true","try","typedef","typeid",
+  "typeof","ubyte","ucent","uint","ulong","union","unittest",
+  "ushort","version","void","volatile","wchar","while","with",
+
+  "EOF"
+];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/Types.d	Tue Aug 21 16:28:05 2007 +0000
@@ -0,0 +1,426 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module Types;
+import SyntaxTree;
+import Token;
+import Expressions;
+
+enum Linkage
+{
+  Invalid,
+  C,
+  Cpp,
+  D,
+  Windows,
+  Pascal,
+  System
+}
+
+enum StorageClass
+{
+  None         = 0,
+  Abstract     = 1,
+  Auto         = 1<<2,
+  Const        = 1<<3,
+  Deprecated   = 1<<4,
+  Extern       = 1<<5,
+  Final        = 1<<6,
+  Invariant    = 1<<7,
+  Override     = 1<<8,
+  Scope        = 1<<9,
+  Static       = 1<<10,
+  Synchronized = 1<<11,
+  In           = 1<<12,
+  Out          = 1<<13,
+  Ref          = 1<<14,
+  Lazy         = 1<<15,
+  Variadic     = 1<<16,
+}
+
+class Parameter : Node
+{
+  StorageClass stc;
+  Token* stcTok;
+  Type type;
+  Token* ident;
+  Expression assignExpr;
+
+  this(Token* stcTok, Type type, Token* ident, Expression assignExpr)
+  {
+    super(NodeCategory.Other);
+    mixin(set_kind);
+    if (type) // type can be null when param in foreach statement
+      this.children = [type];
+    if (assignExpr)
+      this.children ~= 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;
+  }
+
+  bool isVariadic()
+  {
+    return !!(stc & StorageClass.Variadic);
+  }
+
+  bool isOnlyVariadic()
+  {
+    return stc == StorageClass.Variadic;
+  }
+}
+
+class Parameters : Node
+{
+  this()
+  {
+    super(NodeCategory.Other);
+    mixin(set_kind);
+  }
+
+  bool hasVariadic()
+  {
+    if (children.length != 0)
+      return items[$-1].isVariadic();
+    return false;
+  }
+
+  void opCatAssign(Parameter param)
+  { children ~= param; }
+
+  Parameter[] items()
+  { return cast(Parameter[])children; }
+
+  size_t length()
+  { return children.length; }
+}
+
+
+enum Protection
+{
+  None,
+  Private   = 1,
+  Protected = 1<<1,
+  Package   = 1<<2,
+  Public    = 1<<3,
+  Export    = 1<<4
+}
+
+class BaseClass : Node
+{
+  Protection prot;
+  Type type;
+  this(Protection prot, Type type)
+  {
+    super(NodeCategory.Other);
+    mixin(set_kind);
+    this.children = [type];
+    this.prot = prot;
+    this.type = type;
+  }
+}
+
+enum TP
+{
+  Type,
+  Value,
+  Alias,
+  Tuple
+}
+
+class TemplateParameter : Node
+{
+  TP tp;
+  Type valueType;
+  Token* ident;
+  Type specType, defType;
+  Expression specValue, defValue;
+  this(TP tp, Type valueType, Token* ident, Type specType, Type defType, Expression specValue, Expression defValue)
+  {
+    super(NodeCategory.Other);
+    mixin(set_kind);
+    if (valueType)
+      this.children ~= valueType;
+    if (specType)
+      this.children ~= specType;
+    if (defType)
+      this.children ~= defType;
+    if (specValue)
+      this.children ~= specValue;
+    if (defValue)
+      this.children ~= defValue;
+    this.tp = tp;
+    this.valueType = valueType;
+    this.ident = ident;
+    this.specType = specType;
+    this.defType = defType;
+    this.specValue = specValue;
+    this.defValue = defValue;
+  }
+}
+
+class TemplateParameters : Node
+{
+  this()
+  {
+    super(NodeCategory.Other);
+    mixin(set_kind);
+  }
+
+  void opCatAssign(TemplateParameter parameter)
+  {
+    this.children ~= parameter;
+  }
+
+  TemplateParameter[] items()
+  {
+    return cast(TemplateParameter[])children;
+  }
+}
+
+class TemplateArguments : Node
+{
+  this()
+  {
+    super(NodeCategory.Other);
+    mixin(set_kind);
+  }
+
+  void opCatAssign(Node argument)
+  {
+    this.children ~= argument;
+  }
+}
+
+enum TID
+{
+  Void    = TOK.Void,
+  Char    = TOK.Char,
+  Wchar   = TOK.Wchar,
+  Dchar   = TOK.Dchar,
+  Bool    = TOK.Bool,
+  Byte    = TOK.Byte,
+  Ubyte   = TOK.Ubyte,
+  Short   = TOK.Short,
+  Ushort  = TOK.Ushort,
+  Int     = TOK.Int,
+  Uint    = TOK.Uint,
+  Long    = TOK.Long,
+  Ulong   = TOK.Ulong,
+  Float   = TOK.Float,
+  Double  = TOK.Double,
+  Real    = TOK.Real,
+  Ifloat  = TOK.Ifloat,
+  Idouble = TOK.Idouble,
+  Ireal   = TOK.Ireal,
+  Cfloat  = TOK.Cfloat,
+  Cdouble = TOK.Cdouble,
+  Creal   = TOK.Creal,
+
+  Undefined,
+  Function,
+  Delegate,
+  Pointer,
+  Array,
+  DotList,
+  Identifier,
+  Typeof,
+  TemplateInstance,
+  Const, // D2
+  Invariant, // D2
+}
+
+abstract class Type : Node
+{
+  TID tid;
+  Type next;
+
+  this(TID tid)
+  {
+    this(tid, null);
+  }
+
+  this(TID tid, Type next)
+  {
+    super(NodeCategory.Type);
+    if (next)
+      this.children ~= next;
+    this.tid = tid;
+    this.next = next;
+  }
+}
+
+class IntegralType : Type
+{
+  this(TOK tok)
+  {
+    super(cast(TID)tok);
+    mixin(set_kind);
+  }
+}
+
+class UndefinedType : Type
+{
+  this()
+  {
+    super(TID.Undefined);
+    mixin(set_kind);
+  }
+}
+
+class DotListType : Type
+{
+  Type[] dotList;
+  this(Type[] dotList)
+  {
+    super(TID.DotList);
+    mixin(set_kind);
+    this.children ~= dotList;
+    this.dotList = dotList;
+  }
+}
+
+class IdentifierType : Type
+{
+  Token* ident;
+  this(Token* ident)
+  {
+    super(TID.Identifier);
+    mixin(set_kind);
+    this.ident = ident;
+  }
+}
+
+class TypeofType : Type
+{
+  Expression e;
+  this(Expression e)
+  {
+    super(TID.Typeof);
+    mixin(set_kind);
+    this.children ~= e;
+    this.e = e;
+  }
+}
+
+class TemplateInstanceType : Type
+{
+  Token* ident;
+  TemplateArguments targs;
+  this(Token* ident, TemplateArguments targs)
+  {
+    super(TID.TemplateInstance);
+    mixin(set_kind);
+    this.children ~= targs;
+    this.ident = ident;
+    this.targs = targs;
+  }
+}
+
+class PointerType : Type
+{
+  this(Type t)
+  {
+    super(TID.Pointer, t);
+    mixin(set_kind);
+  }
+}
+
+class ArrayType : Type
+{
+  Expression e, e2;
+  Type assocType;
+  this(Type t)
+  {
+    super(TID.Array, t);
+    mixin(set_kind);
+  }
+  this(Type t, Expression e, Expression e2)
+  {
+    this.children = [e];
+    if (e2)
+      this.children ~= e2;
+    this.e = e;
+    this.e2 = e2;
+    this(t);
+  }
+  this(Type t, Type assocType)
+  {
+    this.children = [assocType];
+    this.assocType = assocType;
+    this(t);
+  }
+}
+
+class FunctionType : Type
+{
+  Type returnType;
+  Parameters parameters;
+  this(Type returnType, Parameters parameters)
+  {
+    super(TID.Function);
+    mixin(set_kind);
+    this.children = [cast(Node)returnType, parameters];
+    this.returnType = returnType;
+    this.parameters = parameters;
+  }
+}
+
+class DelegateType : Type
+{
+  Type returnType;
+  Parameters parameters;
+  this(Type returnType, Parameters parameters)
+  {
+    super(TID.Delegate);
+    mixin(set_kind);
+    this.children = [cast(Node)returnType, parameters];
+    this.returnType = returnType;
+    this.parameters = parameters;
+  }
+}
+
+version(D2)
+{
+class ConstType : Type
+{
+  this(Type t)
+  {
+    // If t is null: cast(const)
+    super(TID.Const, t);
+    mixin(set_kind);
+  }
+}
+
+class InvariantType : Type
+{
+  this(Type t)
+  {
+    // If t is null: cast(invariant)
+    super(TID.Invariant, t);
+    mixin(set_kind);
+  }
+}
+} // version(D2)