changeset 618:07946b379006

Refactored the way dot expressions are parsed. DotExpression is a binary expression now. Added ModuleScopeExpression. Removed some obsolete expression classes. Added QualifiedType and ModuleScopeType. Removed some obsolete type node classes. Added genAnonymousID() to IdTable. Removed obsolete parser functions. Improved Node.getDocComments(). Added semantic() methods to some declaration classes.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Fri, 11 Jan 2008 00:42:35 +0100
parents 0749f30ef2d0
children 933cd8d24467
files trunk/src/dil/ast/Declarations.d trunk/src/dil/ast/Expressions.d trunk/src/dil/ast/Node.d trunk/src/dil/ast/Statements.d trunk/src/dil/ast/Types.d trunk/src/dil/lexer/IdTable.d trunk/src/dil/parser/Parser.d trunk/src/main.d
diffstat 8 files changed, 274 insertions(+), 259 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/src/dil/ast/Declarations.d	Thu Jan 10 19:47:34 2008 +0100
+++ b/trunk/src/dil/ast/Declarations.d	Fri Jan 11 00:42:35 2008 +0100
@@ -205,6 +205,21 @@
     addChild(decl);
     this.decl = decl;
   }
+
+  override void semantic(Scope scop)
+  {
+    /+
+    decl.semantic(scop); // call semantic() or do SA in if statements?
+    if (auto fd = TryCast!(FunctionDeclaration)(decl))
+    {
+      // TODO: do SA here?
+    }
+    else if (auto vd = TryCast!(VariableDeclaration)(decl))
+    {
+      // TODO: do SA here?
+    }
+    +/
+  }
 }
 
 class TypedefDeclaration : Declaration
@@ -216,6 +231,21 @@
     addChild(decl);
     this.decl = decl;
   }
+
+  override void semantic(Scope scop)
+  {
+    /+
+    decl.semantic(scop); // call semantic() or do SA in if statements?
+    if (auto fd = TryCast!(FunctionDeclaration)(decl))
+    {
+      // TODO: do SA here?
+    }
+    else if (auto vd = TryCast!(VariableDeclaration)(decl))
+    {
+      // TODO: do SA here?
+    }
+    +/
+  }
 }
 
 class EnumDeclaration : Declaration
@@ -234,6 +264,43 @@
     this.baseType = baseType;
     this.members = members;
   }
+
+  Enum symbol;
+
+  override void semantic(Scope scop)
+  {
+    /+
+    // Create the symbol.
+    symbol = new Enum(name, this);
+    // Type semantics.
+    Type type = Types.Int; // Default to integer.
+    if (baseType)
+      type = baseType.semantic(scop);
+    auto enumType = new EnumType(symbol, type);
+    // Set the base type of the enum symbol.
+    symbol.setType(enumType);
+    if (name)
+    { // Insert named enum into scope.
+      scop.insert(symbol, symbol.ident);
+      // Create new scope.
+      scop = scop.push(symbol);
+    }
+    // Semantic on members.
+    foreach (member; members)
+    {
+      auto value = member.value;
+      if (value)
+      {
+        // value = value.semantic(scop);
+        // value = value.evaluate();
+      }
+      auto variable = new Variable(StorageClass.Const, LinkageType.None, type, member.name, member);
+      scop.insert(variable, variable.ident);
+    }
+    if (name)
+      scop.pop();
+    +/
+  }
 }
 
 class EnumMember : Node
@@ -530,6 +597,7 @@
       if (values[i])
         values[i] = values[i].semantic(scop);
       // Create a new variable symbol.
+      // TODO: pass 'prot' to constructor.
       auto variable = new Variable(stc, linkageType, type, ident, this);
       variables ~= variable;
       // Add to scope.
@@ -768,16 +836,16 @@
 
 class MixinDeclaration : Declaration
 {
-  Expression[] templateIdents;
+  Expression templateExpr;
   Identifier* mixinIdent;
   Expression argument; // mixin ( AssignExpression )
 
-  this(Expression[] templateIdents, Identifier* mixinIdent)
+  this(Expression templateExpr, Identifier* mixinIdent)
   {
     mixin(set_kind);
-    addChildren(templateIdents);
+    addChild(templateExpr);
 
-    this.templateIdents = templateIdents;
+    this.templateExpr = templateExpr;
     this.mixinIdent = mixinIdent;
   }
 
--- a/trunk/src/dil/ast/Expressions.d	Thu Jan 10 19:47:34 2008 +0100
+++ b/trunk/src/dil/ast/Expressions.d	Fri Jan 11 00:42:35 2008 +0100
@@ -374,6 +374,20 @@
   }
 }
 
+/// DotExpression := Expression '.' Expression
+class DotExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+
+/*++++++++++++++++++++
++ Unary Expressions: +
+++++++++++++++++++++*/
+
 abstract class UnaryExpression : Expression
 {
   Expression e;
@@ -464,41 +478,6 @@
     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);
-    addChild(dotList);
-    this.dotList = dotList;
-  }
-}
 
 class CallExpression : UnaryExpression
 {
@@ -601,12 +580,22 @@
   }
 }
 
-/*
-class PrimaryExpression
+/// Module scope operator: '.' (IdentifierExpression|TemplateInstanceExpression)
+class ModuleScopeExpression : UnaryExpression
 {
-
+  this(Expression e)
+  {
+    super(e);
+    assert(e.kind == NodeKind.IdentifierExpression ||
+           e.kind == NodeKind.TemplateInstanceExpression
+    );
+    mixin(set_kind);
+  }
 }
-*/
+
+/*++++++++++++++++++++++
++ Primary Expressions: +
+++++++++++++++++++++++*/
 
 class IdentifierExpression : Expression
 {
@@ -649,36 +638,6 @@
   }
 }
 
-/*
-class IdentifierListExpression : Expression
-{
-  Expression[] identList;
-  this(Expression[] identList)
-  {
-    this.identList = identList;
-  }
-}
-*/
-
-class DotExpression : Expression
-{
-  this()
-  {
-    mixin(set_kind);
-  }
-}
-
-class DotListExpression : Expression
-{
-  Expression[] items;
-  this(Expression[] items)
-  {
-    mixin(set_kind);
-    addChildren(items);
-    this.items = items;
-  }
-}
-
 class TemplateInstanceExpression : Expression
 {
   Identifier* ident;
--- a/trunk/src/dil/ast/Node.d	Thu Jan 10 19:47:34 2008 +0100
+++ b/trunk/src/dil/ast/Node.d	Fri Jan 11 00:42:35 2008 +0100
@@ -143,7 +143,6 @@
   SignExpression,
   NotExpression,
   CompExpression,
-  PostDotListExpression,
   CallExpression,
   NewExpression,
   NewAnonClassExpression,
@@ -151,11 +150,10 @@
   CastExpression,
   IndexExpression,
   SliceExpression,
-  PrimaryExpressio,
+  ModuleScopeExpression,
   IdentifierExpression,
   SpecialTokenExpression,
   DotExpression,
-  DotListExpression,
   TemplateInstanceExpression,
   ThisExpression,
   SuperExpression,
@@ -190,10 +188,10 @@
   AsmRegisterExpression,
 
   // Types:
+  UndefinedType,
   IntegralType,
-  UndefinedType,
-  DotType,
-  DotListType,
+  QualifiedType,
+  ModuleScopeType,
   IdentifierType,
   TypeofType,
   TemplateInstanceType,
@@ -316,11 +314,15 @@
       if (token.type == TOK.LBrace ||
           token.type == TOK.RBrace ||
           token.type == TOK.Semicolon ||
-          token.type == TOK.HEAD)
+          token.type == TOK.HEAD ||
+          (kind == NodeKind.EnumMember && token.type == TOK.Comma))
         break;
+
       if (token.type == TOK.Comment)
       {
         // Check that this comment doesn't belong to the previous declaration.
+        if (kind == NodeKind.EnumMember && token.type == TOK.Comma)
+          break;
         switch (token.prev.type)
         {
         case TOK.Semicolon, TOK.RBrace:
@@ -333,9 +335,18 @@
     }
     // Get single comment to the right.
     token = end.next;
-    if (token.type == TOK.Comment &&
-        isDocComment(token))
-        comments ~= token;
+    if (token.type == TOK.Comment && isDocComment(token))
+      comments ~= token;
+    else if (kind == NodeKind.EnumMember)
+    {
+      token = end.nextNWS;
+      if (token.type == TOK.Comma)
+      {
+        token = token.next;
+        if (token.type == TOK.Comment && isDocComment(token))
+          comments ~= token;
+      }
+    }
     return comments;
   }
 }
--- a/trunk/src/dil/ast/Statements.d	Thu Jan 10 19:47:34 2008 +0100
+++ b/trunk/src/dil/ast/Statements.d	Fri Jan 11 00:42:35 2008 +0100
@@ -498,13 +498,13 @@
 
 class MixinStatement : Statement
 {
-  Expression[] templateIdents;
+  Expression templateExpr;
   Identifier* mixinIdent;
-  this(Expression[] templateIdents, Identifier* mixinIdent)
+  this(Expression templateExpr, Identifier* mixinIdent)
   {
     mixin(set_kind);
-    addChildren(templateIdents);
-    this.templateIdents = templateIdents;
+    addChild(templateExpr);
+    this.templateExpr = templateExpr;
     this.mixinIdent = mixinIdent;
   }
 }
--- a/trunk/src/dil/ast/Types.d	Thu Jan 10 19:47:34 2008 +0100
+++ b/trunk/src/dil/ast/Types.d	Fri Jan 11 00:42:35 2008 +0100
@@ -45,8 +45,8 @@
   Pointer,
   CFuncPointer,
   Array,
-  Dot,
-  DotList,
+  Qualified,
+  ModuleScope,
   Identifier,
   Typeof,
   TemplateInstance,
@@ -78,15 +78,6 @@
   }
 }
 
-class IntegralType : TypeNode
-{
-  this(TOK tok)
-  {
-    super(cast(TID)tok);
-    mixin(set_kind);
-  }
-}
-
 class UndefinedType : TypeNode
 {
   this()
@@ -96,15 +87,12 @@
   }
 }
 
-class DotListType : TypeNode
+class IntegralType : TypeNode
 {
-  TypeNode[] dotList;
-  this(TypeNode[] dotList)
+  this(TOK tok)
   {
-    super(TID.DotList);
+    super(cast(TID)tok);
     mixin(set_kind);
-    addChildren(dotList);
-    this.dotList = dotList;
   }
 }
 
@@ -119,11 +107,22 @@
   }
 }
 
-class DotType : TypeNode
+class QualifiedType : TypeNode
 {
-  this()
+  alias next left;
+  TypeNode right;
+  this(TypeNode left, TypeNode right)
   {
-    super(TID.Dot);
+    super(TID.Qualified, left);
+    addChild(right);
+  }
+}
+
+class ModuleScopeType : TypeNode
+{
+  this(TypeNode next)
+  {
+    super(TID.ModuleScope, next);
     mixin(set_kind);
   }
 }
--- a/trunk/src/dil/lexer/IdTable.d	Thu Jan 10 19:47:34 2008 +0100
+++ b/trunk/src/dil/lexer/IdTable.d	Fri Jan 11 00:42:35 2008 +0100
@@ -127,6 +127,18 @@
     }
   }
   +/
+
+  static uint anonCount;
+  Identifier* genAnonymousID(char[] str)
+  {
+    ++anonCount;
+    auto x = anonCount;
+    // Convert count to a string and append it to str.
+    do
+      str = cast(char)('0' + (x % 10)) ~ str;
+    while (x /= 10)
+    return Identifier(str, TOK.Identifier);
+  }
 }
 
 unittest
--- a/trunk/src/dil/parser/Parser.d	Thu Jan 10 19:47:34 2008 +0100
+++ b/trunk/src/dil/parser/Parser.d	Fri Jan 11 00:42:35 2008 +0100
@@ -1372,6 +1372,7 @@
   Type parseTypeofType()
   {
     assert(token.type == T.Typeof);
+    auto begin = token;
     Type type;
     requireNext(T.LParen);
     switch (token.type)
@@ -1387,117 +1388,10 @@
       type = new TypeofType(parseExpression());
     }
     require(T.RParen);
+    set(type, begin);
     return type;
   }
 
-  /+
-    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);
-    auto begin = token;
-    Expression[] identList;
-    if (skipped(T.Dot))
-      identList ~= set(new DotExpression(), begin);
-    else if (token.type == T.Typeof)
-    {
-      auto type = parseTypeofType();
-      set(type, begin);
-      identList ~= set(new TypeofExpression(type), begin);
-      if (!skipped(T.Dot))
-        goto Lreturn;
-    }
-
-    while (1)
-    {
-      begin = token;
-      auto ident = requireIdentifier(MSG.ExpectedAnIdentifier);
-      Expression e;
-      if (token.type == T.Not && peekNext() == T.LParen) // Identifier !( TemplateArguments )
-      {
-        nT(); // Skip !.
-        auto tparams = parseTemplateArguments();
-        e = new TemplateInstanceExpression(ident, tparams);
-      }
-      else // Identifier
-        e = new IdentifierExpression(ident);
-
-      identList ~= set(e, begin);
-
-    LnewExpressionLoop:
-      if (!skipped(T.Dot))
-        break;
-
-      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()
-  {
-    auto begin = token;
-    Type[] identList;
-    if (skipped(T.Dot))
-      identList ~= set(new DotType(), begin);
-    else if (token.type == T.Typeof)
-    {
-      identList ~= set(parseTypeofType(), begin);
-      if (!skipped(T.Dot))
-        goto Lreturn;
-    }
-
-    do
-    {
-      begin = token;
-      auto ident = requireIdentifier(MSG.ExpectedAnIdentifier);
-      Type t;
-      // NB.: Currently Types can't be followed by "!="
-      // so no need to peek for "(" when parsing TemplateInstances.
-      if (skipped(T.Not)/+ && peekNext() == T.LParen+/) // Identifier !( TemplateArguments )
-        t = new TemplateInstanceType(ident, parseTemplateArguments());
-      else // Identifier
-        t = new IdentifierType(ident);
-      identList ~= set(t, begin);
-    } while(skipped(T.Dot))
-  Lreturn:
-    return new DotListType(identList);
-  }
-
   /*
     TemplateMixin:
             mixin ( AssignExpression ) ;
@@ -1524,33 +1418,21 @@
   }
 
     auto begin = token;
-    Expression[] templateIdent;
+    Expression e;
     Identifier* mixinIdent;
 
-    // This code is similar to parseDotListType().
     if (skipped(T.Dot))
-      templateIdent ~= set(new DotExpression(), begin);
-
-    do
-    {
-      begin = token;
-      auto ident = requireIdentifier(MSG.ExpectedAnIdentifier);
-      Expression e;
-      if (skipped(T.Not)) // Identifier !( TemplateArguments )
-      {
-        // No need to peek for T.LParen. This must be a template instance.
-        auto tparams = parseTemplateArguments();
-        e = new TemplateInstanceExpression(ident, tparams);
-      }
-      else // Identifier
-        e = new IdentifierExpression(ident);
-      templateIdent ~= set(e, begin);
-    } while (skipped(T.Dot))
+      e = set(new ModuleScopeExpression(parseIdentifierExpression()), begin);
+    else
+      e = parseIdentifierExpression();
+
+    while (skipped(T.Dot))
+      e = set(new DotExpression(e, parseIdentifierExpression()), begin);
 
     mixinIdent = optionalIdentifier();
     require(T.Semicolon);
 
-    return new Class(templateIdent, mixinIdent);
+    return new Class(e, mixinIdent);
   }
 
   /+++++++++++++++++++++++++++++
@@ -2736,6 +2618,11 @@
     case T.Tilde:
       nT();
       e = new CompExpression(parseAsmUnaryExpression());
+      break;
+    case T.Dot:
+      nT();
+      e = new ModuleScopeExpression(parseIdentifierExpression());
+      break;
     default:
     LparseAsmPrimaryExpression:
       e = parseAsmPrimaryExpression();
@@ -2827,21 +2714,13 @@
         e = new AsmRegisterExpression(register);
         break;
       default:
-        // DotIdentifier
-        Expression[] identList;
-        while (1)
+        e = parseIdentifierExpression();
+        while (skipped(TOK.Dot))
         {
-          auto begin2 = token;
-          auto ident = requireIdentifier(MSG.ExpectedAnIdentifier);
-          e = new IdentifierExpression(ident);
-          set(e, begin2);
-          identList ~= e;
-          if (token.type != T.Dot)
-            break;
-          nT(); // Skip dot.
+          e = new DotExpression(e, parseIdentifierExpression());
+          set(e, begin);
         }
-        e = new DotListExpression(identList);
-      }
+      } // end of switch
       break;
     default:
       error(MID.ExpectedButFound, "Expression", token.srcText);
@@ -3130,11 +3009,14 @@
     auto e = parseUnaryExpression();
     while (1)
     {
+      while (skipped(T.Dot))
+      {
+        e = new DotExpression(e, parseNewOrIdentifierExpression());
+        set(e, begin);
+      }
+
       switch (token.type)
       {
-      case T.Dot:
-        e = new PostDotListExpression(e, parseDotListExpression());
-        goto Lset;
       case T.PlusPlus:
         e = new PostIncrExpression(e);
         break;
@@ -3266,6 +3148,10 @@
         break;
       }
       goto default;
+    case T.Dot:
+      nT();
+      e = new ModuleScopeExpression(parseIdentifierExpression());
+      break;
     default:
       e = parsePrimaryExpression();
       return e;
@@ -3275,14 +3161,45 @@
     return e;
   }
 
+  /++
+    IdentifierExpression:
+            Identifier
+            TemplateInstance
+    TemplateInstance:
+            Identifier !( TemplateArguments )
+  +/
+  Expression parseIdentifierExpression()
+  {
+    auto begin = token;
+    auto ident = requireIdentifier(MSG.ExpectedAnIdentifier);
+    Expression e;
+    if (token.type == T.Not && peekNext() == T.LParen)
+    { // Identifier !( TemplateArguments )
+      nT(); // Skip !.
+      auto tparams = parseTemplateArguments();
+      e = new TemplateInstanceExpression(ident, tparams);
+    }
+    else // Identifier
+      e = new IdentifierExpression(ident);
+    return set(e, begin);
+  }
+
+  Expression parseNewOrIdentifierExpression()
+  {
+    return token.type == T.New ? parseNewExpression() :  parseIdentifierExpression();
+  }
+
   Expression parsePrimaryExpression()
   {
     auto begin = token;
     Expression e;
     switch (token.type)
     {
-    case T.Identifier, T.Dot, T.Typeof:
-      e = parseDotListExpression();
+    case T.Identifier:
+      e = parseIdentifierExpression();
+      return e;
+    case T.Typeof:
+      e = new TypeofExpression(parseTypeofType());
       break;
     case T.This:
       nT();
@@ -3564,6 +3481,38 @@
     return parseBasicType2(parseBasicType());
   }
 
+  Type parseIdentifierType()
+  {
+    auto begin = token;
+    auto ident = requireIdentifier(MSG.ExpectedAnIdentifier);
+    Type t;
+    if (skipped(T.Not)) // Identifier !( TemplateArguments )
+      t = new TemplateInstanceType(ident, parseTemplateArguments());
+    else // Identifier
+      t = new IdentifierType(ident);
+    return set(t, begin);
+  }
+
+  Type parseQualifiedType()
+  {
+    auto begin = token;
+    Type type;
+    if (skipped(T.Dot))
+      type = set(new ModuleScopeType(parseIdentifierType()), begin);
+    else if (token.type == T.Typeof)
+    {
+      type = parseTypeofType();
+      if (token.type != T.Dot)
+        return type;
+    }
+    else
+      type = parseIdentifierType();
+
+    while (skipped(T.Dot))
+      type = set(new QualifiedType(type, parseIdentifierType()), begin);
+    return type;
+  }
+
   Type parseBasicType()
   {
     auto begin = token;
@@ -3578,9 +3527,8 @@
     switch (token.type)
     {
     case T.Identifier, T.Typeof, T.Dot:
-      t = parseDotListType();
-      assert(!isNodeSet(t));
-      break;
+      t = parseQualifiedType();
+      return t;
     version(D2)
     {
     case T.Const:
--- a/trunk/src/main.d	Thu Jan 10 19:47:34 2008 +0100
+++ b/trunk/src/main.d	Fri Jan 11 00:42:35 2008 +0100
@@ -5,16 +5,20 @@
 module main;
 
 import dil.parser.Parser;
-import dil.lexer.Lexer;
-import dil.lexer.Token;
+import dil.lexer.Lexer,
+       dil.lexer.Token;
+import dil.ast.Declarations,
+       dil.ast.Expressions,
+       dil.ast.Node;
 import dil.Messages;
 import dil.Settings;
 import dil.SettingsLoader;
 import dil.CompilerInfo;
 import dil.semantic.Module;
-import dil.ast.Declarations, dil.ast.Expressions, dil.ast.Node;
 import dil.Information;
 import dil.File;
+import dil.semantic.Symbols;
+
 import cmd.Generate;
 import cmd.Statistics;
 import cmd.ImportGraph;
@@ -48,6 +52,20 @@
       mod.parse();
       // Start semantic analysis.
       mod.semantic();
+
+      void printSymbolTable(ScopeSymbol scopeSym)
+      {
+        foreach (member; scopeSym.members)
+        {
+          auto tokens = member.node.getDocComments();
+          char[] docText;
+          foreach (token; tokens)
+            docText ~= token.srcText;
+          Stdout.formatln("Id:{}, Symbol:{}, DocText:{}", member.ident.str, member.classinfo.name, docText);
+        }
+      }
+
+      printSymbolTable(mod);
     }
 
     foreach (info; infoMan.info)