Mercurial > projects > dil
diff src/cmd/Statistics.d @ 806:bcb74c9b895c
Moved out files in the trunk folder to the root.
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Sun, 09 Mar 2008 00:12:19 +0100 |
parents | trunk/src/cmd/Statistics.d@cf2ad5df025c |
children | 5c29f1ebec9f |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cmd/Statistics.d Sun Mar 09 00:12:19 2008 +0100 @@ -0,0 +1,212 @@ +/++ + Author: Aziz Köksal + License: GPL3 ++/ +module cmd.Statistics; + +import cmd.ASTStats; +import dil.lexer.Lexer; +import dil.lexer.Token; +import dil.parser.Parser; +import dil.ast.NodesEnum; +import dil.SourceText; +import common; + +/// A group of statistics variables. +struct Statistics +{ + uint whitespaceCount; /// Counter for whitespace characters. + uint wsTokenCount; /// Counter for all whitespace tokens. + uint keywordCount; /// Counter for keywords. + uint identCount; /// Counter for identifiers. + uint numberCount; /// Counter for number literals. + uint commentCount; /// Counter for comments. + uint tokenCount; /// Counter for all tokens produced by the Lexer. + uint linesOfCode; /// Number of lines. + uint[] tokensTable; /// Table of counters for all token kinds. + uint[] nodesTable; /// Table of counters for all node kinds. + + static Statistics opCall(bool allocateTokensTable, bool allocateNodesTable = false) + { + Statistics s; + if (allocateTokensTable) + s.tokensTable = new uint[TOK.MAX]; + if (allocateNodesTable) + s.nodesTable = new uint[g_classNames.length]; + return s; + } + + void opAddAssign(Statistics s) + { + this.whitespaceCount += s.whitespaceCount; + this.wsTokenCount += s.wsTokenCount; + this.keywordCount += s.keywordCount; + this.identCount += s.identCount; + this.numberCount += s.numberCount; + this.commentCount += s.commentCount; + this.tokenCount += s.tokenCount; + this.linesOfCode += s.linesOfCode; + foreach (i, count; s.tokensTable) + this.tokensTable[i] += count; + foreach (i, count; s.nodesTable) + this.nodesTable[i] += count; + } +} + +/// Executes the statistics command. +void execute(string[] filePaths, bool printTokensTable, bool printNodesTable) +{ + Statistics[] stats; + foreach (filePath; filePaths) + stats ~= getStatistics(filePath, printTokensTable, printNodesTable); + + auto total = Statistics(printTokensTable, printNodesTable); + + foreach (i, ref stat; stats) + { + total += stat; + Stdout.formatln( + "----\n" + "File: {}\n" + "Whitespace character count: {}\n" + "Whitespace token count: {}\n" + "Keyword count: {}\n" + "Identifier count: {}\n" + "Number count: {}\n" + "Comment count: {}\n" + "All tokens count: {}\n" + "Lines of code: {}", + filePaths[i], + stat.whitespaceCount, + stat.wsTokenCount, + stat.keywordCount, + stat.identCount, + stat.numberCount, + stat.commentCount, + stat.tokenCount, + stat.linesOfCode + ); + } + + if (filePaths.length > 1) + { + Stdout.formatln( + "--------------------------------------------------------------------------------\n" + "Total of {} files:\n" + "Whitespace character count: {}\n" + "Whitespace token count: {}\n" + "Keyword count: {}\n" + "Identifier count: {}\n" + "Number count: {}\n" + "Comment count: {}\n" + "All tokens count: {}\n" + "Lines of code: {}", + filePaths.length, + total.whitespaceCount, + total.wsTokenCount, + total.keywordCount, + total.identCount, + total.numberCount, + total.commentCount, + total.tokenCount, + total.linesOfCode + ); + } + + if (printTokensTable) + { + Stdout("Table of tokens:").newline; + Stdout.formatln(" {,10} | {}", "Count", "Token kind"); + Stdout("-----------------------------").newline; + foreach (i, count; total.tokensTable) + Stdout.formatln(" {,10} | {}", count, Token.toString(cast(TOK)i)); + Stdout("// End of tokens table.").newline; + } + + if(printNodesTable) + { + Stdout("Table of nodes:").newline; + Stdout.formatln(" {,10} | {}", "Count", "Node kind"); + Stdout("-----------------------------").newline; + foreach (i, count; total.nodesTable) + Stdout.formatln(" {,10} | {}", count, g_classNames[i]); + Stdout("// End of nodes table.").newline; + } +} + +/// Returns the statistics for a D source file. +Statistics getStatistics(string filePath, bool printTokensTable, bool printNodesTable) +{ + // Create a new record. + auto stats = Statistics(printTokensTable); + + auto sourceText = new SourceText(filePath, true); + Parser parser; + Lexer lx; + if (printNodesTable) + { + parser = new Parser(sourceText); + auto rootNode = parser.start(); + // Count nodes. + stats.nodesTable = (new ASTStats).count(rootNode); + lx = parser.lexer; + } + else + { + lx = new Lexer(sourceText); + lx.scanAll(); + } + + auto token = lx.firstToken(); + + // Count tokens. + // Lexer creates HEAD + Newline, which are not in the source text. + // No token left behind! + stats.tokenCount = 2; + stats.linesOfCode = lx.lineNum; + if (printTokensTable) + { + stats.tokensTable[TOK.HEAD] = 1; + stats.tokensTable[TOK.Newline] = 1; + } + // Traverse linked list. + while (1) + { + stats.tokenCount += 1; + + if (printTokensTable) + stats.tokensTable[token.kind] += 1; + + // Count whitespace characters + if (token.ws !is null) + stats.whitespaceCount += token.start - token.ws; + + switch (token.kind) + { + case TOK.Identifier: + stats.identCount++; + break; + case TOK.Comment: + stats.commentCount++; + break; + case TOK.Int32, TOK.Int64, TOK.Uint32, TOK.Uint64, + TOK.Float32, TOK.Float64, TOK.Float80, + TOK.Imaginary32, TOK.Imaginary64, TOK.Imaginary80: + stats.numberCount++; + break; + case TOK.Newline: + break; + default: + if (token.isKeyword) + stats.keywordCount++; + else if (token.isWhitespace) + stats.wsTokenCount++; + } + + if (token.next is null) + break; + token = token.next; + } + assert(token.kind == TOK.EOF); + return stats; +}