changeset 747:00f872d949ea

Added method scanCommentText() to DDocEmitter. Added method writeParams() and scanCodeSection(). Added method scanMacro() to MacroParser. Made fixes and improvements to the MacroExpander. Applied other minor fixes.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Mon, 11 Feb 2008 03:15:45 +0100
parents 32a8ddd330f8
children efd87fdb1c00
files trunk/src/cmd/DDoc.d trunk/src/dil/Unicode.d trunk/src/dil/ast/Parameters.d trunk/src/dil/doc/Macro.d trunk/src/dil/doc/Parser.d trunk/src/dil/lexer/Token.d trunk/src/dil/semantic/Pass1.d trunk/src/dil/semantic/Symbols.d
diffstat 8 files changed, 210 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/src/cmd/DDoc.d	Sun Feb 10 02:14:08 2008 +0100
+++ b/trunk/src/cmd/DDoc.d	Mon Feb 11 03:15:45 2008 +0100
@@ -15,6 +15,7 @@
        dil.ast.Types;
 import dil.ast.DefaultVisitor;
 import dil.lexer.Token;
+import dil.lexer.Funcs;
 import dil.semantic.Module;
 import dil.semantic.Pass1;
 import dil.semantic.Symbol;
@@ -95,6 +96,7 @@
   mtable.insert("BODY", doc.text);
   // Do the macro expansion pass.
   auto fileText = MacroExpander.expand(mtable, "$(DDOC)", mod.filePath, infoMan);
+//   fileText ~= "\n<pre>\n" ~ doc.text ~ "\n</pre>";
   // Finally write the file out to the harddisk.
   auto file = new File(dest);
   file.write(fileText);
@@ -236,16 +238,126 @@
         }
         else
           write("\n$(DDOC_SECTION $(DDOC_SECTION_H " ~ s.name ~ ":)");
-        write(s.text, ")");
+        write(scanCommentText(s.text), ")");
       }
     write(")");
   }
 
+  char[] scanCommentText(char[] text)
+  {
+    char* p = text.ptr;
+    char* end = p + text.length;
+    char[] result = new char[text.length]; // Reserve space.
+    result.length = 0;
+
+    while (p < end)
+    {
+      switch (*p)
+      {
+      case '$':
+        if (auto macroEnd = MacroParser.scanMacro(p, end))
+        {
+          result ~= makeString(p, macroEnd); // Copy macro invocation as is.
+          p = macroEnd;
+          continue;
+        }
+        goto default;
+      case '<':
+        auto begin = p;
+        p++;
+        if (p+2 < end && *p == '!' && p[1] == '-' && p[2] == '-') // <!--
+        {
+          p += 2; // Point to 2nd '-'.
+          // Scan to closing "-->".
+          while (++p < end)
+            if (p+2 < end && *p == '-' && p[1] == '-' && p[2] == '>')
+            {
+              p += 3; // Point one past '>'.
+              break;
+            }
+          result ~= makeString(begin, p);
+        } // <tag ...> or </tag>
+        else if (p < end && (isalpha(*p) || *p == '/'))
+        {
+          while (++p < end && *p != '>') // Skip to closing '>'.
+          {}
+          p != end && p++; // Skip '>'.
+          result ~= makeString(begin, p);
+        }
+        else
+          result ~= "&lt;";
+        continue;
+      case '(': result ~= "&#40;"; break;
+      case ')': result ~= "&#41;"; break;
+      case '\'': result ~= "&apos;"; break; // &#39;
+      case '"': result ~= "&quot;"; break;
+      case '>': result ~= "&gt;"; break;
+      case '&':
+        if (p+1 < end && (isalpha(p[1]) || p[1] == '#'))
+          goto default;
+        result ~= "&amp;";
+        break;
+      case '-':
+        if (p+2 < end && p[1] == '-' && p[2] == '-')
+        {
+          p += 2; // Point to 3rd '-'.
+          auto codeBegin = p + 1;
+          while (++p < end)
+            if (p+2 < end && *p == '-' && p[1] == '-' && p[2] == '-')
+            {
+              result ~= "$(D_CODE " ~ scanCodeSection(makeString(codeBegin, p)) ~ ")";
+              p += 3;
+              break;
+            }
+          continue;
+        }
+        //goto default;
+      default:
+        result ~= *p;
+      }
+      p++;
+    }
+    return result;
+  }
+
+  char[] scanCodeSection(char[] text)
+  {
+    return text;
+  }
+
+  void writeParams(Parameters params)
+  {
+    if (!params.items.length)
+      return write("()");
+    write("(");
+    auto lastParam = params.items[$-1];
+    foreach (param; params.items)
+    {
+      if (param.isCVariadic)
+        write("...");
+      else
+      {
+        assert(param.type);
+        // Write storage classes.
+        auto typeBegin = param.type.baseType.begin;
+        if (typeBegin !is param.begin)
+          write(textSpan(param.begin, typeBegin.prevNWS), " ");
+        write(textSpan(typeBegin, param.type.end));
+        write(" $(DDOC_PARAM ", param.name.str, ")");
+        if (param.isDVariadic)
+          write("...");
+      }
+      if (param !is lastParam)
+        write(", ");
+    }
+    write(")");
+  }
+
   void writeTemplateParams()
   {
     if (!isTemplatized)
       return;
-    text ~= "(" ~ (tparams ? textSpan(tparams.begin, tparams.end) : "") ~ ")";
+    write("(", (tparams ? textSpan(tparams.begin, tparams.end) : ""), ")");
     isTemplatized = false;
     tparams = null;
   }
@@ -440,7 +552,7 @@
   {
     if (!ddoc(d))
       return d;
-    DECL({ writeFuncHeader(d, d.funcBody); });
+    DECL({ write("this"); writeParams(d.params); });
     DESC({ writeComment(); });
     return d;
   }
@@ -476,7 +588,8 @@
   {
     if (!ddoc(d))
       return d;
-    DECL({ writeFuncHeader(d, d.funcBody); });
+    auto type = textSpan(d.returnType.baseType.begin, d.returnType.end);
+    DECL({ write(type, " "); SYMBOL(d.name.str); writeParams(d.params); });
     DESC({ writeComment(); });
     return d;
   }
@@ -485,7 +598,7 @@
   {
     if (!ddoc(d))
       return d;
-    DECL({ writeFuncHeader(d, d.funcBody); });
+    DECL({ write("new"); writeParams(d.params); });
     DESC({ writeComment(); });
     return d;
   }
--- a/trunk/src/dil/Unicode.d	Sun Feb 10 02:14:08 2008 +0100
+++ b/trunk/src/dil/Unicode.d	Mon Feb 11 03:15:45 2008 +0100
@@ -31,13 +31,13 @@
          d <= 0x10FFFF && (d & 0xFFFF) >= 0xFFFE; // 34
 }
 
-/// Returns true if this is a trail byte of a UTF-8 sequence?
+/// Returns: true if this is a trail byte of a UTF-8 sequence.
 bool isTrailByte(ubyte b)
 {
   return (b & 0xC0) == 0x80; // 10xx_xxxx
 }
 
-/// Returns true if this is a lead byte of a UTF-8 sequence.
+/// Returns: true if this is a lead byte of a UTF-8 sequence.
 bool isLeadByte(ubyte b)
 {
   return (b & 0xC0) == 0xC0; // 11xx_xxxx
--- a/trunk/src/dil/ast/Parameters.d	Sun Feb 10 02:14:08 2008 +0100
+++ b/trunk/src/dil/ast/Parameters.d	Mon Feb 11 03:15:45 2008 +0100
@@ -37,8 +37,14 @@
     return !!(stc & StorageClass.Variadic);
   }
 
+  /// func(int[] values ...)
+  bool isDVariadic()
+  {
+    return isVariadic && !isCVariadic;
+  }
+
   /// func(...)
-  bool isOnlyVariadic()
+  bool isCVariadic()
   {
     return stc == StorageClass.Variadic &&
            type is null && name is null;
@@ -70,9 +76,9 @@
   { return children.length; }
 }
 
-/*********************
-  Template parameters:
-*/
+/*~~~~~~~~~~~~~~~~~~~~~~
+~ Template parameters: ~
+~~~~~~~~~~~~~~~~~~~~~~*/
 
 abstract class TemplateParameter : Node
 {
--- a/trunk/src/dil/doc/Macro.d	Sun Feb 10 02:14:08 2008 +0100
+++ b/trunk/src/dil/doc/Macro.d	Mon Feb 11 03:15:45 2008 +0100
@@ -70,6 +70,7 @@
   { return parent is null; }
 }
 
+/// Parses a text with macro definitions.
 struct MacroParser
 {
   Macro[] parse(string text)
@@ -81,16 +82,39 @@
       macros[i] = new Macro(idvalue.ident, idvalue.value);
     return macros;
   }
+
+  /// Scans for a macro invocation. E.g.: $&#40;DDOC&#41;
+  /// Returns: a pointer set to one char past the closing parenthesis,
+  /// or null if this isn't a macro invocation.
+  static char* scanMacro(char* p, char* textEnd)
+  {
+    assert(*p == '$');
+    if (p+2 < textEnd && p[1] == '(')
+    {
+      p += 2;
+      if (isidbeg(*p) || isUnicodeAlpha(p, textEnd)) // IdStart
+      {
+        do // IdChar*
+          p++;
+        while (p < textEnd && (isident(*p) || isUnicodeAlpha(p, textEnd)))
+        MacroExpander.scanArguments(p, textEnd);
+        p != textEnd && p++; // Skip ')'.
+        return p;
+      }
+    }
+    return null;
+  }
 }
 
+/// Expands DDoc macros in a text.
 struct MacroExpander
 {
   MacroTable mtable; /// Used to look up macros.
   InfoManager infoMan; /// Collects warning messages.
   char[] filePath; /// Used in warning messages.
 
-  static char[] expand(MacroTable mtable, char[] text,
-                       char[] filePath,
+  /// Starts expanding the macros.
+  static char[] expand(MacroTable mtable, char[] text, char[] filePath,
                        InfoManager infoMan = null)
   {
     MacroExpander me;
@@ -100,6 +124,7 @@
     return me.expandMacros(text);
   }
 
+  /// Reports a warning message.
   void warning(char[] msg, char[] macroName)
   {
     msg = Format(msg, macroName);
@@ -107,9 +132,12 @@
       infoMan ~= new Warning(new Location(filePath, 0), msg);
   }
 
-  /// Expands the macros from the table in text.
-  char[] expandMacros(char[] text, char[][] args = null)
+  /// Expands the macros from the table in the text.
+  char[] expandMacros(char[] text, char[] prevArg0 = null/+, uint depth = 1000+/)
   {
+    // if (depth == 0)
+    //   return  text;
+    // depth--;
     char[] result;
     char* p = text.ptr;
     char* textEnd = p + text.length;
@@ -119,7 +147,7 @@
       if (*p == '$' && p[1] == '(')
       {
         // Copy string between macros.
-        if (macroEnd !is p)
+        if (macroEnd != p)
           result ~= makeString(macroEnd, p);
         p += 2;
         auto idBegin = p;
@@ -132,44 +160,49 @@
           auto macroName = makeString(idBegin, p);
           // Get arguments.
           auto macroArgs = scanArguments(p, textEnd);
-          // TODO: still expand macro if no closing bracket was found?
           if (p == textEnd)
           {
             warning(MSG.UnterminatedDDocMacro, macroName);
-            break; // No closing bracket found.
+            result ~= "$(" ~ macroName ~ " ";
           }
-          assert(*p == ')');
-          p++;
-          macroEnd = p;
+          else
+            p++;
+          macroEnd = p; // Point past ')'.
 
           auto macro_ = mtable.search(macroName);
           if (macro_)
           { // Ignore recursive macro if:
+            auto macroArg0 = macroArgs.length ? macroArgs[0] : null;
             if (macro_.callLevel != 0 &&
-                (macroArgs.length == 0 || // Macro has no arguments.
-                  args.length && args[0] == macroArgs[0]) // arg0 == macroArg0.
-              )
-              continue;
+                (macroArgs.length == 0/+ || // Macro has no arguments.
+                 prevArg0 == macroArg0+/)) // macroArg0 equals previous arg0.
+            { continue; }
             macro_.callLevel++;
+            // Expand the arguments in the macro text.
             auto expandedText = expandArguments(macro_.text, macroArgs);
-            result ~= expandMacros(expandedText, macroArgs);
+            result ~= expandMacros(expandedText, macroArg0/+, depth+/);
             macro_.callLevel--;
           }
           else
+          {
             warning(MSG.UndefinedDDocMacro, macroName);
+            //result ~= makeString(macroName.ptr-2, macroEnd);
+          }
           continue;
         }
       }
       p++;
     }
+    if (macroEnd == text.ptr)
+      return text; // No macros found. Return original text.
     if (macroEnd < textEnd)
       result ~= makeString(macroEnd, textEnd);
     return result;
   }
 
-  /// Scans until the closing ')' is found.
-  /// Returns: ['$0', $1, $2 ...].
-  char[][] scanArguments(ref char* p, char* textEnd)
+  /// Scans until the closing parenthesis is found. Sets p to one char past it.
+  /// Returns: [arg0, arg1, arg2 ...].
+  static char[][] scanArguments(ref char* p, char* textEnd)
   out(args) { assert(args.length != 1); }
   body
   {
@@ -184,7 +217,7 @@
 
     char* arg0Begin = p; // Whole argument list.
     char* argBegin = p;
-  Loop:
+  MainLoop:
     while (p < textEnd)
     {
       switch (*p)
@@ -203,7 +236,7 @@
         break;
       case ')':
         if (--level == 0)
-          break Loop;
+          break MainLoop;
         break;
       case '"', '\'':
         auto c = *p;
@@ -211,33 +244,33 @@
         {}
         assert(*p == c || p == textEnd);
         if (p == textEnd)
-          break Loop;
+          break MainLoop;
         break;
       case '<':
-        if (p+3 < textEnd && p[1] == '!' && p[2] == '-' && p[3] == '-') // <!--
+        p++;
+        if (p+2 < textEnd && *p == '!' && p[1] == '-' && p[2] == '-') // <!--
         {
-          p += 3;
+          p += 2; // Point to 2nd '-'.
           // Scan to closing "-->".
-          while (++p + 2 < textEnd)
-            if (*p == '-' && p[1] == '-' && p[2] == '>')
-            {
-              p += 3;
-              continue Loop;
-            }
-          p = textEnd; // p += 2;
+          while (++p < textEnd)
+            if (p+2 < textEnd && *p == '-' && p[1] == '-' && p[2] == '>')
+              p += 2; // Point to '>'.
         } // <tag ...> or </tag>
-        else if (p+1 < textEnd && (isalpha(p[1]) || p[1] == '/'))
+        else if (p < textEnd && (isalpha(*p) || *p == '/'))
           while (++p < textEnd && *p != '>') // Skip to closing '>'.
           {}
+        else
+          continue MainLoop;
         if (p == textEnd)
-          break Loop;
+          break MainLoop;
+        assert(*p == '>');
         break;
       default:
       }
       p++;
     }
     assert(*p == ')' && level == 0 || p == textEnd);
-    if (arg0Begin is p)
+    if (arg0Begin == p)
       return null;
     // arg0 spans the whole argument list.
     auto arg0 = makeString(arg0Begin, p);
@@ -246,7 +279,7 @@
     return arg0 ~ args;
   }
 
-  /// Expands "$+", "$0" - "$9" with args[n] in text.
+  /// Expands "$ +", "$ 0" - "$ 9" with args[n] in text.
   /// Params:
   ///   text = the text to scan for argument placeholders.
   ///   args = the first element, args[0], is the whole argument string and
@@ -263,13 +296,12 @@
 
     while (p+1 < textEnd)
     {
-      if (*p == '$' && (p[1] == '+' || isdigit(p[1])))
+      if (*p == '$' && (*++p == '+' || isdigit(*p)))
       {
         // Copy string between argument placeholders.
-        if (placeholderEnd !is p)
-          result ~= makeString(placeholderEnd, p);
-        p++;
-        placeholderEnd = p + 1; // Set new argument end.
+        if (placeholderEnd != p-1)
+          result ~= makeString(placeholderEnd, p-1);
+        placeholderEnd = p+1; // Set new placeholder end.
 
         if (args.length == 0)
           continue;
@@ -288,6 +320,8 @@
       }
       p++;
     }
+    if (placeholderEnd == text.ptr)
+      return text; // No placeholders found. Return original text.
     if (placeholderEnd < textEnd)
       result ~= makeString(placeholderEnd, textEnd);
     return result;
--- a/trunk/src/dil/doc/Parser.d	Sun Feb 10 02:14:08 2008 +0100
+++ b/trunk/src/dil/doc/Parser.d	Mon Feb 11 03:15:45 2008 +0100
@@ -20,9 +20,11 @@
 }
 
 /// Parses text of the form:
+/// <pre>
 /// ident = value
 /// ident2 = value2
-///          more text
+////         more text
+/// </pre>
 struct IdentValueParser
 {
   char* p;
--- a/trunk/src/dil/lexer/Token.d	Sun Feb 10 02:14:08 2008 +0100
+++ b/trunk/src/dil/lexer/Token.d	Mon Feb 11 03:15:45 2008 +0100
@@ -119,7 +119,7 @@
     return tokToString[tok];
   }
 
-  /// Adds Flags.Whitespace to this token's flags.
+  /// Adds Flags. Whitespace to this token's flags.
   void setWhitespaceFlag()
   {
     this.flags |= Flags.Whitespace;
--- a/trunk/src/dil/semantic/Pass1.d	Sun Feb 10 02:14:08 2008 +0100
+++ b/trunk/src/dil/semantic/Pass1.d	Mon Feb 11 03:15:45 2008 +0100
@@ -26,7 +26,8 @@
 import common;
 
 /++
-  The fist pass is the declaration pass.
+  The first pass is the declaration pass.
+
   The basic task of this class is to traverse the parse tree,
   find all kinds of declarations and add them
   to the symbol tables of their respective scopes.
--- a/trunk/src/dil/semantic/Symbols.d	Sun Feb 10 02:14:08 2008 +0100
+++ b/trunk/src/dil/semantic/Symbols.d	Mon Feb 11 03:15:45 2008 +0100
@@ -24,7 +24,7 @@
     super(sid, name, node);
   }
 
-  /// Look up ident in the table.
+  /// Look up name in the table.
   Symbol lookup(Identifier* name)
   {
     return symbolTable.lookup(name);