changeset 492:9c208925a3d4

Added module ImportParser and new stuff from DMD2.008. Moved ImportParser from module Parser to its own module. Added a few methods from class Parser and simplified them. Now protection attributes are taken into consideration as well. Added class TemplateThisParameter. Adapted TypeofType so that typeof(return) can be recognized.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Thu, 06 Dec 2007 22:19:55 +0100
parents b991f49628a8
children d13502b6fa5f
files trunk/src/dil/Declarations.d trunk/src/dil/ImportParser.d trunk/src/dil/Module.d trunk/src/dil/Parser.d trunk/src/dil/SyntaxTree.d trunk/src/dil/Types.d
diffstat 6 files changed, 466 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/src/dil/Declarations.d	Tue Dec 04 23:33:13 2007 +0100
+++ b/trunk/src/dil/Declarations.d	Thu Dec 06 22:19:55 2007 +0100
@@ -349,7 +349,8 @@
   TemplateParameters tparams;
   Parameters params;
   FunctionBody funcBody;
-  this(Type returnType, Token* funcName, TemplateParameters tparams, Parameters params, FunctionBody funcBody)
+  this(Type returnType, Token* funcName, TemplateParameters tparams,
+       Parameters params, FunctionBody funcBody, StorageClass stc)
   {
     super.hasBody = funcBody.funcBody !is null;
     mixin(set_kind);
@@ -358,6 +359,7 @@
     addChild(params);
     addChild(funcBody);
 
+    this.stc = stc;
     this.returnType = returnType;
     this.funcName = funcName;
     this.tparams = tparams;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/ImportParser.d	Thu Dec 06 22:19:55 2007 +0100
@@ -0,0 +1,375 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module dil.ImportParser;
+import dil.Parser;
+import dil.Token;
+import dil.Enums;
+import dil.Declarations;
+import dil.Statements;
+import dil.SyntaxTree;
+import common;
+
+private alias TOK T;
+
+class ImportParser : Parser
+{
+  this(char[] srcText, string fileName)
+  {
+    super(srcText, fileName);
+  }
+
+  override Declarations start()
+  {
+    auto decls = new Declarations;
+    super.init();
+    if (token.type == T.Module)
+      decls ~= parseModuleDeclaration();
+    while (token.type != T.EOF)
+      parseDeclarationDefinition(Protection.None);
+    return decls;
+  }
+
+  void parseDeclarationDefinitionsBlock(Protection prot)
+  {
+    skip(T.LBrace);
+    while (token.type != T.RBrace && token.type != T.EOF)
+      parseDeclarationDefinition(prot);
+    skip(T.RBrace);
+  }
+
+  void parseDeclarationsBlock(Protection prot)
+  {
+    switch (token.type)
+    {
+    case T.LBrace:
+      parseDeclarationDefinitionsBlock(prot);
+      break;
+    case T.Colon:
+      nT();
+      while (token.type != T.RBrace && token.type != T.EOF)
+        parseDeclarationDefinition(prot);
+      break;
+    default:
+      parseDeclarationDefinition(prot);
+    }
+  }
+
+  bool skipToClosing(T opening, T closing)
+  {
+    Token* next = token;
+    uint level = 1;
+    while (1)
+    {
+      lx.peek(next);
+      if (next.type == opening)
+        ++level;
+      else if (next.type == closing && --level == 0)
+        return true;
+      else if (next.type == T.EOF)
+        break;
+    }
+    return false;
+  }
+
+  void skipToTokenAfterClosingParen()
+  {
+    skipToClosing(T.LParen, T.RParen);
+    nT();
+  }
+
+  void skipToTokenAfterClosingBrace()
+  {
+    skipToClosing(T.LBrace, T.RBrace);
+    nT();
+  }
+
+  void skip(TOK tok)
+  {
+    token.type == tok && nT();
+  }
+
+  void parseProtectionAttribute()
+  {
+    Protection prot;
+    switch (token.type)
+    {
+    case T.Private:
+      prot = Protection.Private; break;
+    case T.Package:
+      prot = Protection.Package; break;
+    case T.Protected:
+      prot = Protection.Protected; break;
+    case T.Public:
+      prot = Protection.Public; break;
+    case T.Export:
+      prot = Protection.Export; break;
+    default:
+      assert(0);
+    }
+    nT();
+    parseDeclarationsBlock(prot);
+  }
+
+  void parseDeclarationDefinition(Protection prot)
+  {
+    switch (token.type)
+    {
+    case T.Align:
+      nT();
+      if (token.type == T.LParen)
+        nT(), nT(), nT(); // ( Integer )
+      parseDeclarationsBlock(prot);
+      break;
+    case T.Pragma:
+      nT();
+      skipToTokenAfterClosingParen();
+      parseDeclarationsBlock(prot);
+      break;
+    case T.Export,
+         T.Private,
+         T.Package,
+         T.Protected,
+         T.Public:
+      parseProtectionAttribute();
+      break;
+    // Storage classes
+    case T.Extern:
+      nT();
+      token.type == T.LParen && skipToTokenAfterClosingParen();
+      parseDeclarationsBlock(prot);
+      break;
+    case T.Const:
+    version(D2)
+    {
+      if (peekNext() == T.LParen)
+        goto case_Declaration;
+    }
+    case T.Override,
+         T.Deprecated,
+         T.Abstract,
+         T.Synchronized,
+         // T.Static,
+         T.Final,
+         T.Auto,
+         T.Scope:
+    case_StaticAttribute:
+    case_InvariantAttribute:
+      nT();
+      parseDeclarationsBlock(prot);
+      break;
+    // End of storage classes.
+    case T.Alias, T.Typedef:
+      nT();
+      goto case_Declaration;
+    case T.Static:
+      switch (peekNext())
+      {
+      case T.Import:
+        goto case_Import;
+      case T.This:
+        nT(), nT(); // static this
+        skipToTokenAfterClosingParen();
+        parseFunctionBody();
+        break;
+      case T.Tilde:
+        nT(), nT(), nT(), nT(), nT(); // static ~ this ( )
+        parseFunctionBody();
+        break;
+      case T.If:
+        nT(), nT();
+        skipToTokenAfterClosingParen();
+        parseDeclarationsBlock(prot);
+        if (token.type == T.Else)
+          nT(), parseDeclarationsBlock(prot);
+        break;
+      case T.Assert:
+        nT(), nT(); // static assert
+        skipToTokenAfterClosingParen();
+        skip(T.Semicolon);
+        break;
+      default:
+        goto case_StaticAttribute;
+      }
+      break;
+    case T.Import:
+    case_Import:
+      auto decl = parseImportDeclaration();
+      assert(decl && decl.kind == NodeKind.ImportDeclaration);
+      decl.prot = prot; // Set the protection attribute.
+      imports ~= cast(ImportDeclaration)cast(void*)decl;
+      break;
+    case T.Enum:
+      nT();
+      token.type == T.Identifier && nT();
+      if (token.type == T.Colon)
+      {
+        nT();
+        while (token.type != T.LBrace && token.type != T.EOF)
+          nT();
+      }
+      if (token.type == T.Semicolon)
+        nT();
+      else
+        skipToTokenAfterClosingBrace();
+      break;
+    case T.Class:
+    case T.Interface:
+      nT(), skip(T.Identifier); // class Identifier
+      token.type == T.LParen && skipToTokenAfterClosingParen(); // Skip template params.
+      if (token.type == T.Colon)
+      { // BaseClasses
+        nT();
+        while (token.type != T.LBrace && token.type != T.EOF)
+          if (token.type == T.LParen) // Skip ( tokens... )
+            skipToTokenAfterClosingParen();
+          else
+            nT();
+      }
+      if (token.type == T.Semicolon)
+        nT();
+      else
+        parseDeclarationDefinitionsBlock(Protection.None);
+      break;
+    case T.Struct, T.Union:
+      nT(); skip(T.Identifier);
+      token.type == T.LParen && skipToTokenAfterClosingParen();
+      if (token.type == T.Semicolon)
+        nT();
+      else
+        parseDeclarationDefinitionsBlock(Protection.None);
+      break;
+    case T.Tilde:
+      nT(); // ~
+    case T.This:
+      nT(); nT(); nT(); // this ( )
+      parseFunctionBody();
+      break;
+    case T.Invariant:
+    version(D2)
+    {
+      auto next = token;
+      if (peekAfter(next) == T.LParen)
+      {
+        if (peekAfter(next) != T.RParen)
+          goto case_Declaration;
+      }
+      else
+        goto case_InvariantAttribute;
+    }
+      token.type == T.LParen && skipToTokenAfterClosingParen();
+      parseFunctionBody();
+      break;
+    case T.Unittest:
+      nT();
+      parseFunctionBody();
+      break;
+    case T.Debug:
+      nT();
+      if (token.type == T.Assign)
+      {
+        nT(), nT(), nT(); // = Condition ;
+        break;
+      }
+      if (token.type == T.LParen)
+        nT(), nT(), nT(); // ( Condition )
+      parseDeclarationsBlock(prot);
+      if (token.type == T.Else)
+        nT(), parseDeclarationsBlock(prot);
+      break;
+    case T.Version:
+      nT();
+      if (token.type == T.Assign)
+      {
+        nT(), nT(), nT(); // = Condition ;
+        break;
+      }
+      nT(), nT(), nT(); // ( Condition )
+      parseDeclarationsBlock(prot);
+      if (token.type == T.Else)
+        nT(), parseDeclarationsBlock(prot);
+      break;
+    case T.Template:
+      nT();
+      skip(T.Identifier);
+      skipToTokenAfterClosingParen();
+      parseDeclarationDefinitionsBlock(Protection.None);
+      break;
+    case T.New:
+      nT();
+      skipToTokenAfterClosingParen();
+      parseFunctionBody();
+      break;
+    case T.Delete:
+      nT();
+      skipToTokenAfterClosingParen();
+      parseFunctionBody();
+      break;
+    case T.Mixin:
+      while (token.type != T.Semicolon && token.type != T.EOF)
+        if (token.type == T.LParen)
+          skipToTokenAfterClosingParen();
+        else
+          nT();
+      skip(T.Semicolon);
+      break;
+    case T.Semicolon:
+      nT();
+      break;
+    // Declaration
+    case T.Identifier, T.Dot, T.Typeof:
+    // IntegralType
+    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:
+      while (token.type != T.Semicolon && token.type != T.EOF)
+        if (token.type == T.LParen)
+          skipToTokenAfterClosingParen();
+        else if (token.type == T.LBrace)
+          skipToTokenAfterClosingBrace();
+        else
+          nT();
+      skip(T.Semicolon);
+      break;
+    default:
+      nT();
+    }
+  }
+
+  FunctionBody parseFunctionBody()
+  {
+    while (1)
+    {
+      switch (token.type)
+      {
+      case T.LBrace:
+        skipToTokenAfterClosingBrace();
+        break;
+      case T.Semicolon:
+        nT();
+        break;
+      case T.In:
+        nT();
+        skipToTokenAfterClosingBrace();
+        continue;
+      case T.Out:
+        nT();
+        if (token.type == T.LParen)
+          nT(), nT(), nT(); // ( Identifier )
+        skipToTokenAfterClosingBrace();
+        continue;
+      case T.Body:
+        nT();
+        goto case T.LBrace;
+      default:
+      }
+      break; // Exit loop.
+    }
+    return null;
+  }
+}
--- a/trunk/src/dil/Module.d	Tue Dec 04 23:33:13 2007 +0100
+++ b/trunk/src/dil/Module.d	Thu Dec 06 22:19:55 2007 +0100
@@ -6,6 +6,7 @@
 import dil.SyntaxTree;
 import dil.Declarations;
 import dil.Parser;
+import dil.ImportParser;
 import dil.Lexer;
 import dil.File;
 import tango.io.FilePath;
@@ -28,7 +29,7 @@
 
   Module[] modules;
 
-  this(string filePath, bool isLight = false)
+  this(string filePath, bool isLightweight = false)
   {
     this.filePath = filePath;
     this.isLightweight = isLightweight;
--- a/trunk/src/dil/Parser.d	Tue Dec 04 23:33:13 2007 +0100
+++ b/trunk/src/dil/Parser.d	Thu Dec 06 22:19:55 2007 +0100
@@ -17,35 +17,10 @@
 
 private alias TOK T;
 
-class ImportParser : Parser
-{
-  this(char[] srcText, string fileName)
-  {
-    super(srcText, fileName);
-  }
-
-  override Declarations start()
-  {
-    auto decls = new Declarations;
-    super.init();
-    if (token.type == T.Module)
-      decls ~= parseModuleDeclaration();
-    while (token.type != T.EOF)
-    {
-      if (token.type == T.Import)
-      {
-        auto decl = parseImportDeclaration();
-        assert(decl && decl.kind == NodeKind.ImportDeclaration);
-        super.imports ~= cast(ImportDeclaration)cast(void*)decl;
-        decls ~= decl;
-      }
-      else
-        nT();
-    }
-    return decls;
-  }
-}
-
+/++
+  The Parser produces an abstract syntax tree (AST) by analyzing
+  the tokens of the provided source code.
++/
 class Parser
 {
   Lexer lx;
@@ -61,7 +36,7 @@
     lx = new Lexer(srcText, filePath);
   }
 
-  private void init()
+  protected void init()
   {
     nT();
     prevToken = token;
@@ -452,9 +427,24 @@
           }
 
           auto params = parseParameterList();
+        version(D2)
+        {
+          switch (token.type)
+          {
+          case T.Const:
+            stc |= StorageClass.Const;
+            nT();
+            break;
+          case T.Invariant:
+            stc |= StorageClass.Invariant;
+            nT();
+            break;
+          default:
+          }
+        }
           // ReturnType FunctionName ( ParameterList )
           auto funcBody = parseFunctionBody();
-          return set(new FunctionDeclaration(type, ident, tparams, params, funcBody), begin);
+          return set(new FunctionDeclaration(type, ident, tparams, params, funcBody, stc), begin);
         }
         type = parseDeclaratorSuffix(type);
       }
@@ -1420,6 +1410,27 @@
     return new DeleteDeclaration(parameters, funcBody);
   }
 
+  Type parseTypeofType()
+  {
+    assert(token.type == T.Typeof);
+    Type type;
+    requireNext(T.LParen);
+    switch (token.type)
+    {
+    version(D2)
+    {
+    case T.Return:
+      nT();
+      type = new TypeofType();
+      break;
+    }
+    default:
+      type = new TypeofType(parseExpression());
+    }
+    require(T.RParen);
+    return type;
+  }
+
   /+
     DotListExpression:
             . DotListItems
@@ -1448,9 +1459,7 @@
     }
     else if (token.type == T.Typeof)
     {
-      requireNext(T.LParen);
-      auto type = new TypeofType(parseExpression());
-      require(T.RParen);
+      auto type = parseTypeofType();
       set(type, begin);
       identList ~= set(new TypeofExpression(type), begin);
       if (token.type != T.Dot)
@@ -1515,10 +1524,7 @@
     }
     else if (token.type == T.Typeof)
     {
-      requireNext(T.LParen);
-      auto type = new TypeofType(parseExpression());
-      require(T.RParen);
-      identList ~= set(type, begin);
+      identList ~= set(parseTypeofType(), begin);
       if (token.type != T.Dot)
         goto Lreturn;
       nT();
@@ -4322,6 +4328,17 @@
           goto LTemplateValueParameter;
         }
         break;
+      version(D2)
+      {
+      case T.This:
+        // TemplateThisParameter
+        //         this TemplateTypeParameter
+        nT(); // Skip 'this' keyword.
+        ident = requireId();
+        parseSpecAndOrDefaultType();
+        tp = new TemplateThisParameter(ident, specType, defType);
+        break;
+      }
       default:
       LTemplateValueParameter:
         // TemplateValueParameter:
--- a/trunk/src/dil/SyntaxTree.d	Tue Dec 04 23:33:13 2007 +0100
+++ b/trunk/src/dil/SyntaxTree.d	Thu Dec 06 22:19:55 2007 +0100
@@ -210,6 +210,7 @@
   BaseClass,
   TemplateAliasParameter,
   TemplateTypeParameter,
+  TemplateThisParameter, // D2.0
   TemplateValueParameter,
   TemplateTupleParameter,
   TemplateParameters,
--- a/trunk/src/dil/Types.d	Tue Dec 04 23:33:13 2007 +0100
+++ b/trunk/src/dil/Types.d	Thu Dec 06 22:19:55 2007 +0100
@@ -179,6 +179,24 @@
   }
 }
 
+version(D2)
+{
+class TemplateThisParameter : TemplateParameter
+{
+  Token* ident;
+  Type specType, defType;
+  this(Token* ident, Type specType, Type defType)
+  {
+    mixin(set_kind);
+    addOptChild(specType);
+    addOptChild(defType);
+    this.ident = ident;
+    this.specType = specType;
+    this.defType = defType;
+  }
+}
+}
+
 class TemplateValueParameter : TemplateParameter
 {
   Type valueType;
@@ -354,10 +372,20 @@
   Expression e;
   this(Expression e)
   {
+    this();
+    addChild(e);
+    this.e = e;
+  }
+
+  this()
+  {
     super(TID.Typeof);
     mixin(set_kind);
-    addChild(e);
-    this.e = e;
+  }
+
+  bool isTypeofReturn()
+  {
+    return e is null;
   }
 }