# HG changeset patch # User Aziz K?ksal # Date 1202065007 -3600 # Node ID ca7607226caa0f880f4b661fb50ea0ffbb1abc4a # Parent 5cb236c6fe52b1c5d7ea53fbdf68837397fda9c2 Added new module cmd.DDoc. Added command 'ddoc'. Fixed scanArguments() in dil.doc.Macro. diff -r 5cb236c6fe52 -r ca7607226caa trunk/src/cmd/DDoc.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/cmd/DDoc.d Sun Feb 03 19:56:47 2008 +0100 @@ -0,0 +1,94 @@ +/++ + Author: Aziz Köksal + License: GPL3 ++/ +module cmd.DDoc; + +import dil.doc.Parser; +import dil.doc.Macro; +import dil.doc.Doc; +import dil.ast.DefaultVisitor; +import dil.semantic.Module; +import dil.semantic.Pass1; +import dil.semantic.Symbol; +import dil.semantic.Symbols; +import dil.Information; +import dil.File; +import common; + +import tango.stdc.time : time_t, time, ctime; +import tango.stdc.string : strlen; + +void execute(string[] filePaths, string destDir, string[] macroPaths, + bool incUndoc, InfoManager infoMan) +{ + // Parse macro files. + MacroTable mtable; + MacroParser mparser; + foreach (macroPath; macroPaths) + { + auto macros = mparser.parse(loadFile(macroPath)); + mtable = new MacroTable(mtable); + mtable.insert(macros); + } + +// foreach (k, v; mtable.table) +// Stdout(k)("=")(v.text); + + Module[] modules; + foreach (filePath; filePaths) + { + auto mod = new Module(filePath, infoMan); + modules ~= mod; + // Parse the file. + mod.parse(); + if (mod.hasErrors) + continue; + + // Start semantic analysis. + auto pass1 = new SemanticPass1(mod); + pass1.start(); + } + + foreach (mod; modules) + generateDocumentation(mod, mtable); +} + +void generateDocumentation(Module mod, MacroTable mtable) +{ + // Create a macro environment for this module. + mtable = new MacroTable(mtable); + // Define runtime macros. + mtable.insert(new Macro("TITLE", mod.getFQN())); + mtable.insert(new Macro("DOCFILENAME", mod.getFQN())); + + time_t time_val; + time(&time_val); + char* str = ctime(&time_val); + char[] time_str = str[0 .. strlen(str)]; + mtable.insert(new Macro("DATETIME", time_str.dup)); + mtable.insert(new Macro("YEAR", time_str[20..24].dup)); + + if (mod.moduleDecl) + { + auto ddocComment = getDDocComment(mod.moduleDecl); + if (auto copyright = ddocComment.getCopyright()) + mtable.insert(new Macro("COPYRIGHT", copyright.text)); + } + + auto docEmitter = new DDocEmitter(); + docEmitter.emit(mod); + + mtable.insert(new Macro("BODY", docEmitter.text)); + expandMacros(mtable, "$(DDOC)"); +} + +class DDocEmitter : DefaultVisitor +{ + char[] text; + + char[] emit(Module mod) + { + return text; + } +} diff -r 5cb236c6fe52 -r ca7607226caa trunk/src/dil/SettingsLoader.d --- a/trunk/src/dil/SettingsLoader.d Sun Feb 03 18:59:34 2008 +0100 +++ b/trunk/src/dil/SettingsLoader.d Sun Feb 03 19:56:47 2008 +0100 @@ -57,7 +57,7 @@ { foreach (value; array.values) if (auto str = value.Is!(StringExpression)) - GlobalSettings.ddocFilePaths ~= str.getString(); + GlobalSettings.ddocFilePaths ~= resolvePath(execPath, str.getString()); } else throw new Exception("import_paths variable is set to "~e.classinfo.name~" instead of an ArrayInitializer."); diff -r 5cb236c6fe52 -r ca7607226caa trunk/src/dil/ast/Visitor.d --- a/trunk/src/dil/ast/Visitor.d Sun Feb 03 18:59:34 2008 +0100 +++ b/trunk/src/dil/ast/Visitor.d Sun Feb 03 19:56:47 2008 +0100 @@ -45,17 +45,19 @@ } /++ - Generate functions which do the second dispatch. - E.g.: - Expression visitCommaExpression(Visitor visitor, CommaExpression c) - { visitor.visit(c); } + Generate functions which do the second dispatch.$(BR) + E.g.:$(BR) + $(D_CODE +Expression visitCommaExpression(Visitor visitor, CommaExpression c) +{ visitor.visit(c); }) - The equivalent in the traditional visitor pattern would be: - class CommaExpression : Expression - { - void accept(Visitor visitor) - { visitor.visit(this); } - } + The equivalent in the traditional visitor pattern would be:$(BR) + $(D_CODE +class CommaExpression : Expression +{ + void accept(Visitor visitor) + { visitor.visit(this); } +}) +/ char[] generateDispatchFunctions() { @@ -79,6 +81,7 @@ } // pragma(msg, generateVTable()); +/// The visitor pattern. abstract class Visitor { mixin(generateVisitMethods()); diff -r 5cb236c6fe52 -r ca7607226caa trunk/src/dil/doc/Doc.d --- a/trunk/src/dil/doc/Doc.d Sun Feb 03 18:59:34 2008 +0100 +++ b/trunk/src/dil/doc/Doc.d Sun Feb 03 19:56:47 2008 +0100 @@ -10,6 +10,8 @@ import dil.Unicode; import common; +import tango.text.Ascii : toLower; + class DDocComment { Section[] sections; @@ -22,6 +24,22 @@ this.summary = summary; this.description = description; } + + Section getCopyright() + { + foreach (section; sections) + if (toLower(section.name) == "copyright") + return section; + return null; + } +} + +/// Returns a node's DDocComment. +DDocComment getDDocComment(Node node) +{ + DDocParser p; + p.parse(getDDocText(getDocTokens(node))); + return new DDocComment(p.sections, p.summary, p.description); } struct DDocParser @@ -171,8 +189,8 @@ class MacrosSection : Section { - string[] macroNames; /// Parameter names. - string[] macroTexts; /// Parameter descriptions. + string[] macroNames; /// Macro names. + string[] macroTexts; /// Macro texts. this(string name, string text) { super(name, text); diff -r 5cb236c6fe52 -r ca7607226caa trunk/src/dil/doc/Macro.d --- a/trunk/src/dil/doc/Macro.d Sun Feb 03 18:59:34 2008 +0100 +++ b/trunk/src/dil/doc/Macro.d Sun Feb 03 19:56:47 2008 +0100 @@ -151,6 +151,8 @@ switch (*p) { case ',': + if (level != 1) // Ignore comma if inside (). + break; // Add a new argument. args ~= makeString(argBegin, p); while (++p < textEnd && isspace(*p)) diff -r 5cb236c6fe52 -r ca7607226caa trunk/src/main.d --- a/trunk/src/main.d Sun Feb 03 18:59:34 2008 +0100 +++ b/trunk/src/main.d Sun Feb 03 19:56:47 2008 +0100 @@ -28,12 +28,14 @@ import cmd.Generate; import cmd.Statistics; import cmd.ImportGraph; +import cmd.DDoc; import common; import Integer = tango.text.convert.Integer; import tango.io.File; import tango.text.Util; import tango.time.StopWatch; +import tango.text.Ascii : toLower; void main(char[][] args) { @@ -82,6 +84,31 @@ printErrors(infoMan); break; + case "ddoc", "d": + if (args.length < 4) + return printHelp("ddoc"); + + auto destination = args[2]; + auto macroPaths = GlobalSettings.ddocFilePaths; + char[][] filePaths; + bool incUndoc; + // Parse arguments. + foreach (arg; args[3..$]) + { + if (arg == "-i") + incUndoc = true; + else if (arg.length > 5 && toLower(arg[$-4..$]) == "ddoc") + macroPaths ~= arg; + else + filePaths ~= arg; + } + + auto infoMan = new InfoManager(); + // Execute command. + cmd.DDoc.execute(filePaths, destination, macroPaths, incUndoc, infoMan); + if (infoMan.info.length) + return printErrors(infoMan); + break; case "gen", "generate": char[] fileName; DocOption options = DocOption.Tokens; @@ -252,6 +279,7 @@ const char[] COMMANDS = " compile (c)\n" + " ddoc (d)\n" " generate (gen)\n" " help (?)\n" " importgraph (igraph)\n" @@ -310,6 +338,20 @@ Example: dil c src/main.d"; break; + case "ddoc", "d": + msg = `Generate documentation from DDoc comments in D source files. +Usage: + dil ddoc Destination file.d [file2.d, ...] [Options] + + Destination is the folder where the documentation files are written to. + Files with the extension .ddoc are recognized as macro definition files. + +Options: + -i : include undocumented symbols + +Example: + dil d doc/ src/main.d mymacros.ddoc -i`; + break; case "gen", "generate": msg = GetMsg(MID.HelpGenerate); break;