Mercurial > projects > dil
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 ~= "<"; + continue; + case '(': result ~= "("; break; + case ')': result ~= ")"; break; + case '\'': result ~= "'"; break; // ' + case '"': result ~= """; break; + case '>': result ~= ">"; break; + case '&': + if (p+1 < end && (isalpha(p[1]) || p[1] == '#')) + goto default; + result ~= "&"; + 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.: $(DDOC) + /// 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);