changeset 490:47be6bfe39cd

Refactored code and added new modules. Added ProtectionDeclaration and changed Parser to make use of it. Moved class Location to its own module. Moved some Lexer functions to new module LexerFuncs. Moved Lexer.getLocation() to struct Token. Added methods semantic() and error() to class Expression. Added method error() to class Scope.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Tue, 04 Dec 2007 23:31:20 +0100
parents a7291d3ee9d7
children b991f49628a8
files trunk/src/dil/Declarations.d trunk/src/dil/Expressions.d trunk/src/dil/Information.d trunk/src/dil/Lexer.d trunk/src/dil/LexerFuncs.d trunk/src/dil/Location.d trunk/src/dil/Scope.d trunk/src/dil/SyntaxTree.d trunk/src/dil/Token.d
diffstat 9 files changed, 268 insertions(+), 183 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/src/dil/Declarations.d	Mon Dec 03 22:44:27 2007 +0100
+++ b/trunk/src/dil/Declarations.d	Tue Dec 04 23:31:20 2007 +0100
@@ -20,8 +20,8 @@
   }
 
   // Members relevant to semantic phase.
-  StorageClass stc;
-  Protection prot;
+  StorageClass stc; /// The storage class of this declaration.
+  Protection prot;  /// The protection attribute of this declaration.
 
   void semantic(Scope sc)
   {
@@ -548,6 +548,38 @@
   }
 }
 
+class ProtectionDeclaration : AttributeDeclaration
+{
+  this(Protection prot, Declaration decls)
+  {
+    super(cast(TOK)0, decls);
+    mixin(set_kind);
+    super.prot = prot;
+  }
+
+  void semantic(Scope scop)
+  {
+    /+
+    void traverse(Node[] nodes)
+    {
+      foreach (node; nodes)
+      {
+        if (node.kind == NodeKind.ProtectionDeclaration)
+          break;
+        if (node.category == NodeCategory.Declaration)
+        {
+          auto decl = cast(Declaration)cast(void*)node;
+          decl.prot = this.prot;
+          if (node.children)
+            traverse(node.children);
+        }
+      }
+    }
+    traverse([this.decls]);
+    +/
+  }
+}
+
 class ExternDeclaration : AttributeDeclaration
 {
   Linkage linkage;
--- a/trunk/src/dil/Expressions.d	Mon Dec 03 22:44:27 2007 +0100
+++ b/trunk/src/dil/Expressions.d	Tue Dec 04 23:31:20 2007 +0100
@@ -8,6 +8,7 @@
 import dil.Types;
 import dil.Declarations;
 import dil.Statements;
+import dil.Scope;
 
 abstract class Expression : Node
 {
@@ -15,6 +16,17 @@
   {
     super(NodeCategory.Expression);
   }
+
+  Expression semantic(Scope scop)
+  {
+    return null;
+  }
+
+  import dil.Messages;
+  void error(Scope scop, MID mid)
+  {
+    scop.error(this.begin, mid);
+  }
 }
 
 class EmptyExpression : Expression
@@ -772,6 +784,22 @@
     addChild(expr);
     this.expr = expr;
   }
+
+  // import dil.Parser;
+  Expression semantic(Scope scop)
+  {
+    // TODO:
+    /+
+    auto expr = this.expr.semantic(scop);
+    auto strExpr = Cast!(StringExpression)(expr);
+    // if (strExpr is null)
+    //  error(scop, MID.MixinExpressionMustBeString);
+    auto parser = new Parser(strExpr.getString(), "", scop.infoMan);
+    expr = parser.start2();
+    return expr;
+    +/
+    return null;
+  }
 }
 
 class ImportExpression : Expression
--- a/trunk/src/dil/Information.d	Mon Dec 03 22:44:27 2007 +0100
+++ b/trunk/src/dil/Information.d	Tue Dec 04 23:31:20 2007 +0100
@@ -6,6 +6,8 @@
 import dil.Messages;
 import common;
 
+public import dil.Location;
+
 enum InfoType
 {
   Lexer,
@@ -57,87 +59,3 @@
 {
   Information[] info;
 }
-
-final class Location
-{
-  char[] filePath;
-  size_t lineNum;
-  char* lineBegin, to; // Used to calculate column.
-
-  this(char[] filePath, size_t lineNum)
-  {
-    set(filePath, lineNum);
-  }
-
-  this(char[] filePath, size_t lineNum, char* lineBegin, char* to)
-  {
-    set(filePath, lineNum, lineBegin, to);
-  }
-
-  Location clone()
-  {
-    return new Location(filePath, lineNum, lineBegin, to);
-  }
-
-  void set(char[] filePath, size_t lineNum)
-  {
-    set(filePath, lineNum, null, null);
-  }
-
-  void set(char[] filePath, size_t lineNum, char* lineBegin, char* to)
-  {
-    this.filePath  = filePath;
-    set(lineNum, lineBegin, to);
-  }
-
-  void set(size_t lineNum, char* lineBegin, char* to)
-  {
-    assert(lineBegin !is null && to !is null);
-    assert(lineBegin <= to);
-    this.lineNum   = lineNum;
-    this.lineBegin = lineBegin;
-    this.to        = to;
-  }
-
-  void setFilePath(char[] filePath)
-  {
-    this.filePath = filePath;
-  }
-
-  /++
-    This is a primitive method to count the number of characters in a string.
-    Unicode compound characters and other special characters are not
-    taken into account.
-  +/
-  uint calculateColumn()
-  {
-    uint col;
-    auto p = lineBegin;
-    for (; p <= to; ++p)
-    {
-      assert(delegate ()
-        {
-          const char[3] LS = \u2028;
-          const char[3] PS = \u2029;
-          // Check that there is no newline between p and to.
-          // But 'to' may point to a newline.
-          if (p != to && (*p == '\n' || *p == '\r'))
-            return false;
-          if (to-p >= 2)
-          {
-            if (*p == LS[0] && p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2]))
-              return false;
-          }
-          return true;
-        }() == true
-      );
-
-      // Skip this byte if it is a trail byte of a UTF-8 sequence.
-      if ((*p & 0xC0) == 0x80)
-        continue; // *p == 0b10xx_xxxx
-      // Only count ASCII characters and the first byte of a UTF-8 sequence.
-      ++col;
-    }
-    return col;
-  }
-}
--- a/trunk/src/dil/Lexer.d	Mon Dec 03 22:44:27 2007 +0100
+++ b/trunk/src/dil/Lexer.d	Tue Dec 04 23:31:20 2007 +0100
@@ -18,17 +18,11 @@
 import std.uni;
 import common;
 
-const char[3] LS = \u2028; /// Line separator.
-const char[3] PS = \u2029; /// Paragraph separator.
-const dchar LSd = 0x2028;
-const dchar PSd = 0x2029;
-static assert(LS[0] == PS[0] && LS[1] == PS[1]);
+public import dil.LexerFuncs;
 
 /// U+FFFD = �. Used to replace invalid Unicode characters.
 const dchar REPLACEMENT_CHAR = '\uFFFD';
 
-const uint _Z_ = 26; /// Control+Z
-
 class Lexer
 {
   Token* head;      /// The head of the doubly linked token list.
@@ -206,27 +200,6 @@
     return this.token.type;
   }
 
-  /// Returns true if d is a Unicode line or paragraph separator.
-  static bool isUnicodeNewlineChar(dchar d)
-  {
-    return d == LSd || d == PSd;
-  }
-
-  /// Returns true if p points to a line or paragraph separator.
-  static bool isUnicodeNewline(char* p)
-  {
-    return *p == LS[0] && p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2]);
-  }
-
-  /++
-    Returns true if p points to the start of a Newline.
-    Newline: \n | \r | \r\n | LS | PS
-  +/
-  static bool isNewline(char* p)
-  {
-    return *p == '\n' || *p == '\r' || isUnicodeNewline(p);
-  }
-
   /// Returns true if p points to the last character of a Newline.
   bool isNewlineEnd(char* p)
   {
@@ -240,74 +213,6 @@
   }
 
   /++
-    Returns true if p points to the first character of an EndOfLine.
-    EndOfLine: Newline | 0 | _Z_
-  +/
-  static bool isEndOfLine(char* p)
-  {
-    return isNewline(p) || *p == 0 || *p == _Z_;
-  }
-
-  /++
-    Scans a Newline and sets p one character past it.
-    Returns '\n' if scanned or 0 otherwise.
-  +/
-  static dchar scanNewline(ref char* p)
-  {
-    switch (*p)
-    {
-    case '\r':
-      if (p[1] == '\n')
-        ++p;
-    case '\n':
-      ++p;
-      return '\n';
-    default:
-      if (isUnicodeNewline(p))
-      {
-        ++p; ++p; ++p;
-        return '\n';
-      }
-    }
-    return 0;
-  }
-
-  /// Returns a Location for the given token.
-  static Location getLocation(Token* token)
-  {
-    auto search_t = token.prev;
-    // Find previous newline token.
-    while (search_t.type != TOK.Newline)
-      search_t = search_t.prev;
-    auto filePath  = search_t.filePath;
-    auto lineNum   = search_t.lineNum - search_t.lineNum_hline;
-    auto lineBegin = search_t.end;
-    // Determine actual line begin and line number.
-    while (1)
-    {
-      search_t = search_t.next;
-      if (search_t == token)
-        break;
-      // Multiline tokens must be rescanned for newlines.
-      if (search_t.isMultiline)
-      {
-        auto p = search_t.start, end = search_t.end;
-        while (p != end)
-        {
-          if (Lexer.scanNewline(p) == '\n')
-          {
-            lineBegin = p;
-            ++lineNum;
-          }
-          else
-          ++p;
-        }
-      }
-    }
-    return new Location(filePath, lineNum, lineBegin, token.start);
-  }
-
-  /++
     This is the old scan method.
     TODO: profile old and new to see which one is faster.
   +/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/LexerFuncs.d	Tue Dec 04 23:31:20 2007 +0100
@@ -0,0 +1,67 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module dil.LexerFuncs;
+
+const char[3] LS = \u2028; /// Line separator.
+const char[3] PS = \u2029; /// Paragraph separator.
+const dchar LSd = 0x2028;
+const dchar PSd = 0x2029;
+static assert(LS[0] == PS[0] && LS[1] == PS[1]);
+
+const uint _Z_ = 26; /// Control+Z
+
+/// Returns true if d is a Unicode line or paragraph separator.
+bool isUnicodeNewlineChar(dchar d)
+{
+  return d == LSd || d == PSd;
+}
+
+/// Returns true if p points to a line or paragraph separator.
+bool isUnicodeNewline(char* p)
+{
+  return *p == LS[0] && p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2]);
+}
+
+/++
+  Returns true if p points to the start of a Newline.
+  Newline: \n | \r | \r\n | LS | PS
++/
+bool isNewline(char* p)
+{
+  return *p == '\n' || *p == '\r' || isUnicodeNewline(p);
+}
+
+/++
+  Returns true if p points to the first character of an EndOfLine.
+  EndOfLine: Newline | 0 | _Z_
++/
+bool isEndOfLine(char* p)
+{
+  return isNewline(p) || *p == 0 || *p == _Z_;
+}
+
+/++
+  Scans a Newline and sets p one character past it.
+  Returns '\n' if scanned or 0 otherwise.
++/
+dchar scanNewline(ref char* p)
+{
+  switch (*p)
+  {
+  case '\r':
+    if (p[1] == '\n')
+      ++p;
+  case '\n':
+    ++p;
+    return '\n';
+  default:
+    if (isUnicodeNewline(p))
+    {
+      ++p; ++p; ++p;
+      return '\n';
+    }
+  }
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/Location.d	Tue Dec 04 23:31:20 2007 +0100
@@ -0,0 +1,86 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module dil.Location;
+import dil.LexerFuncs;
+import common;
+
+final class Location
+{
+  char[] filePath;
+  size_t lineNum;
+  char* lineBegin, to; // Used to calculate column.
+
+  this(char[] filePath, size_t lineNum)
+  {
+    set(filePath, lineNum);
+  }
+
+  this(char[] filePath, size_t lineNum, char* lineBegin, char* to)
+  {
+    set(filePath, lineNum, lineBegin, to);
+  }
+
+  Location clone()
+  {
+    return new Location(filePath, lineNum, lineBegin, to);
+  }
+
+  void set(char[] filePath, size_t lineNum)
+  {
+    set(filePath, lineNum, null, null);
+  }
+
+  void set(char[] filePath, size_t lineNum, char* lineBegin, char* to)
+  {
+    this.filePath  = filePath;
+    set(lineNum, lineBegin, to);
+  }
+
+  void set(size_t lineNum, char* lineBegin, char* to)
+  {
+    assert(lineBegin !is null && to !is null);
+    assert(lineBegin <= to);
+    this.lineNum   = lineNum;
+    this.lineBegin = lineBegin;
+    this.to        = to;
+  }
+
+  void setFilePath(char[] filePath)
+  {
+    this.filePath = filePath;
+  }
+
+  /++
+    This is a primitive method to count the number of characters in a string.
+    Unicode compound characters and other special characters are not
+    taken into account.
+  +/
+  uint calculateColumn()
+  {
+    uint col;
+    auto p = lineBegin;
+    for (; p <= to; ++p)
+    {
+      assert(delegate ()
+        {
+          // Check that there is no newline between p and to.
+          // But 'to' may point to a newline.
+          if (p != to && (*p == '\n' || *p == '\r'))
+            return false;
+          if (to-p >= 2 && isUnicodeNewline(p))
+            return false;
+          return true;
+        }() == true
+      );
+
+      // Skip this byte if it is a trail byte of a UTF-8 sequence.
+      if ((*p & 0xC0) == 0x80)
+        continue; // *p == 0b10xx_xxxx
+      // Only count ASCII characters and the first byte of a UTF-8 sequence.
+      ++col;
+    }
+    return col;
+  }
+}
--- a/trunk/src/dil/Scope.d	Mon Dec 03 22:44:27 2007 +0100
+++ b/trunk/src/dil/Scope.d	Tue Dec 04 23:31:20 2007 +0100
@@ -51,4 +51,15 @@
     // delete this;
     return sc;
   }
+
+  import dil.Information;
+  import dil.Messages;
+  import dil.Token;
+  void error(Token* token, MID mid)
+  {
+    auto location = token.getLocation();
+    auto msg = GetMsg(mid);
+    auto error = new Information(InfoType.Semantic, mid, location, msg);
+//     infoMan.add(error);
+  }
 }
--- a/trunk/src/dil/SyntaxTree.d	Mon Dec 03 22:44:27 2007 +0100
+++ b/trunk/src/dil/SyntaxTree.d	Tue Dec 04 23:31:20 2007 +0100
@@ -46,6 +46,7 @@
   NewDeclaration,
   DeleteDeclaration,
   AttributeDeclaration,
+  ProtectionDeclaration,
   ExternDeclaration,
   AlignDeclaration,
   PragmaDeclaration,
--- a/trunk/src/dil/Token.d	Mon Dec 03 22:44:27 2007 +0100
+++ b/trunk/src/dil/Token.d	Tue Dec 04 23:31:20 2007 +0100
@@ -3,9 +3,10 @@
   License: GPL3
 +/
 module dil.Token;
-import common;
+import dil.Location;
 import tango.stdc.stdlib : malloc, free;
 import tango.core.Exception;
+import common;
 
 enum TOK : ushort
 {
@@ -253,6 +254,42 @@
     return type == type2;
   }
 
+  import dil.LexerFuncs;
+  /// Returns the Location of this token.
+  Location getLocation()
+  {
+    auto search_t = this.prev;
+    // Find previous newline token.
+    while (search_t.type != TOK.Newline)
+      search_t = search_t.prev;
+    auto filePath  = search_t.filePath;
+    auto lineNum   = search_t.lineNum - search_t.lineNum_hline;
+    auto lineBegin = search_t.end;
+    // Determine actual line begin and line number.
+    while (1)
+    {
+      search_t = search_t.next;
+      if (search_t == this)
+        break;
+      // Multiline tokens must be rescanned for newlines.
+      if (search_t.isMultiline)
+      {
+        auto p = search_t.start, end = search_t.end;
+        while (p != end)
+        {
+          if (scanNewline(p) == '\n')
+          {
+            lineBegin = p;
+            ++lineNum;
+          }
+          else
+            ++p;
+        }
+      }
+    }
+    return new Location(filePath, lineNum, lineBegin, this.start);
+  }
+
   new(size_t size)
   {
     void* p = malloc(size);