diff options
1 files changed, 95 insertions, 0 deletions
| -rw-r--r-- | homework/81568/c2html/cyclomatic.cpp | 95 |
diff --git a/homework/81568/c2html/cyclomatic.cpp b/homework/81568/c2html/cyclomatic.cpp new file mode 100644 index 0000000..b7b0c17 --- /dev/null +++ b/homework/81568/c2html/cyclomatic.cpp @@ -0,0 +1,95 @@ +#include "cyclomatic.h" +#include "html_utils.h" +#include "lexcer.h" +#include "lexconst.h" +#include <stack> + +using HTMLUtils::writeToOutput; +using LexCer::TokenClass; +using LexCer::Tokenizer; + +// Writing a full parser would give us the change of +// making the cyclomatic graph of the function. +// #courseproject +unsigned ParCer::outputWithCyclomaticComplexity(FILE *in, FILE *out) { + Tokenizer tokenizer (in, out); + + std::string lexeme; + double number; + TokenClass type; + Token currentToken; + std::stack<short> history; + bool inFunction = false; + + #define PAREN false + std::stack<bool> openedBlocks; + std::string className = "a"; + unsigned counter = 1; + unsigned complexity = 1; + + do { + currentToken = tokenizer.nextToken(&lexeme, &number); + type = currentToken.type; + + if (!inFunction) { + history.push(type); + } else { + if (type == TokenClass::RightCurly) { + if (openedBlocks.empty()) { // end of a function. What one does to avoid parsing 'C' + inFunction = false; + fputs("<!-- ", out); + char closingDiv[100]; + sprintf(closingDiv, "%d --></div>", complexity); + fputs(closingDiv, out); + complexity = 1; + } else { + openedBlocks.pop(); + } + } + else if (type == TokenClass::LeftCurly) { + openedBlocks.push(PAREN); + } + else if (type == TokenClass::Keyword) { + if (!lexeme.compare("if") || + !lexeme.compare("while") || + !lexeme.compare("for") || + !lexeme.compare("case") || + !lexeme.compare("default")) + { + ++complexity; + } + } + } + + if (!inFunction && type == TokenClass::LeftCurly) { + history.pop(); + while (!history.empty() && history.top() == TokenClass::Skip) { + history.pop(); + } + + if (history.top() == TokenClass::RightParen) { + while (!history.empty() && history.top() != TokenClass::LeftParen) + history.pop(); + if (!history.empty()) + history.pop(); + while (!history.empty() && history.top() == TokenClass::Skip) + history.pop(); + + if (!history.empty() && history.top() == TokenClass::Identifier) { // We are in a function + char openingDiv[100]; + sprintf(openingDiv, "<div class=\"func\">", className.c_str()); + fputs(openingDiv, out); + inFunction = true; + history = std::stack<short>{}; + } + } + } + + if (!writeToOutput(out, currentToken)) + break; + lexeme = ""; + number = 0.0; + } while (type != TokenClass::Eof || + type != TokenClass::Invalid); + return counter - 1; +} |
