Mercurial > projects > dil
view src/main.d @ 820:1d06b4aed7cf
Revised code in the first pass.
Added code to handle anonymous unions and structs. Hope the idea will work.
Added type to class Aggregate and isAnonymous to some other Symbol classes.
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Fri, 14 Mar 2008 15:42:08 +0100 |
parents | 438ed3a72c9d |
children | a8b3de006554 |
line wrap: on
line source
/++ Author: Aziz Köksal License: GPL3 +/ module main; import dil.parser.Parser; import dil.lexer.Lexer, dil.lexer.Token; import dil.ast.Declarations, dil.ast.Expressions, dil.ast.Node, dil.ast.Visitor; import dil.semantic.Module; import dil.semantic.Symbols; import dil.semantic.Pass1, dil.semantic.Pass2, dil.semantic.Interpreter; import dil.translator.German; import dil.doc.Doc; import dil.Messages; import dil.CompilerInfo; import dil.Information; import dil.SourceText; import dil.Compilation; import cmd.Compile; import cmd.Highlight; import cmd.Statistics; import cmd.ImportGraph; import cmd.DDoc; import Settings; import SettingsLoader; // import TypeRules; import common; import Integer = tango.text.convert.Integer; import tango.stdc.stdio; import tango.io.File; import tango.text.Util; import tango.time.StopWatch; import tango.text.Ascii : icompare; /// Entry function of dil. void main(char[][] args) { auto infoMan = new InfoManager(); SettingsLoader.SettingsLoader(infoMan).load(); if (infoMan.hasInfo) return printErrors(infoMan); if (args.length <= 1) return printHelp("main"); string command = args[1]; switch (command) { case "c", "compile": if (args.length < 3) return printHelp(command); CompileCommand cmd; cmd.context = newCompilationContext(); cmd.infoMan = infoMan; foreach (arg; args[2..$]) { if (parseDebugOrVersion(arg, cmd.context)) {} else if (strbeg(arg, "-I")) cmd.context.importPaths ~= arg[2..$]; else if (arg == "-release") cmd.context.releaseBuild = true; else if (arg == "-unittest") cmd.context.unittestBuild = true; else if (arg == "-d") cmd.context.acceptDeprecated = true; else if (arg == "-ps") cmd.printSymbolTree = true; else if (arg == "-pm") cmd.printModuleTree = true; else cmd.filePaths ~= arg; } cmd.run(); infoMan.hasInfo && printErrors(infoMan); break; case "ddoc", "d": if (args.length < 4) return printHelp(command); DDocCommand cmd; cmd.destDirPath = args[2]; cmd.macroPaths = GlobalSettings.ddocFilePaths; cmd.context = newCompilationContext(); cmd.infoMan = infoMan; // Parse arguments. foreach (arg; args[3..$]) { if (parseDebugOrVersion(arg, cmd.context)) {} else if (arg == "--xml") cmd.writeXML = true; else if (arg == "-i") cmd.includeUndocumented = true; else if (arg == "-v") cmd.verbose = true; else if (arg.length > 5 && icompare(arg[$-4..$], "ddoc") == 0) cmd.macroPaths ~= arg; else cmd.filePaths ~= arg; } cmd.run(); infoMan.hasInfo && printErrors(infoMan); break; case "hl", "highlight": if (args.length < 3) return printHelp(command); HighlightCommand cmd; cmd.infoMan = infoMan; foreach (arg; args[2..$]) { switch (arg) { case "--syntax": cmd.add(HighlightCommand.Option.Syntax); break; case "--xml": cmd.add(HighlightCommand.Option.XML); break; case "--html": cmd.add(HighlightCommand.Option.HTML); break; case "--lines": cmd.add(HighlightCommand.Option.PrintLines); break; default: cmd.filePath = arg; } } cmd.run(); infoMan.hasInfo && printErrors(infoMan); break; case "importgraph", "igraph": if (args.length < 3) return printHelp(command); IGraphCommand cmd; cmd.context = newCompilationContext(); foreach (arg; args[2..$]) { if (parseDebugOrVersion(arg, cmd.context)) {} else if (strbeg(arg, "-I")) cmd.context.importPaths ~= arg[2..$]; else if(strbeg(arg, "-x")) cmd.regexps ~= arg[2..$]; else if(strbeg(arg, "-l")) cmd.levels = Integer.toInt(arg[2..$]); else if(strbeg(arg, "-si")) cmd.siStyle = arg[3..$]; else if(strbeg(arg, "-pi")) cmd.piStyle = arg[3..$]; else switch (arg) { case "--dot": cmd.add(IGraphCommand.Option.PrintDot); break; case "--paths": cmd.add(IGraphCommand.Option.PrintPaths); break; case "--list": cmd.add(IGraphCommand.Option.PrintList); break; case "-i": cmd.add(IGraphCommand.Option.IncludeUnlocatableModules); break; case "-hle": cmd.add(IGraphCommand.Option.HighlightCyclicEdges); break; case "-hlv": cmd.add(IGraphCommand.Option.HighlightCyclicVertices); break; case "-gbp": cmd.add(IGraphCommand.Option.GroupByPackageNames); break; case "-gbf": cmd.add(IGraphCommand.Option.GroupByFullPackageName); break; case "-m": cmd.add(IGraphCommand.Option.MarkCyclicModules); break; default: cmd.filePath = arg; } } cmd.run(); break; case "stats", "statistics": if (args.length < 3) return printHelp(command); StatsCommand cmd; foreach (arg; args[2..$]) if (arg == "--toktable") cmd.printTokensTable = true; else if (arg == "--asttable") cmd.printNodesTable = true; else cmd.filePaths ~= arg; cmd.run(); break; case "tok", "tokenize": if (args.length < 3) return printHelp(command); SourceText sourceText; char[] filePath; char[] separator; bool ignoreWSToks; bool printWS; foreach (arg; args[2..$]) { if (strbeg(arg, "-s")) separator = arg[2..$]; else if (arg == "-") sourceText = new SourceText("stdin", readStdin()); else if (arg == "-i") ignoreWSToks = true; else if (arg == "-ws") printWS = true; else filePath = arg; } separator || (separator = "\n"); if (!sourceText) sourceText = new SourceText(filePath, true); infoMan = new InfoManager(); auto lx = new Lexer(sourceText, infoMan); lx.scanAll(); auto token = lx.firstToken(); for (; token.kind != TOK.EOF; token = token.next) { if (token.kind == TOK.Newline || ignoreWSToks && token.isWhitespace) continue; if (printWS && token.ws) Stdout(token.wsChars); Stdout(token.srcText)(separator); } infoMan.hasInfo && printErrors(infoMan); break; case "trans", "translate": if (args.length < 3) return printHelp(command); if (args[2] != "German") return Stdout.formatln("Error: unrecognized target language \"{}\"", args[2]); infoMan = new InfoManager(); auto filePath = args[3]; auto mod = new Module(filePath, infoMan); // Parse the file. mod.parse(); if (!mod.hasErrors) { // Translate auto german = new GermanTranslator(Stdout, " "); german.translate(mod.root); } printErrors(infoMan); break; case "profile": if (args.length < 3) break; char[][] filePaths; if (args[2] == "dstress") { auto text = cast(char[])(new File("dstress_files")).read(); filePaths = split(text, "\0"); } else filePaths = args[2..$]; StopWatch swatch; swatch.start; foreach (filePath; filePaths) (new Lexer(new SourceText(filePath, true))).scanAll(); Stdout.formatln("Scanned in {:f10}s.", swatch.stop); break; case "?", "help": printHelp(args.length >= 3 ? args[2] : ""); break; // case "typerules": // genHTMLTypeRulesTables(); // break; default: printHelp("main"); } } char[] readStdin() { char[] text; while (1) { auto c = getc(stdin); if (c == EOF) break; text ~= c; } return text; } /// Available commands. const char[] COMMANDS = " compile (c)\n" " ddoc (d)\n" " help (?)\n" " highlight (hl)\n" " importgraph (igraph)\n" " statistics (stats)\n" " tokenize (tok)\n" " translate (trans)\n"; bool strbeg(char[] str, char[] begin) { if (str.length >= begin.length) { if (str[0 .. begin.length] == begin) return true; } return false; } /// Creates the global compilation context. CompilationContext newCompilationContext() { auto cc = new CompilationContext; cc.importPaths = GlobalSettings.importPaths; cc.addVersionId("dil"); cc.addVersionId("all"); version(D2) cc.addVersionId("D_Version2"); foreach (versionId; GlobalSettings.versionIds) if (Lexer.isValidUnreservedIdentifier(versionId)) cc.versionIds[versionId] = true; return cc; } bool parseDebugOrVersion(string arg, CompilationContext context) { if (strbeg(arg, "-debug")) { if (arg.length > 7) { auto val = arg[7..$]; if (isdigit(val[0])) context.debugLevel = Integer.toInt(val); else if (Lexer.isValidUnreservedIdentifier(val)) context.addDebugId(val); } else context.debugLevel = 1; } else if (arg.length > 9 && strbeg(arg, "-version=")) { auto val = arg[9..$]; if (isdigit(val[0])) context.versionLevel = Integer.toInt(val); else if (Lexer.isValidUnreservedIdentifier(val)) context.addVersionId(val); } else return false; return true; } /// Prints the errors collected in infoMan. void printErrors(InfoManager infoMan) { foreach (info; infoMan.info) { char[] errorFormat; if (info.classinfo is LexerError.classinfo) errorFormat = GlobalSettings.lexerErrorFormat; else if (info.classinfo is ParserError.classinfo) errorFormat = GlobalSettings.parserErrorFormat; else if (info.classinfo is SemanticError.classinfo) errorFormat = GlobalSettings.semanticErrorFormat; else if (info.classinfo is Warning.classinfo) errorFormat = "{0}: Warning: {3}"; else continue; auto err = cast(Problem)info; Stderr.formatln(errorFormat, err.filePath, err.loc, err.col, err.getMsg); } } /// Prints a help message for command. void printHelp(char[] command) { char[] msg; switch (command) { case "c", "compile": msg = `Compile D source files. Usage: dil compile file.d [file2.d, ...] [Options] This command only parses the source files and does little semantic analysis. Errors are printed to standard error output. Options: -d : accept deprecated code -debug : include debug code -debug=level : include debug(l) code where l <= level -debug=ident : include debug(ident) code -version=level : include version(l) code where l >= level -version=ident : include version(ident) code -Ipath : add 'path' to the list of import paths -release : compile a release build -unittest : compile a unittest build -ps : print the symbol tree of the modules -pm : print the package/module tree Example: dil c src/main.d -Isrc/`; 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: --xml : write XML instead of HTML documents -i : include undocumented symbols -v : verbose output Example: dil d doc/ src/main.d src/macros_dil.ddoc -i`; break; case "hl", "highlight": // msg = GetMsg(MID.HelpGenerate); msg = `Highlight a D source file with XML or HTML tags. Usage: dil hl file.d [Options] Options: --syntax : generate tags for the syntax tree --xml : use XML format (default) --html : use HTML format --lines : print line numbers Example: dil hl Parser.d --html --syntax > Parser.html`; break; case "importgraph", "igraph": // msg = GetMsg(MID.HelpImportGraph); msg = `Parse a module and build a module dependency graph based on its imports. Usage: dil igraph file.d Format [Options] The directory of file.d is implicitly added to the list of import paths. Format: --dot : generate a dot document (default) Options related to --dot: -gbp : Group modules by package names -gbf : Group modules by full package name -hle : highlight cyclic edges in the graph -hlv : highlight modules in cyclic relationships -siSTYLE : the edge style to use for static imports -piSTYLE : the edge style to use for public imports STYLE can be: "dashed", "dotted", "solid", "invis" or "bold" --paths : print the file paths of the modules in the graph --list : print the names of the module in the graph Options common to --paths and --list: -lN : print N levels. -m : use '*' to mark modules in cyclic relationships Options: -Ipath : add 'path' to the list of import paths where modules are looked for -xREGEXP : exclude modules whose names match the regular expression REGEXP -i : include unlocatable modules Example: dil igraph src/main.d --list dil igraph src/main.d | dot -Tpng > main.png`; break; case "tok", "tokenize": msg = `Print the tokens of a D source file. Usage: dil tok file.d [Options] Options: - : reads text from the standard input. -sSEPARATOR : print SEPARATOR instead of newline between tokens. -i : ignore whitespace tokens (e.g. comments, shebang etc.) -ws : print a token's preceding whitespace characters. Example: echo "module foo; void func(){}" | dil tok - dil tok main.d | grep ^[0-9]`; break; case "stats", "statistics": msg = "Gather statistics about D source files. Usage: dil stat file.d [file2.d, ...] [Options] Options: --toktable : print the count of all kinds of tokens in a table. --asttable : print the count of all kinds of nodes in a table. Example: dil stat src/dil/Parser.d src/dil/Lexer.d"; break; case "trans", "translate": msg = `Translate a D source file to another language. Usage: dil translate Language file.d Languages that are supported: *) German Example: dil trans German src/main.d`; break; case "main": default: auto COMPILED_WITH = __VENDOR__; auto COMPILED_VERSION = Format("{}.{,:d3}", __VERSION__/1000, __VERSION__%1000); auto COMPILED_DATE = __TIMESTAMP__; msg = FormatMsg(MID.HelpMain, VERSION, COMMANDS, COMPILED_WITH, COMPILED_VERSION, COMPILED_DATE); } Stdout(msg).newline; }