changeset 359:511c14950cac

- Added messages MissingLinkageType and UnrecognizedLinkageType. - Changed enum Linkage into a class. - Added method parseLinkage() to Parser. - Added MAX to enum TOK. - Added methods nextNWS() and prevNWS() to Token. - Fixed tokToString table.
author aziz
date Tue, 28 Aug 2007 11:41:00 +0000
parents 0faf57d99c1c
children b6a3755eba94
files trunk/src/dil/Declarations.d trunk/src/dil/Messages.d trunk/src/dil/Parser.d trunk/src/dil/Statements.d trunk/src/dil/SyntaxTree.d trunk/src/dil/Token.d trunk/src/dil/Types.d trunk/src/dil_xml.css trunk/src/lang_de.d trunk/src/lang_en.d trunk/src/lang_tr.d
diffstat 11 files changed, 188 insertions(+), 85 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/src/dil/Declarations.d	Sun Aug 26 15:59:02 2007 +0000
+++ b/trunk/src/dil/Declarations.d	Tue Aug 28 11:41:00 2007 +0000
@@ -473,6 +473,8 @@
   {
     super(TOK.Extern, decls);
     mixin(set_kind);
+    if (linkage)
+      this.children ~= linkage;
     this.linkage = linkage;
   }
 }
--- a/trunk/src/dil/Messages.d	Sun Aug 26 15:59:02 2007 +0000
+++ b/trunk/src/dil/Messages.d	Tue Aug 28 11:41:00 2007 +0000
@@ -60,6 +60,8 @@
   TemplateTupleParameter,
   InContract,
   OutContract,
+  MissingLinkageType,
+  UnrecognizedLinkageType,
 
   // Help messages:
   HelpMain,
--- a/trunk/src/dil/Parser.d	Sun Aug 26 15:59:02 2007 +0000
+++ b/trunk/src/dil/Parser.d	Tue Aug 28 11:41:00 2007 +0000
@@ -535,16 +535,65 @@
     return func;
   }
 
+  Linkage parseLinkage()
+  {
+    if (token.type != T.LParen)
+      return null;
+
+    nT(); // Skip (
+    if (token.type == T.RParen)
+    {
+      error(MID.MissingLinkageType);
+      nT();
+      return null;
+    }
+
+    auto begin = token;
+    auto ident = requireId();
+
+    Linkage.Type linktype;
+    switch (ident ? ident.identifier : null)
+    {
+    case "C":
+      if (token.type == T.PlusPlus)
+      {
+        nT();
+        linktype = Linkage.Type.Cpp;
+        break;
+      }
+      linktype = Linkage.Type.C;
+      break;
+    case "D":
+      linktype = Linkage.Type.D;
+      break;
+    case "Windows":
+      linktype = Linkage.Type.Windows;
+      break;
+    case "Pascal":
+      linktype = Linkage.Type.Pascal;
+      break;
+    case "System":
+      linktype = Linkage.Type.System;
+      break;
+    default:
+      error(MID.UnrecognizedLinkageType, token.srcText);
+      nT();
+    }
+    auto linkage = new Linkage(linktype);
+    set(linkage, begin);
+    require(T.RParen);
+    return linkage;
+  }
+
   Declaration parseStorageAttribute()
   {
     StorageClass stc, tmp;
+    Linkage.Category link_cat;
 
     void addStorageClass()
     {
       if (stc & tmp)
-      {
         error(MID.RedundantStorageClass, token.srcText);
-      }
       else
         stc |= tmp;
     }
@@ -552,46 +601,27 @@
     Declaration parse()
     {
       Declaration decl;
+      auto begin = token;
       switch (token.type)
       {
       case T.Extern:
-        tmp = StorageClass.Extern;
-        addStorageClass();
+        stc |= StorageClass.Extern;
         nT();
-        Linkage linkage = Linkage.Extern;
-        if (token.type == T.LParen)
+        Linkage linkage = parseLinkage();
+
+        // Check for redundancy.
+        Linkage.Category link_cat_tmp = Linkage.getCategory(linkage);
+        if (link_cat & link_cat_tmp)
         {
-          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);
+          char[] srcText = begin.srcText;
+          if (link_cat_tmp == Linkage.Category.MangleSymbol)
+            srcText = begin.start[0 .. prevToken.end - begin.start];
+          error(MID.RedundantStorageClass, srcText);
         }
-        decl = new ExternDeclaration(linkage, parse());
+        else
+          link_cat |= link_cat_tmp;
+
+        decl = set(new ExternDeclaration(linkage, parse()), begin);
         break;
       case T.Override:
         tmp = StorageClass.Override;
@@ -622,6 +652,7 @@
       version(D2)
       {
       case T.Invariant: // D 2.0
+        // TODO: could this be a class invariant?
         if (peekNext() == T.LParen)
           goto case_Declaration;
         tmp = StorageClass.Invariant;
@@ -637,7 +668,7 @@
         addStorageClass();
         auto tok = token.type;
         nT();
-        decl = new AttributeDeclaration(tok, parse());
+        decl = set(new AttributeDeclaration(tok, parse()), begin);
         break;
       case T.Identifier:
       case_Declaration:
@@ -1772,6 +1803,7 @@
   Statement parseAttributeStatement()
   {
     StorageClass stc, tmp;
+    Linkage.Category link_cat;
 
     void addStorageClass()
     {
@@ -1790,42 +1822,22 @@
       switch (token.type)
       {
       case T.Extern:
-        tmp = StorageClass.Extern;
-        addStorageClass();
+        stc |= StorageClass.Extern;
         nT();
-        Linkage linkage = Linkage.Extern;
-        if (token.type == T.LParen)
+        Linkage linkage = parseLinkage();
+
+        // Check for redundancy.
+        Linkage.Category link_cat_tmp = Linkage.getCategory(linkage);
+        if (link_cat & link_cat_tmp)
         {
-          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);
+          char[] srcText = begin.srcText;
+          if (link_cat_tmp == Linkage.Category.MangleSymbol)
+            srcText = begin.start[0 .. prevToken.end - begin.start];
+          error(MID.RedundantStorageClass, srcText);
         }
+        else
+          link_cat |= link_cat_tmp;
+
         s = new ExternStatement(linkage, parse());
         break;
       case T.Static:
--- a/trunk/src/dil/Statements.d	Sun Aug 26 15:59:02 2007 +0000
+++ b/trunk/src/dil/Statements.d	Tue Aug 28 11:41:00 2007 +0000
@@ -549,6 +549,7 @@
   this(TOK tok, Statement statement)
   {
     mixin(set_kind);
+    assert(statement !is null);
     this.children = [statement];
     this.tok = tok;
     this.statement = statement;
@@ -562,6 +563,8 @@
   {
     super(TOK.Extern, statement);
     mixin(set_kind);
+    if (linkage)
+      this.children ~= linkage;
     this.linkage = linkage;
   }
 }
--- a/trunk/src/dil/SyntaxTree.d	Sun Aug 26 15:59:02 2007 +0000
+++ b/trunk/src/dil/SyntaxTree.d	Tue Aug 28 11:41:00 2007 +0000
@@ -208,6 +208,7 @@
   TemplateTupleParameter,
   TemplateParameters,
   TemplateArguments,
+  Linkage,
 }
 
 /// This string is mixed into the constructor of a class that inherits from Node.
--- a/trunk/src/dil/Token.d	Sun Aug 26 15:59:02 2007 +0000
+++ b/trunk/src/dil/Token.d	Tue Aug 28 11:41:00 2007 +0000
@@ -36,7 +36,7 @@
   VENDOR,
   VERSION,
 
-  // Numbers
+  // Number literals
   Int32, Int64, Uint32, Uint64,
   // Floating point number scanner relies on this order. (FloatXY + 3 == ImaginaryXY)
   Float32, Float64, Float80,
@@ -107,7 +107,8 @@
   Ushort,Version,Void,Volatile,Wchar,While,With,
 
   HEAD, // start of linked list
-  EOF
+  EOF,
+  MAX
 }
 
 alias TOK.Abstract KeywordsBegin;
@@ -153,6 +154,38 @@
     return start[0 .. end - start];
   }
 
+  /// Find next non-whitespace token. Returns 'this' token if the next token is TOK.EOF or null.
+  Token* nextNWS()
+  out(token)
+  {
+    assert(token !is null);
+  }
+  body
+  {
+    auto token = next;
+    while (token !is null && token.isWhitespace)
+      token = token.next;
+    if (token is null || token.type == TOK.EOF)
+      return this;
+    return token;
+  }
+
+  /// Find previous non-whitespace token. Returns 'this' token if the previous token is TOK.HEAD or null.
+  Token* prevNWS()
+  out(token)
+  {
+    assert(token !is null);
+  }
+  body
+  {
+    auto token = prev;
+    while (token !is null && token.isWhitespace)
+      token = token.prev;
+    if (token is null || token.type == TOK.HEAD)
+      return this;
+    return token;
+  }
+
   static string toString(TOK tok)
   {
     return tokToString[tok];
@@ -193,18 +226,26 @@
   }
 }
 
-string[] tokToString = [
+const string[] tokToString = [
   "Invalid",
 
   "Comment",
   "#! /shebang/",
   "#line",
+  `"filespec"`,
 
   "Identifier",
   "String",
-  "Special",
   "CharLiteral", "WCharLiteral", "DCharLiteral",
 
+  "__FILE__",
+  "__LINE__",
+  "__DATE__",
+  "__TIME__",
+  "__TIMESTAMP__",
+  "__VENDOR__",
+  "__VERSION__",
+
   "Int32", "Int64", "Uint32", "Uint64",
   "Float32", "Float64", "Float80",
   "Imaginary32", "Imaginary64", "Imaginary80",
@@ -262,9 +303,11 @@
   "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",
+  "template","this","throw","__traits","true","try","typedef","typeid",
   "typeof","ubyte","ucent","uint","ulong","union","unittest",
   "ushort","version","void","volatile","wchar","while","with",
 
+  "HEAD",
   "EOF"
 ];
+static assert(tokToString.length == TOK.MAX);
\ No newline at end of file
--- a/trunk/src/dil/Types.d	Sun Aug 26 15:59:02 2007 +0000
+++ b/trunk/src/dil/Types.d	Tue Aug 28 11:41:00 2007 +0000
@@ -7,15 +7,46 @@
 import dil.Token;
 import dil.Expressions;
 
-enum Linkage
+class Linkage : Node
 {
-  Extern,
-  C,
-  Cpp,
-  D,
-  Windows,
-  Pascal,
-  System
+  enum Type
+  {
+    Extern,
+    C,
+    Cpp,
+    D,
+    Windows,
+    Pascal,
+    System
+  }
+
+  /++
+    This enum is used by the parser to find redundant
+    or conflicting extern attribute declarations.
+  +/
+  enum Category
+  {
+    Unset,
+    ExternSymbol = 1<<1, /// Extern
+    MangleSymbol = 1<<2  /// C, Cpp, D, Windows, Pascal, System
+  }
+
+  Linkage.Type type;
+
+  this(typeof(type) type)
+  {
+    super(NodeCategory.Other);
+    mixin(set_kind);
+    this.type = type;
+  }
+
+  static Category getCategory(Linkage linkage)
+  {
+    if (linkage is null)
+      return Category.ExternSymbol;
+    else
+      return Category.MangleSymbol;
+  }
 }
 
 enum StorageClass
--- a/trunk/src/dil_xml.css	Sun Aug 26 15:59:02 2007 +0000
+++ b/trunk/src/dil_xml.css	Tue Aug 28 11:41:00 2007 +0000
@@ -46,7 +46,10 @@
 op[t=le] { content: "≤"; } /*<=*/
 op[t=ge] { content: "≥"; } /*>=*/
 op[t=lg] { content: "≶"; } /*<>*/
-
+o[t=Linkage] i, o[t=Linkage] op
+{
+  color: red;
+}
 /*
 d = Declaration
 s = Statement
--- a/trunk/src/lang_de.d	Sun Aug 26 15:59:02 2007 +0000
+++ b/trunk/src/lang_de.d	Tue Aug 28 11:41:00 2007 +0000
@@ -44,7 +44,7 @@
   "Überlauf in Binärzahl.",
   "Überlauf in Oktalzahl.",
   "Überlauf in Fließkommazahl.",
-  "die Ziffern 8 und 9 sind in Oktalzahlen verboten.",
+  "die Ziffern 8 und 9 sind in Oktalzahlen unzulässig.",
   "ungültige Hexzahl; mindestens eine Hexziffer erforderlich.",
   "ungültige Binärzahl; mindestens eine Binärziffer erforderlich.",
   "der Exponent einer hexadezimalen Fließkommazahl ist erforderlich.",
@@ -57,6 +57,8 @@
   "Template-Tupel-Parameter dürfen nur am Ende auftreten.",
   "der 'in'-Vertrag der Funktion wurde bereits geparsed.",
   "der 'out'-Vertrag der Funktion wurde bereits geparsed.",
+  "es wurde kein Verknüpfungstyp angegeben.",
+  "unbekannter Verknüpfungstyp '{1}'; gültig sind C, C++, D, Windows, Pascal und System.",
 
   // Help messages:
   `dil v{1}
--- a/trunk/src/lang_en.d	Sun Aug 26 15:59:02 2007 +0000
+++ b/trunk/src/lang_en.d	Tue Aug 28 11:41:00 2007 +0000
@@ -57,6 +57,8 @@
   "template tuple parameters can only be last.",
   "the functions 'in' contract was already parsed.",
   "the functions 'out' contract was already parsed.",
+  "no linkage type was specified.",
+  "unrecognized linkage type '{1}'; valid types are C, C++, D, Windows, Pascal und System.",
 
   // Help messages:
   `dil v{1}
--- a/trunk/src/lang_tr.d	Sun Aug 26 15:59:02 2007 +0000
+++ b/trunk/src/lang_tr.d	Tue Aug 28 11:41:00 2007 +0000
@@ -57,6 +57,8 @@
   "şablon tuple parametre son sırada olmalı.",
   "fonksiyonun 'in' kontratı daha önceden ayrıştırılmış.",
   "fonksiyonun 'out' kontratı daha önceden ayrıştırılmış.",
+  "bağlantı tüp (linkage type) belirtilmedi.",
+  "bilinmeyen bağlantı tüpü (linkage type) '{1}'; geçerli olanlar C, C++, D, Windows, Pascal ve System.",
 
   // Help messages:
   `dil v{1}